blob: b664e2745dfd3ae9f94ac3fbb622efa041924a98 [file] [log] [blame]
#Topic Region
#Alias Region_Reference ##
#Alias Regions ##
Region is a compressed one bit mask. Region describes an aliased clipping area
on integer boundaries. Region can also describe an array of integer rectangles.
Canvas uses Region to reduce the current clip. Region may be drawn to Canvas;
Paint determines if Region is filled or stroked, its Color, and so on.
Region may be constructed from IRect array or Path. Diagonal lines and curves
in Path become integer rectangle edges. Regions operators compute union,
intersection, difference, and so on. Canvas allows only intersection and
difference; successive clips can only reduce available Canvas area.
#PhraseDef list_of_op_types
kDifference_Op, kIntersect_Op, kUnion_Op, kXOR_Op, kReverseDifference_Op,
kReplace_Op
##
#Class SkRegion
SkRegion describes the set of pixels used to clip Canvas. SkRegion is compact,
efficiently storing a single integer rectangle, or a run length encoded array
of rectangles. SkRegion may reduce the current Canvas_Clip, or may be drawn as
one or more integer rectangles. SkRegion iterator returns the scan lines or
rectangles contained by it, optionally intersecting a bounding rectangle.
#Subtopic Overview
#Populate
##
#Subtopic Constant
#Populate
##
#Subtopic Class
#Populate
##
#Subtopic Constructor
#Populate
##
#Subtopic Operator
#Populate
##
#Subtopic Member_Function
#Populate
##
# ------------------------------------------------------------------------------
#Class Iterator
#Line # iterator returning IRect ##
#Code
class Iterator {
public:
Iterator();
Iterator(const SkRegion& region);
bool rewind();
void reset(const SkRegion& region);
bool done() const;
void next();
const SkIRect& rect();
const SkRegion* rgn();
};
##
Returns sequence of rectangles, sorted along y-axis, then x-axis, that make
up Region.
# ------------------------------------------------------------------------------
#Method Iterator()
#Line # constructs Region iterator ##
Initializes Iterator with an empty Region. done() on Iterator returns true.
Call reset() to initialized Iterator at a later time.
#Return empty Region ierator ##
#Example
SkRegion::Iterator iter;
SkRegion region;
region.setRect({1, 2, 3, 4});
iter.reset(region);
auto r = iter.rect();
SkDebugf("rect={%d,%d,%d,%d}\n", r.fLeft, r.fTop, r.fRight, r.fBottom);
#StdOut
rect={1,2,3,4}
##
##
#SeeAlso reset SkRegion
#Method ##
# ------------------------------------------------------------------------------
#Method Iterator(const SkRegion& region)
#Line # constructs Region iterator ##
Sets Iterator to return elements of IRect array in region.
#Param region Region to iterate ##
#Return Region iterator ##
#Example
SkRegion region;
region.setRect({1, 2, 3, 4});
SkRegion::Iterator iter(region);
auto r = iter.rect();
SkDebugf("rect={%d,%d,%d,%d}\n", r.fLeft, r.fTop, r.fRight, r.fBottom);
#StdOut
rect={1,2,3,4}
##
##
#SeeAlso reset SkRegion Cliperator Spanerator
#Method ##
# ------------------------------------------------------------------------------
#Method bool rewind()
#Line # points Iterator to start ##
Points Iterator to start of Region.
Returns true if Region was set; otherwise, returns false.
#Return true if Region was set ##
#Example
#Bug 8186
auto debugster = [](const char* label, SkRegion::Iterator& iter, bool addRewind) -> void {
if (addRewind) {
bool success = iter.rewind();
SkDebugf("%14s rewind success=%s\n", label, success ? "true" : "false");
}
auto r = iter.rect();
SkDebugf("%14s rect={%d,%d,%d,%d}\n", label, r.fLeft, r.fTop, r.fRight, r.fBottom);
};
SkRegion::Iterator iter;
debugster("empty iter", iter, true);
SkRegion region;
iter.reset(region);
debugster("empty region", iter, true);
region.setRect({1, 2, 3, 4});
iter.reset(region);
debugster("after set rect", iter, false);
debugster("after rewind", iter, true);
#StdOut
#Volatile
empty iter rewind success=false
empty iter rect={0,0,0,0}
empty region rewind success=true
empty region rect={0,0,0,0}
after set rect rect={1,2,3,4}
after rewind rewind success=true
after rewind rect={1,2,3,4}
##
##
#SeeAlso reset
#Method ##
# ------------------------------------------------------------------------------
#Method void reset(const SkRegion& region)
#Line # sets Region to iterate ##
Resets iterator, using the new Region.
#Param region Region to iterate ##
#Example
auto debugster = [](const char* label, SkRegion::Iterator& iter) -> void {
SkDebugf("%14s: done=%s\n", label, iter.done() ? "true" : "false");
};
SkRegion region;
SkRegion::Iterator iter(region);
debugster("empty region", iter);
region.setRect({1, 2, 3, 4});
debugster("after set rect", iter);
iter.reset(region);
debugster("after reset", iter);
#StdOut
empty region: done=true
after set rect: done=true
after reset: done=false
##
##
#SeeAlso rewind
#Method ##
# ------------------------------------------------------------------------------
#Method bool done() const
#Line # returns if data parsing is complete ##
Returns true if Iterator is pointing to final IRect in Region.
#Return true if data parsing is complete ##
#Example
SkRegion region;
SkRegion::Iterator iter(region);
SkDebugf("done=%s\n", iter.done() ? "true" : "false");
region.setRect({1, 2, 3, 4});
iter.rewind();
SkDebugf("done=%s\n", iter.done() ? "true" : "false");
#StdOut
done=true
done=false
##
##
#SeeAlso next rect
#Method ##
# ------------------------------------------------------------------------------
#Method void next()
#Line # advances to next IRect ##
Advances Iterator to next IRect in Region if it is not done.
#Example
SkRegion region;
SkIRect rects[] = {{1, 2, 3, 4}, {5, 6, 7, 8}};
region.setRects(rects, SK_ARRAY_COUNT(rects));
SkRegion::Iterator iter(region);
do {
auto r2 = iter.rect();
SkDebugf("rect={%d,%d,%d,%d}\n", r2.fLeft, r2.fTop, r2.fRight, r2.fBottom);
iter.next();
} while (!iter.done());
#StdOut
rect={1,2,3,4}
rect={5,6,7,8}
##
##
#SeeAlso done rect
#Method ##
# ------------------------------------------------------------------------------
#Method const SkIRect& rect() const
#Line # returns part of Region as IRect ##
Returns IRect element in Region. Does not return predictable results if Region
is empty.
#Return part of Region as IRect ##
#Example
#Bug 8186
SkRegion region;
SkRegion::Iterator iter(region);
auto r1 = iter.rect();
SkDebugf("rect={%d,%d,%d,%d}\n", r1.fLeft, r1.fTop, r1.fRight, r1.fBottom);
region.setRect({1, 2, 3, 4});
iter.rewind();
auto r2 = iter.rect();
SkDebugf("rect={%d,%d,%d,%d}\n", r2.fLeft, r2.fTop, r2.fRight, r2.fBottom);
#StdOut
#Volatile
rect={0,0,0,0}
rect={1,2,3,4}
##
##
#SeeAlso next done
#Method ##
# ------------------------------------------------------------------------------
#Method const SkRegion* rgn() const
#Line # returns original Region ##
Returns Region if set; otherwise, returns nullptr.
#Return iterated Region ##
#Example
SkRegion region;
SkIRect rects[] = {{1, 2, 3, 4}, {3, 4, 5, 6}};
region.setRects(rects, SK_ARRAY_COUNT(rects));
SkRegion::Iterator iter(region);
auto r = iter.rect();
SkDebugf("rect={%d,%d,%d,%d}\n", r.fLeft, r.fTop, r.fRight, r.fBottom);
auto b = iter.rgn()->getBounds();
SkDebugf("bounds={%d,%d,%d,%d}\n", b.fLeft, b.fTop, b.fRight, b.fBottom);
##
#SeeAlso Iterator reset
#Method ##
#Class Iterator ##
# ------------------------------------------------------------------------------
#Class Cliperator
#Line # iterator returning IRect within clip ##
#Code
class SK_API Cliperator {
public:
Cliperator(const SkRegion&, const SkIRect& clip);
bool done();
void next();
const SkIRect& rect() const;
};
##
Returns the sequence of rectangles, sorted along y-axis, then x-axis, that make
up Region intersected with the specified clip rectangle.
# ------------------------------------------------------------------------------
#Method Cliperator(const SkRegion& region, const SkIRect& clip)
#Line # constructs Region iterator with clip ##
Sets Cliperator to return elements of IRect array in Region within clip.
#Param region Region to iterate ##
#Param clip bounds of iteration ##
#Return Region iterator ##
#Example
SkRegion region;
region.setRect({1, 2, 3, 4});
SkRegion::Cliperator clipper(region, {0, 0, 2, 3});
auto r = clipper.rect();
SkDebugf("rect={%d,%d,%d,%d}\n", r.fLeft, r.fTop, r.fRight, r.fBottom);
#StdOut
rect={1,2,2,3}
##
##
#SeeAlso SkRegion Iterator Spanerator
#Method ##
# ------------------------------------------------------------------------------
#Method bool done()
#Line # returns if data parsing is complete ##
Returns true if Cliperator is pointing to final IRect in Region.
#Return true if data parsing is complete ##
#Example
auto debugster = [](const char* label, SkRegion& region) -> void {
SkRegion::Cliperator clipper(region, {0, 0, 5, 5});
SkDebugf("%14s done=%s\n", label, clipper.done() ? "true" : "false");
};
SkRegion region;
debugster("empty region", region);
region.setRect({1, 2, 3, 4});
debugster("after add rect", region);
#StdOut
empty region done=true
after add rect done=false
##
##
#SeeAlso next rect
#Method ##
# ------------------------------------------------------------------------------
#Method void next()
#Line # advances to next IRect within clip ##
Advances iterator to next IRect in Region contained by clip.
#Example
SkRegion region;
SkIRect rects[] = {{1, 2, 3, 4}, {5, 6, 7, 8}};
region.setRects(rects, SK_ARRAY_COUNT(rects));
SkRegion::Cliperator clipper(region, {0, 3, 8, 7});
do {
auto r2 = clipper.rect();
SkDebugf("rect={%d,%d,%d,%d}\n", r2.fLeft, r2.fTop, r2.fRight, r2.fBottom);
clipper.next();
} while (!clipper.done());
#StdOut
rect={1,3,3,4}
rect={5,6,7,7}
##
##
#SeeAlso done
#Method ##
# ------------------------------------------------------------------------------
#Method const SkIRect& rect() const
#Line # returns part of Region as IRect intersected with clip ##
Returns IRect element in Region, intersected with clip passed to Cliperator
constructor. Does not return predictable results if Region
is empty.
#Return part of Region inside clip as IRect ##
#Example
#Bug 8186
auto debugster = [](const char* label, SkRegion& region) -> void {
SkRegion::Cliperator clipper(region, {0, 0, 5, 3});
auto r = clipper.rect();
SkDebugf("%14s rect={%d,%d,%d,%d}\n", label, r.fLeft, r.fTop, r.fRight, r.fBottom);
};
SkRegion region;
debugster("empty region", region);
region.setRect({1, 2, 3, 4});
debugster("after set rect", region);
#StdOut
#Volatile
empty region rect={1094713344,1065353216,0,-1}
after set rect rect={1,2,3,3}
##
##
#SeeAlso next done
#Method ##
#Class Cliperator ##
# ------------------------------------------------------------------------------
#Class Spanerator
#Line # horizontal line segment iterator ##
#Code
class Spanerator {
public:
Spanerator(const SkRegion& region, int y, int left, int right);
bool next(int* left, int* right);
};
##
Returns the line segment ends within Region that intersect a horizontal line.
# ------------------------------------------------------------------------------
#Method Spanerator(const SkRegion& region, int y, int left, int right)
#Line # constructs Region iterator on scan line ##
Sets Spanerator to return line segments in Region on scan line.
#Param region Region to iterate ##
#Param y horizontal line to intersect ##
#Param left bounds of iteration ##
#Param right bounds of iteration ##
#Return Region iterator ##
#Example
SkRegion region;
region.setRect({1, 2, 3, 4});
SkRegion::Spanerator spanner(region, 3, 2, 4);
int left, right;
bool result = spanner.next(&left, &right);
SkDebugf("result=%s left=%d right=%d\n", result ? "true" : "false", left, right);
##
#SeeAlso SkRegion Iterator Cliperator
#Method ##
# ------------------------------------------------------------------------------
#Method bool next(int* left, int* right)
#Line # advances to next span on horizontal line ##
Advances iterator to next span intersecting Region within line segment provided
in constructor. Returns true if interval was found.
#Param left pointer to span start; may be nullptr ##
#Param right pointer to span end; may be nullptr ##
#Return true if interval was found ##
#Example
auto debugster = [](const char* label, SkRegion& region) -> void {
SkRegion::Spanerator spanner(region, 3, 2, 4);
int left, right;
bool result = spanner.next(&left, &right);
SkDebugf("%14s: result=%s", label, result ? "true" : "false");
if (result) SkDebugf(" left=%d right=%d", left, right);
SkDebugf("\n");
};
SkRegion region;
debugster("empty region", region);
region.setRect({1, 2, 3, 4});
debugster("after set rect", region);
#StdOut
empty region: result=false
after set rect: result=true left=2 right=3
##
##
#SeeAlso done
#Method ##
#Class Spanerator ##
# ------------------------------------------------------------------------------
#Method SkRegion()
#In Constructor
#Line # constructs with default values ##
Constructs an empty Region. Region is set to empty bounds
at (0, 0) with zero width and height.
#Return empty Region ##
#Example
SkRegion region;
SkIRect r = region.getBounds();
SkDebugf("region bounds: {%d, %d, %d, %d}\n", r.fLeft, r.fTop, r.fRight, r.fBottom);
#StdOut
region bounds: {0, 0, 0, 0}
##
##
#SeeAlso setEmpty
#Method ##
# ------------------------------------------------------------------------------
#Method SkRegion(const SkRegion& region)
#In Constructor
#Line # makes a shallow copy ##
Constructs a copy of an existing region.
Copy constructor makes two regions identical by value. Internally, region and
the returned result share pointer values. The underlying Rect array is
copied when modified.
Creating a Region copy is very efficient and never allocates memory.
Regions are always copied by value from the interface; the underlying shared
pointers are not exposed.
#Param region Region to copy by value ##
#Return copy of Region ##
#Example
auto debugster = [](const char* label, SkRegion& region) -> void {
auto r = region.getBounds();
SkDebugf("%14s: {%d,%d,%d,%d}\n", label, r.fLeft, r.fTop, r.fRight, r.fBottom);
};
SkRegion region({1, 2, 3, 4});
SkRegion region2(region);
debugster("region bounds", region);
debugster("region2 bounds", region2);
region.setEmpty();
SkDebugf(" after region set empty:\n");
debugster("region bounds", region);
debugster("region2 bounds", region2);
#StdOut
region bounds: {1,2,3,4}
region2 bounds: {1,2,3,4}
after region set empty:
region bounds: {0,0,0,0}
region2 bounds: {1,2,3,4}
##
##
#SeeAlso setRegion operator=(const SkRegion& region)
#Method ##
# ------------------------------------------------------------------------------
#Method explicit SkRegion(const SkIRect& rect)
#In Constructor
#Line # constructs Region matching IRect ##
Constructs a rectangular Region matching the bounds of rect.
#Param rect bounds of constructed Region ##
#Return rectangular Region ##
#Example
SkRegion region({1, 2, 3, 4});
SkRegion region2;
region2.setRect({1, 2, 3, 4});
SkDebugf("region %c= region2\n", region == region2 ? '=' : '!');
##
#SeeAlso setRect setRegion
#Method ##
# ------------------------------------------------------------------------------
#Method ~SkRegion()
#In Constructor
#Line # decreases Reference_Count of owned objects ##
Releases ownership of any shared data and deletes data if Region is sole owner.
#Example
#Description
delete calls Region Destructor, but copy of original in region2 is unaffected.
##
SkRegion* region = new SkRegion({1, 2, 3, 4});
SkRegion region2(*region);
delete region;
auto r = region2.getBounds();
SkDebugf("region2 bounds: {%d,%d,%d,%d}\n", r.fLeft, r.fTop, r.fRight, r.fBottom);
#StdOut
region2 bounds: {1,2,3,4}
##
##
#SeeAlso SkRegion() SkRegion(const SkRegion& region) SkRegion(const SkIRect& rect) operator=(const SkRegion& region)
#Method ##
# ------------------------------------------------------------------------------
#Method SkRegion& operator=(const SkRegion& region)
#In Operator
#Line # makes a shallow copy ##
Constructs a copy of an existing region.
Makes two regions identical by value. Internally, region and
the returned result share pointer values. The underlying Rect array is
copied when modified.
Creating a Region copy is very efficient and never allocates memory.
Regions are always copied by value from the interface; the underlying shared
pointers are not exposed.
#Param region Region to copy by value ##
#Return Region to copy by value ##
#Example
auto debugster = [](const char* label, SkRegion& region) -> void {
auto r = region.getBounds();
SkDebugf("%14s: {%d,%d,%d,%d}\n", label, r.fLeft, r.fTop, r.fRight, r.fBottom);
};
SkRegion region1({1, 2, 3, 4});
SkRegion region2 = region1;
debugster("region1 bounds", region1);
debugster("region2 bounds", region2);
#StdOut
region1 bounds: {1,2,3,4}
region2 bounds: {1,2,3,4}
##
##
#SeeAlso set swap SkRegion(const SkRegion& region)
#Method ##
# ------------------------------------------------------------------------------
#Method bool operator==(const SkRegion& other)_const
#In Operator
#Line # compares Regions for equality ##
Compares Region and other; returns true if they enclose exactly
the same area.
#Param other Region to compare ##
#Return true if Region pair are equivalent ##
#Example
auto debugster = [](const char* prefix, const SkRegion& a, const SkRegion& b) -> void {
SkDebugf("%s one %c= two\n", prefix, a == b ? '=' : '!');
};
SkRegion one;
SkRegion two;
debugster("empty", one, two);
one.setRect({1, 2, 3, 4});
debugster("set rect", one, two);
one.setEmpty();
debugster("set empty", one, two);
#StdOut
empty one == two
set rect one != two
set empty one == two
##
##
#SeeAlso operator!=(const SkRegion& other)_const operator=(const SkRegion& region)
#Method ##
# ------------------------------------------------------------------------------
#Method bool operator!=(const SkRegion& other)_const
#In Operator
#Line # compares Regions for inequality ##
Compares Region and other; returns true if they do not enclose the same area.
#Param other Region to compare ##
#Return true if Region pair are not equivalent ##
#Example
auto debugster = [](const char* prefix, const SkRegion& a, const SkRegion& b) -> void {
SkDebugf("%s one %c= two\n", prefix, a != b ? '!' : '=');
};
SkRegion one;
SkRegion two;
debugster("empty", one, two);
one.setRect({1, 2, 3, 4});
two.setRect({1, 2, 3, 3});
debugster("set rect", one, two);
two.op({1, 3, 3, 4}, SkRegion::kUnion_Op);
debugster("union rect", one, two);
#StdOut
empty one == two
set rect one != two
union rect one == two
##
##
#SeeAlso operator==(const SkRegion& other)_const operator=(const SkRegion& region)
#Method ##
# ------------------------------------------------------------------------------
#Method bool set(const SkRegion& src)
#In Constructor
#Line # makes a shallow copy ##
Sets Region to src, and returns true if src bounds is not empty.
This makes Region and src identical by value. Internally,
Region and src share pointer values. The underlying Rect array is
copied when modified.
Creating a Region copy is very efficient and never allocates memory.
Regions are always copied by value from the interface; the underlying shared
pointers are not exposed.
#Param src Region to copy ##
#Return copy of src ##
#Example
auto debugster = [](const char* label, SkRegion& region) -> void {
auto r = region.getBounds();
SkDebugf("%14s: {%d,%d,%d,%d}\n", label, r.fLeft, r.fTop, r.fRight, r.fBottom);
};
SkRegion region1({1, 2, 3, 4});
SkRegion region2;
region2.set(region1);
debugster("region1 bounds", region1);
debugster("region2 bounds", region2);
#StdOut
region1 bounds: {1,2,3,4}
region2 bounds: {1,2,3,4}
##
##
#SeeAlso operator=(const SkRegion& region) swap SkRegion(const SkRegion& region)
#Method ##
# ------------------------------------------------------------------------------
#Method void swap(SkRegion& other)
#In Operator
#Line # exchanges Region pair ##
Exchanges IRect array of Region and other. swap() internally exchanges pointers,
so it is lightweight and does not allocate memory.
swap() usage has largely been replaced by operator=(const SkRegion& region).
Paths do not copy their content on assignment until they are written to,
making assignment as efficient as swap().
#Param other operator=(const SkRegion& region) set ##
#Example
auto debugster = [](const char* label, SkRegion& region) -> void {
auto r = region.getBounds();
SkDebugf("%14s: {%d,%d,%d,%d}\n", label, r.fLeft, r.fTop, r.fRight, r.fBottom);
};
SkRegion region1({1, 2, 3, 4});
SkRegion region2;
region1.swap(region2);
debugster("region1 bounds", region1);
debugster("region2 bounds", region2);
#StdOut
region1 bounds: {0,0,0,0}
region2 bounds: {1,2,3,4}
##
##
#SeeAlso operator=(const SkRegion& region) set SkRegion(const SkRegion& region)
#Method ##
# ------------------------------------------------------------------------------
#Method bool isEmpty() const
#In Property
#Line # returns if bounds has no width or height ##
Returns true if Region is empty.
Empty Region has bounds width or height less than or equal to zero.
SkRegion() constructs empty Region; setEmpty
and setRect with dimensionless data make Region empty.
#Return true if bounds has no width or height ##
#Example
auto debugster = [](const char* label, SkRegion& region) -> void {
SkDebugf("%14s: region is %s" "empty\n", label, region.isEmpty() ? "" : "not ");
};
SkRegion region;
debugster("initial", region);
region.setRect({1, 2, 3, 4});
debugster("set rect", region);
region.setEmpty();
debugster("set empty", region);
#StdOut
initial: region is empty
set rect: region is not empty
set empty: region is empty
##
##
#SeeAlso isRect isComplex operator==(const SkRegion& other)_const
#Method ##
# ------------------------------------------------------------------------------
#Method bool isRect() const
#In Property
#Line # returns if Region contains one IRect ##
Returns true if Region is one IRect with positive dimensions.
#Return true if Region contains one IRect ##
#Example
auto debugster = [](const char* label, const SkRegion& region) -> void {
SkDebugf("%s: region is %s" "rect\n", label, region.isRect() ? "" : "not ");
};
SkRegion region;
debugster("initial", region);
region.setRect({1, 2, 3, 4});
debugster("set rect", region);
region.setEmpty();
debugster("set empty", region);
#StdOut
initial: region is not rect
set rect: region is rect
set empty: region is not rect
##
##
#SeeAlso isEmpty isComplex
#Method ##
# ------------------------------------------------------------------------------
#Method bool isComplex() const
#In Property
#Line # returns true if Region contains more than one IRect ##
Returns true if Region is described by more than one rectangle.
#Return true if Region contains more than one IRect ##
#Example
auto debugster = [](const char* label, const SkRegion& region) -> void {
SkDebugf("%s: region is %s" "complex\n", label, region.isComplex() ? "" : "not ");
};
SkRegion region;
debugster("initial", region);
region.setRect({1, 2, 3, 4});
debugster("set rect", region);
region.op({2, 3, 4, 5}, SkRegion::kUnion_Op);
debugster("op rect", region);
#StdOut
initial: region is not complex
set rect: region is not complex
op rect: region is complex
##
##
#SeeAlso isEmpty isRect
#Method ##
# ------------------------------------------------------------------------------
#Method const SkIRect& getBounds() const
#In Property
#Line # returns maximum and minimum of IRect array ##
Returns minimum and maximum axes values of IRect array.
Returns (0, 0, 0, 0) if Region is empty.
#Return combined bounds of all IRect elements ##
#Example
SkRegion region({1, 2, 3, 4});
region.op({2, 3, 4, 5}, SkRegion::kUnion_Op);
auto r = region.getBounds();
SkDebugf("bounds: {%d,%d,%d,%d}\n", r.fLeft, r.fTop, r.fRight, r.fBottom);
#StdOut
bounds: {1,2,4,5}
##
##
#SeeAlso isEmpty isRect
#Method ##
# ------------------------------------------------------------------------------
#Method int computeRegionComplexity() const
#In Property
#Line # returns relative complexity ##
Returns a value that increases with the number of
elements in Region. Returns zero if Region is empty.
Returns one if Region equals IRect; otherwise, returns
value greater than one indicating that Region is complex.
Call to compare Regions for relative complexity.
#Return relative complexity ##
#Example
auto debugster = [](const char* label, const SkRegion& region) -> void {
SkDebugf("%s: region complexity %d\n", label, region.computeRegionComplexity());
};
SkRegion region;
debugster("initial", region);
region.setRect({1, 2, 3, 4});
debugster("set rect", region);
region.op({2, 3, 4, 5}, SkRegion::kUnion_Op);
debugster("op rect", region);
#StdOut
initial: region complexity 0
set rect: region complexity 1
op rect: region complexity 3
##
##
#SeeAlso isRect isComplex
#Method ##
# ------------------------------------------------------------------------------
#Method bool getBoundaryPath(SkPath* path) const
#In Property
#Line # appends Region outline to Path ##
Appends outline of Region to path.
Returns true if Region is not empty; otherwise, returns false, and leaves path
unmodified.
#Param path Path to append to ##
#Return true if path changed ##
#Example
#Height 100
SkRegion region;
region.setRect({10, 20, 90, 60});
region.op({30, 40, 60, 80}, SkRegion::kXOR_Op);
canvas->drawRegion(region, SkPaint());
SkPath path;
region.getBoundaryPath(&path);
path.offset(100, 0);
canvas->drawPath(path, SkPaint());
##
#SeeAlso isEmpty isComplex
#Method ##
# ------------------------------------------------------------------------------
#Method bool setEmpty()
#In Constructor
#Line # constructs with default values ##
Constructs an empty Region. Region is set to empty bounds
at (0, 0) with zero width and height. Always returns false.
#Return false ##
#Example
auto debugster = [](const char* label, SkRegion& region) -> void {
auto r = region.getBounds();
SkDebugf("%14s: {%d,%d,%d,%d}\n", label, r.fLeft, r.fTop, r.fRight, r.fBottom);
};
SkRegion region({1, 2, 3, 4});
debugster("region bounds", region);
region.setEmpty();
SkDebugf(" after region set empty:\n");
debugster("region bounds", region);
#StdOut
region bounds: {1,2,3,4}
after region set empty:
region bounds: {0,0,0,0}
##
##
#SeeAlso SkRegion()
#Method ##
# ------------------------------------------------------------------------------
#Method bool setRect(const SkIRect& rect)
#In Constructor
#Line # constructs Region matching IRect ##
Constructs a rectangular Region matching the bounds of rect.
If rect is empty, constructs empty and returns false.
#Param rect bounds of constructed Region ##
#Return true if rect is not empty ##
#Example
SkRegion region({1, 2, 3, 4});
SkDebugf("region is %s" "empty\n", region.isEmpty() ? "" : "not ");
bool setEmpty = region.setRect({1, 2, 1, 4});
SkDebugf("region is %s" "empty\n", region.isEmpty() ? "" : "not ");
SkDebugf("setEmpty: %s\n", setEmpty ? "true" : "false");
#StdOut
region is not empty
region is empty
setEmpty: false
##
##
#SeeAlso SkRegion(const SkIRect& rect)
#Method ##
# ------------------------------------------------------------------------------
#Method bool setRect(int32_t left, int32_t top, int32_t right, int32_t bottom)
#In Constructor
#Line # constructs Region matching bounds ##
Constructs Region with bounds (left, top, right, bottom).
Returns true if left is less than right and top is less than bottom; otherwise,
constructs empty Region and returns false.
#Param left edge of bounds on x-axis ##
#Param top edge of bounds on y-axis ##
#Param right edge of bounds on x-axis ##
#Param bottom edge of bounds on y-axis ##
#Return rectangular Region ##
#Example
auto debugster = [](const char* label, bool success, SkRegion& region) -> void {
auto r = region.getBounds();
SkDebugf("%14s: success:%s {%d,%d,%d,%d}\n", label, success ? "true" : "false",
r.fLeft, r.fTop, r.fRight, r.fBottom);
};
SkRegion region;
bool success = region.setRect(1, 2, 3, 4);
debugster("set to: 1,2,3,4", success, region);
success = region.setRect(3, 2, 1, 4);
debugster("set to: 3,2,1,4", success, region);
#StdOut
set to: 1,2,3,4: success:true {1,2,3,4}
set to: 3,2,1,4: success:false {0,0,0,0}
##
##
#SeeAlso SkRegion(const SkIRect& rect)
#Method ##
# ------------------------------------------------------------------------------
#Method bool setRects(const SkIRect rects[], int count)
#In Constructor
#Line # sets IRect array ##
Constructs Region as the union of IRect in rects array. If count is
zero, constructs empty Region. Returns false if constructed Region is empty.
May be faster than repeated calls to op().
#Param rects array of IRects ##
#Param count array size ##
#Return true if constructed Region is not empty ##
#Example
#Height 70
SkIRect rects[] = { {10, 10, 40, 40}, {20, 20, 50, 50}, {30, 30, 60, 60} };
SkRegion region;
region.setRects(rects, SK_ARRAY_COUNT(rects));
canvas->drawRegion(region, SkPaint());
region.setEmpty();
for (auto add : rects) {
region.op(add, SkRegion::kUnion_Op);
}
region.translate(100, 0);
canvas->drawRegion(region, SkPaint());
##
#SeeAlso setRect op
#Method ##
# ------------------------------------------------------------------------------
#Method bool setRegion(const SkRegion& region)
#In Constructor
#Line # copies Region ##
Constructs a copy of an existing region.
Makes two regions identical by value. Internally, region and
the returned result share pointer values. The underlying Rect array is
copied when modified.
Creating a Region copy is very efficient and never allocates memory.
Regions are always copied by value from the interface; the underlying shared
pointers are not exposed.
#Param region Region to copy by value ##
#Return Region to copy by value ##
#Example
auto debugster = [](const char* label, SkRegion& region) -> void {
auto r = region.getBounds();
SkDebugf("%14s: {%d,%d,%d,%d}\n", label, r.fLeft, r.fTop, r.fRight, r.fBottom);
};
SkRegion region({1, 2, 3, 4});
SkRegion region2;
region2.setRegion(region);
debugster("region bounds", region);
debugster("region2 bounds", region2);
region2.setEmpty();
SkDebugf(" after region set empty:\n");
debugster("region bounds", region);
debugster("region2 bounds", region2);
#StdOut
region bounds: {1,2,3,4}
region2 bounds: {1,2,3,4}
after region set empty:
region bounds: {1,2,3,4}
region2 bounds: {0,0,0,0}
##
##
#SeeAlso SkRegion(const SkRegion& region)
#Method ##
# ------------------------------------------------------------------------------
#Method bool setPath(const SkPath& path, const SkRegion& clip)
#In Constructor
#Line # constructs Region from clipped Path ##
Constructs Region to match outline of path within clip.
Returns false if constructed Region is empty.
Constructed Region draws the same pixels as path through clip when
Anti_Aliasing is disabled.
#Param path Path providing outline ##
#Param clip Region containing path ##
#Return true if constructed Region is not empty ##
#Example
#Height 120
SkPaint paint;
paint.setTextSize(128);
SkPath textPath;
paint.getTextPath("Q", 1, 0, 110, &textPath);
SkIRect clipRect = {20, 20, 100, 120};
SkRegion clipRegion(clipRect);
SkRegion region;
region.setPath(textPath, clipRegion);
canvas->drawRegion(region, SkPaint());
clipRect.offset(100, 0);
textPath.offset(100, 0);
canvas->clipRect(SkRect::Make(clipRect), false);
canvas->drawPath(textPath, SkPaint());
##
#SeeAlso setRects op
#Method ##
# ------------------------------------------------------------------------------
#Method bool intersects(const SkIRect& rect) const
#In Intersection
#Line # returns true if areas overlap ##
Returns true if Region intersects rect.
Returns false if either rect or Region is empty, or do not intersect.
#Param rect IRect to intersect ##
#Return true if rect and Region have area in common ##
#Example
#Duration 4
#Height 128
SkPaint paint;
paint.setTextSize(128);
SkPath textPath;
paint.getTextPath("W", 1, 20, 110, &textPath);
SkRegion region;
region.setPath(textPath, SkRegion({0, 0, 256, 256}));
canvas->drawRegion(region, SkPaint());
SkIRect iRect = SkIRect::MakeXYWH(frame * 160, 55, 10, 10);
paint.setColor(region.intersects(iRect) ? SK_ColorBLUE : SK_ColorRED);
canvas->drawRect(SkRect::Make(iRect), paint);
##
#SeeAlso contains SkRect::intersects
#Method ##
# ------------------------------------------------------------------------------
#Method bool intersects(const SkRegion& other) const
Returns true if Region intersects other.
Returns false if either other or Region is empty, or do not intersect.
#Param other Region to intersect ##
#Return true if other and Region have area in common ##
#Example
#Duration 4
#Height 128
SkPaint paint;
paint.setTextSize(128);
SkPath hPath, dotPath;
paint.getTextPath("H", 1, 40, 110, &hPath);
paint.getTextPath(",", 1, frame * 180, 95, &dotPath);
SkRegion hRegion, dotRegion;
hRegion.setPath(hPath, SkRegion({0, 0, 256, 256}));
dotRegion.setPath(dotPath, SkRegion({0, 0, 256, 256}));
canvas->drawRegion(hRegion, paint);
paint.setColor(hRegion.intersects(dotRegion) ? SK_ColorBLUE : SK_ColorRED);
canvas->drawRegion(dotRegion, paint);
##
#SeeAlso contains SkRect::intersects
#Method ##
# ------------------------------------------------------------------------------
#Method bool contains(int32_t x, int32_t y) const
#In Intersection
#Line # returns true if points are equal or inside ##
Returns true if IPoint (x, y) is inside Region.
Returns false if Region is empty.
#Param x test IPoint x-coordinate ##
#Param y test IPoint y-coordinate ##
#Return true if (x, y) is inside Region ##
#Example
#Height 128
SkPaint paint;
paint.setTextSize(128);
SkPath xPath;
paint.getTextPath("X", 1, 20, 110, &xPath);
SkRegion xRegion;
xRegion.setPath(xPath, SkRegion({0, 0, 256, 256}));
canvas->drawRegion(xRegion, paint);
for (int y = 0; y < 128; y += 8) {
for (int x = 0; x < 128; x += 8) {
paint.setColor(xRegion.contains(x, y) ? SK_ColorWHITE : SK_ColorRED);
canvas->drawPoint(x, y, paint);
}
}
##
#SeeAlso intersects SkRect::contains
#Method ##
# ------------------------------------------------------------------------------
#Method bool contains(const SkIRect& other) const
Returns true if other is completely inside Region.
Returns false if Region or other is empty.
#Param other IRect to contain ##
#Return true if other is inside Region ##
#Example
#Height 128
#Duration 4
SkPaint paint;
paint.setTextSize(128);
SkPath xPath;
paint.getTextPath("X", 1, 20, 110, &xPath);
SkRegion xRegion;
SkIRect drawBounds = {0, 0, 128, 128};
xRegion.setPath(xPath, SkRegion(drawBounds));
xRegion.op(drawBounds, SkRegion::kReverseDifference_Op);
canvas->drawRegion(xRegion, paint);
SkIRect test = SkIRect::MakeXYWH(frame* 128, 64, 5, 5);
if (xRegion.contains(test)) {
paint.setColor(SK_ColorYELLOW);
canvas->drawRect(SkRect::Make(test), paint);
}
##
#SeeAlso intersects SkRect::contains
#Method ##
# ------------------------------------------------------------------------------
#Method bool contains(const SkRegion& other) const
Returns true if other is completely inside Region.
Returns false if Region or other is empty.
#Param other Region to contain ##
#Return true if other is inside Region ##
#Example
#Height 128
#Duration 4
SkPaint paint;
paint.setTextSize(128);
SkPath xPath, testPath;
paint.getTextPath("X", 1, 20, 110, &xPath);
paint.getTextPath("`", 1, frame * 150 - 40, 150, &testPath);
SkRegion xRegion, testRegion;
SkIRect drawBounds = {0, 0, 128, 128};
xRegion.setPath(xPath, SkRegion(drawBounds));
testRegion.setPath(testPath, SkRegion(drawBounds));
xRegion.op(drawBounds, SkRegion::kReverseDifference_Op);
canvas->drawRegion(xRegion, paint);
if (xRegion.contains(testRegion)) {
paint.setColor(SK_ColorYELLOW);
canvas->drawRegion(testRegion, paint);
}
##
#SeeAlso intersects SkRect::contains
#Method ##
# ------------------------------------------------------------------------------
#Method bool quickContains(const SkIRect& r) const
#In Intersection
#Line # returns true quickly if points are equal or inside ##
Returns true if Region is a single rectangle and contains r.
May return false even though Region contains r.
#Param r IRect to contain ##
#Return true quickly if r points are equal or inside ##
#Example
SkRegion region({1, 2, 3, 4});
SkIRect test = {2, 2, 3, 3};
SkDebugf("quickContains 1: %s\n", region.quickContains(test) ? "true" : "false");
region.op({1, 4, 3, 6}, SkRegion::kUnion_Op);
SkDebugf("quickContains 2: %s\n", region.quickContains(test) ? "true" : "false");
region.op({1, 7, 3, 8}, SkRegion::kUnion_Op);
SkDebugf("quickContains 3: %s\n", region.quickContains(test) ? "true" : "false");
#StdOut
quickContains 1: true
quickContains 2: true
quickContains 3: false
##
##
#SeeAlso contains quickReject intersects
#Method ##
# ------------------------------------------------------------------------------
#Method bool quickContains(int32_t left, int32_t top, int32_t right,
int32_t bottom) const
Returns true if Region is a single rectangle and contains IRect
(left, top, right, bottom).
Returns false if Region is empty or IRect (left, top, right, bottom) is empty.
May return false even though Region contains (left, top, right, bottom).
#Param left edge of bounds on x-axis ##
#Param top edge of bounds on y-axis ##
#Param right edge of bounds on x-axis ##
#Param bottom edge of bounds on y-axis ##
#Return true quickly if IRect are equal or inside ##
#Example
auto debugster = [](const char* label, SkRegion& region) -> void {
SkDebugf("%s: %s\n", label, region.quickContains(2, 2, 3, 3) ? "true" : "false");
};
SkRegion region({1, 2, 3, 4});
debugster("quickContains 1", region);
region.op({1, 4, 3, 6}, SkRegion::kUnion_Op);
debugster("quickContains 2", region);
region.op({1, 7, 3, 8}, SkRegion::kUnion_Op);
debugster("quickContains 3", region);
#StdOut
quickContains 1: true
quickContains 2: true
quickContains 3: false
##
##
#SeeAlso contains quickReject intersects
#Method ##
# ------------------------------------------------------------------------------
#Method bool quickReject(const SkIRect& rect) const
#In Intersection
#Line # returns true quickly if points are outside ##
Returns true if Region does not intersect rect.
Returns true if rect is empty or Region is empty.
May return false even though Region does not intersect rect.
#Param rect IRect to intersect ##
#Return true if rect does not intersect ##
#Example
SkRegion region({1, 2, 3, 4});
SkIRect test = {4, 2, 5, 3};
SkDebugf("quickReject 1: %s\n", region.quickReject(test) ? "true" : "false");
region.op({1, 4, 3, 6}, SkRegion::kUnion_Op);
SkDebugf("quickReject 2: %s\n", region.quickReject(test) ? "true" : "false");
region.op({4, 7, 5, 8}, SkRegion::kUnion_Op);
SkDebugf("quickReject 3: %s\n", region.quickReject(test) ? "true" : "false");
#StdOut
quickReject 1: true
quickReject 2: true
quickReject 3: false
##
##
#SeeAlso quickContains contains intersects
#Method ##
# ------------------------------------------------------------------------------
#Method bool quickReject(const SkRegion& rgn) const
Returns true if Region does not intersect rgn.
Returns true if rgn is empty or Region is empty.
May return false even though Region does not intersect rgn.
#Param rgn Region to intersect ##
#Return true if rgn does not intersect ##
#Example
SkRegion region({1, 2, 3, 4});
SkRegion test;
SkIRect rects[] = {{4, 2, 5, 3}, {7, 2, 8, 3}};
test.setRects(rects, SK_ARRAY_COUNT(rects));
SkDebugf("quickReject 1: %s\n", region.quickReject(test) ? "true" : "false");
region.op({1, 4, 3, 6}, SkRegion::kUnion_Op);
SkDebugf("quickReject 2: %s\n", region.quickReject(test) ? "true" : "false");
region.op({4, 7, 5, 8}, SkRegion::kUnion_Op);
SkDebugf("quickReject 3: %s\n", region.quickReject(test) ? "true" : "false");
#StdOut
quickReject 1: true
quickReject 2: true
quickReject 3: false
##
##
#SeeAlso quickContains contains intersects
#Method ##
# ------------------------------------------------------------------------------
#Method void translate(int dx, int dy)
#In Transform
#Line # translates IPoints in Region ##
Offsets Region by IVector (dx, dy). Has no effect if Region is empty.
#Param dx x-axis offset ##
#Param dy y-axis offset ##
#Example
#Height 90
SkRegion test;
SkIRect rects[] = {{40, 20, 50, 30}, {70, 40, 80, 50}, { 60, 10, 70, 20}};
test.setRects(rects, SK_ARRAY_COUNT(rects));
SkPaint paint;
for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN, SK_ColorMAGENTA } ) {
paint.setColor(color);
canvas->drawRegion(test, paint);
test.translate(10, 10);
}
##
#SeeAlso SkCanvas::translate SkIRect::offset SkPath::offset
#Method ##
# ------------------------------------------------------------------------------
#Method void translate(int dx, int dy, SkRegion* dst) const
Offsets Region by IVector (dx, dy), writing result to dst. Region may be passed
as dst parameter, translating Region in place. Has no effect if dst is nullptr.
If Region is empty, sets dst to empty.
#Param dx x-axis offset ##
#Param dy y-axis offset ##
#Param dst translated result ##
#Example
SkRegion test;
SkIRect rects[] = {{40, 20, 50, 30}, {70, 40, 80, 50}, { 60, 10, 70, 20}};
test.setRects(rects, SK_ARRAY_COUNT(rects));
SkPaint paint;
for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN, SK_ColorMAGENTA } ) {
paint.setColor(color);
canvas->drawRegion(test, paint);
SkRegion second;
test.translate(10, test.getBounds().fBottom, &second);
test.op(second, SkRegion::kXOR_Op);
test.translate(30, 0);
}
##
#SeeAlso SkCanvas::translate SkIRect::offset SkPath::offset
#Method ##
# ------------------------------------------------------------------------------
#Enum Op
#Line # binary operator combining Regions ##
#Code
enum Op {
kDifference_Op,
kIntersect_Op,
kUnion_Op,
kXOR_Op,
kReverseDifference_Op,
kReplace_Op,
kLastOp = kReplace_Op,
};
##
The logical operations that can be performed when combining two Regions.
#Const kDifference_Op 0
#Line # target minus operand ##
Subtracts operand Region from target Region.
##
#Const kIntersect_Op 1
#Line # target intersected with operand ##
Intersects operand Region and target Region.
##
#Const kUnion_Op 2
#Line # target unioned with operand ##
Unions operand Region and target Region.
##
#Const kXOR_Op 3
#Line # target exclusive or with operand ##
Replaces target Region with area exclusive to both Regions.
##
#Const kReverseDifference_Op 4
#Line # operand minus target ##
Subtracts target Region from operand Region.
##
#Const kReplace_Op 5
#Line # replace target with operand ##
Replaces target Region with operand Region.
##
#Const kLastOp 5
#Line # last operator ##
##
#Example
SkRegion operand({35, 35, 85, 85});
const char* labels[] = {"difference", "intersect", "union", "xor", "reverse diff", "replace"};
int index = 0;
SkPaint paint;
paint.setTextAlign(SkPaint::kCenter_Align);
for (auto op : { SkRegion::kDifference_Op, SkRegion::kIntersect_Op, SkRegion::kUnion_Op,
SkRegion::kXOR_Op, SkRegion::kReverseDifference_Op, SkRegion::kReplace_Op } ) {
SkRegion target({10, 10, 60, 60});
target.op(operand, op);
canvas->drawRegion(target, paint);
canvas->drawString(labels[index++], 40, 100, paint);
canvas->translate(80, 0);
if (SkRegion::kUnion_Op == op) {
canvas->translate(-240, 120);
}
}
##
#SeeAlso SkPathOp
#Enum ##
# ------------------------------------------------------------------------------
#Const kOpCnt 6
#Line # number of operators defined ##
May be used to verify that Op is a legal value.
#Const ##
# ------------------------------------------------------------------------------
#Method bool op(const SkIRect& rect, Op op)
#In Transform
#Line # applies binary operator ##
Replaces Region with the result of Region op rect.
Returns true if replaced Region is not empty.
#Param rect IRect operand ##
#Param op operator, one of: #list_of_op_types#
##
#Return false if result is empty ##
#Example
#Height 128
SkPaint paint;
paint.setTextSize(128);
SkPath xPath;
paint.getTextPath("X", 1, 20, 110, &xPath);
SkRegion xRegion;
SkIRect drawBounds = {0, 0, 128, 128};
xRegion.setPath(xPath, SkRegion(drawBounds));
xRegion.op(drawBounds, SkRegion::kReverseDifference_Op);
canvas->drawRegion(xRegion, paint);
##
#SeeAlso setRects Op
#Method ##
# ------------------------------------------------------------------------------
#Method bool op(int left, int top, int right, int bottom, Op op)
Replaces Region with the result of Region op IRect (left, top, right, bottom).
Returns true if replaced Region is not empty.
#Param left edge of bounds on x-axis ##
#Param top edge of bounds on y-axis ##
#Param right edge of bounds on x-axis ##
#Param bottom edge of bounds on y-axis ##
#Param op operator, one of: #list_of_op_types#
##
#Return false if result is empty ##
#Example
#Duration 4
#Height 128
SkPaint paint;
paint.setTextSize(128);
SkPath xPath;
paint.getTextPath("X", 1, 20, 110, &xPath);
SkRegion xRegion;
SkIRect drawBounds = {0, 0, 128, 128};
xRegion.setPath(xPath, SkRegion(drawBounds));
xRegion.op(drawBounds.fLeft + frame * drawBounds.width(), drawBounds.fTop,
drawBounds.fRight, drawBounds.fBottom, SkRegion::kReverseDifference_Op);
canvas->drawRegion(xRegion, paint);
##
#SeeAlso setRects Op
#Method ##
# ------------------------------------------------------------------------------
#Method bool op(const SkRegion& rgn, Op op)
Replaces Region with the result of Region op rgn.
Returns true if replaced Region is not empty.
#Param rgn Region operand ##
#Param op operator, one of: #list_of_op_types#
##
#Return false if result is empty ##
#Example
#Duration 4
#Height 128
SkPaint paint;
paint.setTextSize(128);
SkPath xPath, opPath;
paint.getTextPath("X", 1, 20, 110, &xPath);
opPath.addCircle(64, 64, frame * 64);
SkRegion xRegion, opRegion;
SkIRect drawBounds = {0, 0, 128, 128};
opRegion.setPath(opPath, SkRegion(drawBounds));
xRegion.setPath(xPath, SkRegion(drawBounds));
xRegion.op(opRegion, SkRegion::kReverseDifference_Op);
canvas->drawRegion(xRegion, paint);
##
#SeeAlso setRects Op
#Method ##
# ------------------------------------------------------------------------------
#Method bool op(const SkIRect& rect, const SkRegion& rgn, Op op)
Replaces Region with the result of rect op rgn.
Returns true if replaced Region is not empty.
#Param rect IRect operand ##
#Param rgn Region operand ##
#Param op operator, one of: #list_of_op_types#
##
#Return false if result is empty ##
#Example
#Duration 4
#Height 128
SkPaint paint;
paint.setTextSize(128);
SkPath xPath, opPath;
paint.getTextPath("X", 1, 20, 110, &xPath);
opPath.addCircle(64, 64, frame * 64);
SkRegion xRegion, opRegion, rectRegion;
SkIRect drawBounds = {0, 0, 128, 128};
opRegion.setPath(opPath, SkRegion(drawBounds));
xRegion.setPath(xPath, SkRegion(drawBounds));
drawBounds.inset(frame * drawBounds.width() / 2, 0);
rectRegion.op(drawBounds, opRegion, SkRegion::kIntersect_Op);
xRegion.op(rectRegion, SkRegion::kReverseDifference_Op);
canvas->drawRegion(xRegion, paint);
##
#SeeAlso setRects Op
#Method ##
# ------------------------------------------------------------------------------
#Method bool op(const SkRegion& rgn, const SkIRect& rect, Op op)
Replaces Region with the result of rgn op rect.
Returns true if replaced Region is not empty.
#Param rgn Region operand ##
#Param rect IRect operand ##
#Param op operator, one of: #list_of_op_types#
##
#Return false if result is empty ##
#Example
#Duration 4
#Height 128
SkPaint paint;
paint.setTextSize(128);
SkPath xPath, opPath;
paint.getTextPath("X", 1, 20, 110, &xPath);
opPath.addCircle(64, 64, frame * 64);
SkRegion xRegion, opRegion, rectRegion;
SkIRect drawBounds = {0, 0, 128, 128};
opRegion.setPath(opPath, SkRegion(drawBounds));
xRegion.setPath(xPath, SkRegion(drawBounds));
drawBounds.inset(frame * drawBounds.width() / 2, 0);
rectRegion.op(opRegion, drawBounds, SkRegion::kUnion_Op);
xRegion.op(rectRegion, SkRegion::kReverseDifference_Op);
canvas->drawRegion(xRegion, paint);
##
#SeeAlso setRects Op
#Method ##
# ------------------------------------------------------------------------------
#Method bool op(const SkRegion& rgna, const SkRegion& rgnb, Op op)
Replaces Region with the result of rgna op rgnb.
Returns true if replaced Region is not empty.
#Param rgna Region operand ##
#Param rgnb Region operand ##
#Param op operator, one of: #list_of_op_types#
##
#Return false if result is empty ##
#Example
#Duration 4
#Height 128
SkPaint paint;
paint.setTextSize(128);
SkPath xPath, opPath;
paint.getTextPath("X", 1, 20, 110, &xPath);
xPath.setFillType(SkPath::kInverseWinding_FillType);
opPath.addCircle(64, 64, frame * 64);
opPath.setFillType(SkPath::kInverseWinding_FillType);
SkRegion xRegion, opRegion, rectRegion;
SkIRect drawBounds = {0, 0, 128, 128};
opRegion.setPath(opPath, SkRegion(drawBounds));
xRegion.setPath(xPath, SkRegion(drawBounds));
drawBounds.inset(frame * drawBounds.width() / 2, 0);
rectRegion.setRect(drawBounds);
rectRegion.op(xRegion, SkRegion::kIntersect_Op);
xRegion.op(rectRegion, opRegion, SkRegion::kReverseDifference_Op);
canvas->drawRegion(xRegion, paint);
##
#SeeAlso setRects Op
#Method ##
# ------------------------------------------------------------------------------
#Method char* toString()
#In Utility
#Line # exists for Android framework only ##
#Private
Android framework only.
##
#Return string representation of Region ##
#Method ##
# ------------------------------------------------------------------------------
#Method size_t writeToMemory(void* buffer) const
#In Utility
#Line # writes to buffer ##
Writes Region to buffer, and returns number of bytes written.
If buffer is nullptr, returns number number of bytes that would be written.
#Param buffer storage for binary data ##
#Return size of Region ##
#Example
#Height 128
SkPaint paint;
paint.setTextSize(128);
SkPath xPath;
paint.getTextPath("X", 1, 20, 110, &xPath);
SkIRect drawBounds = {0, 0, 128, 128};
SkRegion xRegion;
xRegion.setPath(xPath, SkRegion(drawBounds));
size_t size = xRegion.writeToMemory(nullptr);
sk_sp<SkData> data = SkData::MakeUninitialized(size);
xRegion.writeToMemory(data->writable_data());
SkRegion copy;
copy.readFromMemory(data->data(), data->size());
canvas->drawRegion(copy, paint);
##
#SeeAlso readFromMemory
#Method ##
# ------------------------------------------------------------------------------
#Method size_t readFromMemory(const void* buffer, size_t length)
#In Utility
#Line # reads from buffer ##
Constructs Region from buffer of size length. Returns bytes read.
Returned value will be multiple of four or zero if length was too small.
#Param buffer storage for binary data ##
#Param length size of buffer ##
#Return bytes read ##
#Example
#Height 100
SkRegion region({20, 20, 80, 80});
size_t size = region.writeToMemory(nullptr);
sk_sp<SkData> data = SkData::MakeUninitialized(size);
region.writeToMemory(data->writable_data());
SkRegion copy;
copy.readFromMemory(data->data(), data->size());
canvas->drawRegion(copy, SkPaint());
##
#SeeAlso writeToMemory
#Method ##
#Class SkRegion ##
#Topic Region ##