blob: ae9d8a0ba9c20a23e7f527864ece62c9361d9ce7 [file] [log] [blame] [edit]
/*
* 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 <stdint.h>
#include <map>
#include <vector>
#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<RowSpan> 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<int, Row*> 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_