/* * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #ifndef MODULES_DESKTOP_CAPTURE_DESKTOP_REGION_H_ #define MODULES_DESKTOP_CAPTURE_DESKTOP_REGION_H_ #include #include #include #include "modules/desktop_capture/desktop_geometry.h" #include "rtc_base/system/rtc_export.h" namespace webrtc { // DesktopRegion represents a region of the screen or window. // // Internally each region is stored as a set of rows where each row contains one // or more rectangles aligned vertically. class RTC_EXPORT DesktopRegion { private: // The following private types need to be declared first because they are used // in the public Iterator. // RowSpan represents a horizontal span withing a single row. struct RowSpan { RowSpan(int32_t left, int32_t right); // Used by std::vector<>. bool operator==(const RowSpan& that) const { return left == that.left && right == that.right; } int32_t left; int32_t right; }; typedef std::vector RowSpanSet; // Row represents a single row of a region. A row is set of rectangles that // have the same vertical position. struct Row { Row(const Row&); Row(Row&&); Row(int32_t top, int32_t bottom); ~Row(); int32_t top; int32_t bottom; RowSpanSet spans; }; // Type used to store list of rows in the region. The bottom position of row // is used as the key so that rows are always ordered by their position. The // map stores pointers to make Translate() more efficient. typedef std::map Rows; public: // Iterator that can be used to iterate over rectangles of a DesktopRegion. // The region must not be mutated while the iterator is used. class RTC_EXPORT Iterator { public: explicit Iterator(const DesktopRegion& target); ~Iterator(); bool IsAtEnd() const; void Advance(); const DesktopRect& rect() const { return rect_; } private: const DesktopRegion& region_; // Updates `rect_` based on the current `row_` and `row_span_`. If // `row_span_` matches spans on consecutive rows then they are also merged // into `rect_`, to generate more efficient output. void UpdateCurrentRect(); Rows::const_iterator row_; Rows::const_iterator previous_row_; RowSpanSet::const_iterator row_span_; DesktopRect rect_; }; DesktopRegion(); explicit DesktopRegion(const DesktopRect& rect); DesktopRegion(const DesktopRect* rects, int count); DesktopRegion(const DesktopRegion& other); ~DesktopRegion(); DesktopRegion& operator=(const DesktopRegion& other); bool is_empty() const { return rows_.empty(); } bool Equals(const DesktopRegion& region) const; // Reset the region to be empty. void Clear(); // Reset region to contain just `rect`. void SetRect(const DesktopRect& rect); // Adds specified rect(s) or region to the region. void AddRect(const DesktopRect& rect); void AddRects(const DesktopRect* rects, int count); void AddRegion(const DesktopRegion& region); // Finds intersection of two regions and stores them in the current region. void Intersect(const DesktopRegion& region1, const DesktopRegion& region2); // Same as above but intersects content of the current region with `region`. void IntersectWith(const DesktopRegion& region); // Clips the region by the `rect`. void IntersectWith(const DesktopRect& rect); // Subtracts `region` from the current content of the region. void Subtract(const DesktopRegion& region); // Subtracts `rect` from the current content of the region. void Subtract(const DesktopRect& rect); // Adds (dx, dy) to the position of the region. void Translate(int32_t dx, int32_t dy); void Swap(DesktopRegion* region); private: // Comparison functions used for std::lower_bound(). Compare left or right // edges withs a given `value`. static bool CompareSpanLeft(const RowSpan& r, int32_t value); static bool CompareSpanRight(const RowSpan& r, int32_t value); // Adds a new span to the row, coalescing spans if necessary. static void AddSpanToRow(Row* row, int32_t left, int32_t right); // Returns true if the `span` exists in the given `row`. static bool IsSpanInRow(const Row& row, const RowSpan& rect); // Calculates the intersection of two sets of spans. static void IntersectRows(const RowSpanSet& set1, const RowSpanSet& set2, RowSpanSet* output); static void SubtractRows(const RowSpanSet& set_a, const RowSpanSet& set_b, RowSpanSet* output); // Merges `row` with the row above it if they contain the same spans. Doesn't // do anything if called with `row` set to rows_.begin() (i.e. first row of // the region). If the rows were merged `row` remains a valid iterator to the // merged row. void MergeWithPrecedingRow(Rows::iterator row); Rows rows_; }; } // namespace webrtc #endif // MODULES_DESKTOP_CAPTURE_DESKTOP_REGION_H_