1 /* 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 11 #ifndef WEBRTC_MODULES_DESKTOP_CAPTURE_DESKTOP_REGION_H_ 12 #define WEBRTC_MODULES_DESKTOP_CAPTURE_DESKTOP_REGION_H_ 13 14 #include <map> 15 #include <vector> 16 17 #include "webrtc/base/constructormagic.h" 18 #include "webrtc/modules/desktop_capture/desktop_geometry.h" 19 #include "webrtc/typedefs.h" 20 21 namespace webrtc { 22 23 // DesktopRegion represents a region of the screen or window. 24 // 25 // Internally each region is stored as a set of rows where each row contains one 26 // or more rectangles aligned vertically. 27 class DesktopRegion { 28 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 { 50 Row(int32_t top, int32_t bottom); 51 ~Row(); 52 53 int32_t top; 54 int32_t bottom; 55 56 RowSpanSet spans; 57 }; 58 59 // Type used to store list of rows in the region. The bottom position of row 60 // is used as the key so that rows are always ordered by their position. The 61 // map stores pointers to make Translate() more efficient. 62 typedef std::map<int, Row*> Rows; 63 64 public: 65 // Iterator that can be used to iterate over rectangles of a DesktopRegion. 66 // The region must not be mutated while the iterator is used. 67 class Iterator { 68 public: 69 explicit Iterator(const DesktopRegion& target); 70 71 bool IsAtEnd() const; 72 void Advance(); 73 rect()74 const DesktopRect& rect() const { return rect_; } 75 76 private: 77 const DesktopRegion& region_; 78 79 // Updates |rect_| based on the current |row_| and |row_span_|. If 80 // |row_span_| matches spans on consecutive rows then they are also merged 81 // into |rect_|, to generate more efficient output. 82 void UpdateCurrentRect(); 83 84 Rows::const_iterator row_; 85 Rows::const_iterator previous_row_; 86 RowSpanSet::const_iterator row_span_; 87 DesktopRect rect_; 88 }; 89 90 DesktopRegion(); 91 explicit DesktopRegion(const DesktopRect& rect); 92 DesktopRegion(const DesktopRect* rects, int count); 93 DesktopRegion(const DesktopRegion& other); 94 ~DesktopRegion(); 95 96 DesktopRegion& operator=(const DesktopRegion& other); 97 is_empty()98 bool is_empty() const { return rows_.empty(); } 99 100 bool Equals(const DesktopRegion& region) const; 101 102 // Reset the region to be empty. 103 void Clear(); 104 105 // Reset region to contain just |rect|. 106 void SetRect(const DesktopRect& rect); 107 108 // Adds specified rect(s) or region to the region. 109 void AddRect(const DesktopRect& rect); 110 void AddRects(const DesktopRect* rects, int count); 111 void AddRegion(const DesktopRegion& region); 112 113 // Finds intersection of two regions and stores them in the current region. 114 void Intersect(const DesktopRegion& region1, const DesktopRegion& region2); 115 116 // Same as above but intersects content of the current region with |region|. 117 void IntersectWith(const DesktopRegion& region); 118 119 // Clips the region by the |rect|. 120 void IntersectWith(const DesktopRect& rect); 121 122 // Subtracts |region| from the current content of the region. 123 void Subtract(const DesktopRegion& region); 124 125 // Subtracts |rect| from the current content of the region. 126 void Subtract(const DesktopRect& rect); 127 128 // Adds (dx, dy) to the position of the region. 129 void Translate(int32_t dx, int32_t dy); 130 131 void Swap(DesktopRegion* region); 132 133 private: 134 // Comparison functions used for std::lower_bound(). Compare left or right 135 // edges withs a given |value|. 136 static bool CompareSpanLeft(const RowSpan& r, int32_t value); 137 static bool CompareSpanRight(const RowSpan& r, int32_t value); 138 139 // Adds a new span to the row, coalescing spans if necessary. 140 static void AddSpanToRow(Row* row, int32_t left, int32_t right); 141 142 // Returns true if the |span| exists in the given |row|. 143 static bool IsSpanInRow(const Row& row, const RowSpan& rect); 144 145 // Calculates the intersection of two sets of spans. 146 static void IntersectRows(const RowSpanSet& set1, 147 const RowSpanSet& set2, 148 RowSpanSet* output); 149 150 static void SubtractRows(const RowSpanSet& set_a, 151 const RowSpanSet& set_b, 152 RowSpanSet* output); 153 154 // Merges |row| with the row above it if they contain the same spans. Doesn't 155 // do anything if called with |row| set to rows_.begin() (i.e. first row of 156 // the region). If the rows were merged |row| remains a valid iterator to the 157 // merged row. 158 void MergeWithPrecedingRow(Rows::iterator row); 159 160 Rows rows_; 161 }; 162 163 } // namespace webrtc 164 165 #endif // WEBRTC_MODULES_DESKTOP_CAPTURE_DESKTOP_REGION_H_ 166 167