blob: 93f78a4c0c75fd21b36b93150ce2a90e9e9019b9 [file] [log] [blame]
sergeyu@chromium.org15e32cc2013-04-29 20:10:57 +00001/*
2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#ifndef MODULES_DESKTOP_CAPTURE_DESKTOP_REGION_H_
12#define MODULES_DESKTOP_CAPTURE_DESKTOP_REGION_H_
sergeyu@chromium.org15e32cc2013-04-29 20:10:57 +000013
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +000014#include <map>
sergeyu@chromium.org15e32cc2013-04-29 20:10:57 +000015#include <vector>
16
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020017#include "modules/desktop_capture/desktop_geometry.h"
18#include "rtc_base/constructormagic.h"
Mirko Bonadei71207422017-09-15 13:58:09 +020019#include "typedefs.h" // NOLINT(build/include)
sergeyu@chromium.org15e32cc2013-04-29 20:10:57 +000020
21namespace webrtc {
22
23// DesktopRegion represents a region of the screen or window.
24//
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +000025// Internally each region is stored as a set of rows where each row contains one
26// or more rectangles aligned vertically.
sergeyu@chromium.org15e32cc2013-04-29 20:10:57 +000027class DesktopRegion {
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +000028 private:
29 // The following private types need to be declared first because they are used
30 // in the public Iterator.
31
32 // RowSpan represents a horizontal span withing a single row.
33 struct RowSpan {
34 RowSpan(int32_t left, int32_t right);
35
36 // Used by std::vector<>.
37 bool operator==(const RowSpan& that) const {
38 return left == that.left && right == that.right;
39 }
40
41 int32_t left;
42 int32_t right;
43 };
44
45 typedef std::vector<RowSpan> RowSpanSet;
46
47 // Row represents a single row of a region. A row is set of rectangles that
48 // have the same vertical position.
49 struct Row {
kjellander470dd372016-04-19 03:03:23 -070050 Row(const Row&);
kwiberg4fb3d2b2016-04-22 04:59:31 -070051 Row(Row&&);
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +000052 Row(int32_t top, int32_t bottom);
pbos@webrtc.orge7242842013-07-31 15:32:43 +000053 ~Row();
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +000054
55 int32_t top;
56 int32_t bottom;
57
58 RowSpanSet spans;
59 };
60
61 // Type used to store list of rows in the region. The bottom position of row
62 // is used as the key so that rows are always ordered by their position. The
63 // map stores pointers to make Translate() more efficient.
64 typedef std::map<int, Row*> Rows;
65
sergeyu@chromium.org15e32cc2013-04-29 20:10:57 +000066 public:
67 // Iterator that can be used to iterate over rectangles of a DesktopRegion.
68 // The region must not be mutated while the iterator is used.
69 class Iterator {
70 public:
71 explicit Iterator(const DesktopRegion& target);
Sergey Ulanov098c1de2015-09-01 11:36:40 -070072 ~Iterator();
sergeyu@chromium.org15e32cc2013-04-29 20:10:57 +000073
74 bool IsAtEnd() const;
75 void Advance();
76
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +000077 const DesktopRect& rect() const { return rect_; }
sergeyu@chromium.org15e32cc2013-04-29 20:10:57 +000078
79 private:
80 const DesktopRegion& region_;
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +000081
82 // Updates |rect_| based on the current |row_| and |row_span_|. If
83 // |row_span_| matches spans on consecutive rows then they are also merged
84 // into |rect_|, to generate more efficient output.
85 void UpdateCurrentRect();
86
87 Rows::const_iterator row_;
88 Rows::const_iterator previous_row_;
89 RowSpanSet::const_iterator row_span_;
90 DesktopRect rect_;
sergeyu@chromium.org15e32cc2013-04-29 20:10:57 +000091 };
92
93 DesktopRegion();
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +000094 explicit DesktopRegion(const DesktopRect& rect);
95 DesktopRegion(const DesktopRect* rects, int count);
sergeyu@chromium.org15e32cc2013-04-29 20:10:57 +000096 DesktopRegion(const DesktopRegion& other);
97 ~DesktopRegion();
98
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +000099 DesktopRegion& operator=(const DesktopRegion& other);
sergeyu@chromium.org15e32cc2013-04-29 20:10:57 +0000100
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +0000101 bool is_empty() const { return rows_.empty(); }
102
103 bool Equals(const DesktopRegion& region) const;
104
105 // Reset the region to be empty.
sergeyu@chromium.org15e32cc2013-04-29 20:10:57 +0000106 void Clear();
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +0000107
108 // Reset region to contain just |rect|.
sergeyu@chromium.org15e32cc2013-04-29 20:10:57 +0000109 void SetRect(const DesktopRect& rect);
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +0000110
111 // Adds specified rect(s) or region to the region.
sergeyu@chromium.org15e32cc2013-04-29 20:10:57 +0000112 void AddRect(const DesktopRect& rect);
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +0000113 void AddRects(const DesktopRect* rects, int count);
sergeyu@chromium.org15e32cc2013-04-29 20:10:57 +0000114 void AddRegion(const DesktopRegion& region);
115
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +0000116 // Finds intersection of two regions and stores them in the current region.
117 void Intersect(const DesktopRegion& region1, const DesktopRegion& region2);
118
119 // Same as above but intersects content of the current region with |region|.
120 void IntersectWith(const DesktopRegion& region);
121
sergeyu@chromium.org15e32cc2013-04-29 20:10:57 +0000122 // Clips the region by the |rect|.
123 void IntersectWith(const DesktopRect& rect);
124
sergeyu@chromium.org6ab45b92013-09-13 19:53:16 +0000125 // Subtracts |region| from the current content of the region.
126 void Subtract(const DesktopRegion& region);
127
128 // Subtracts |rect| from the current content of the region.
129 void Subtract(const DesktopRect& rect);
130
sergeyu@chromium.org15e32cc2013-04-29 20:10:57 +0000131 // Adds (dx, dy) to the position of the region.
132 void Translate(int32_t dx, int32_t dy);
133
134 void Swap(DesktopRegion* region);
135
136 private:
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +0000137 // Comparison functions used for std::lower_bound(). Compare left or right
138 // edges withs a given |value|.
139 static bool CompareSpanLeft(const RowSpan& r, int32_t value);
140 static bool CompareSpanRight(const RowSpan& r, int32_t value);
141
142 // Adds a new span to the row, coalescing spans if necessary.
143 static void AddSpanToRow(Row* row, int32_t left, int32_t right);
144
145 // Returns true if the |span| exists in the given |row|.
146 static bool IsSpanInRow(const Row& row, const RowSpan& rect);
147
148 // Calculates the intersection of two sets of spans.
149 static void IntersectRows(const RowSpanSet& set1,
150 const RowSpanSet& set2,
151 RowSpanSet* output);
152
sergeyu@chromium.org6ab45b92013-09-13 19:53:16 +0000153 static void SubtractRows(const RowSpanSet& set_a,
154 const RowSpanSet& set_b,
155 RowSpanSet* output);
156
sergeyu@chromium.org3ee13e42013-06-04 00:38:39 +0000157 // Merges |row| with the row above it if they contain the same spans. Doesn't
158 // do anything if called with |row| set to rows_.begin() (i.e. first row of
159 // the region). If the rows were merged |row| remains a valid iterator to the
160 // merged row.
161 void MergeWithPrecedingRow(Rows::iterator row);
162
163 Rows rows_;
sergeyu@chromium.org15e32cc2013-04-29 20:10:57 +0000164};
165
166} // namespace webrtc
167
Mirko Bonadei92ea95e2017-09-15 06:47:31 +0200168#endif // MODULES_DESKTOP_CAPTURE_DESKTOP_REGION_H_
sergeyu@chromium.org15e32cc2013-04-29 20:10:57 +0000169