1#Topic Region
2#Alias Region_Reference ##
3#Alias Regions ##
4
5Region is a compressed one bit mask. Region describes an aliased clipping area
6on integer boundaries. Region can also describe an array of integer rectangles.
7
8Canvas uses Region to reduce the current clip. Region may be drawn to Canvas;
9Paint determines if Region is filled or stroked, its Color, and so on.
10
11Region may be constructed from IRect array or Path. Diagonal lines and curves
12in Path become integer rectangle edges. Regions operators compute union,
13intersection, difference, and so on. Canvas allows only intersection and
14difference; successive clips can only reduce available Canvas area.
15
16#PhraseDef list_of_op_types
17kDifference_Op, kIntersect_Op, kUnion_Op, kXOR_Op, kReverseDifference_Op,
18kReplace_Op
19##
20
21#Class SkRegion
22
23#Code
24#Populate
25##
26
27SkRegion describes the set of pixels used to clip Canvas. SkRegion is compact,
28efficiently storing a single integer rectangle, or a run length encoded array
29of rectangles. SkRegion may reduce the current Canvas_Clip, or may be drawn as
30one or more integer rectangles. SkRegion iterator returns the scan lines or
31rectangles contained by it, optionally intersecting a bounding rectangle.
32
33# ------------------------------------------------------------------------------
34
35#Class Iterator
36#Line # iterator returning IRect  ##
37
38#Code
39    class Iterator {
40    public:
41        Iterator();
42        Iterator(const SkRegion& region);
43        bool rewind();
44        void reset(const SkRegion& region);
45        bool done() const;
46        void next();
47        const SkIRect& rect();
48        const SkRegion* rgn();
49    };
50##
51
52Returns sequence of rectangles, sorted along y-axis, then x-axis, that make
53up Region.
54
55# ------------------------------------------------------------------------------
56
57#Method Iterator()
58#Line # constructs Region iterator ##
59#Populate
60
61#Example
62    SkRegion::Iterator iter;
63    SkRegion region;
64    region.setRect({1, 2, 3, 4});
65    iter.reset(region);
66    auto r = iter.rect();
67    SkDebugf("rect={%d,%d,%d,%d}\n", r.fLeft, r.fTop, r.fRight, r.fBottom);
68#StdOut
69rect={1,2,3,4}
70##
71##
72
73#SeeAlso reset SkRegion
74
75#Method ##
76
77# ------------------------------------------------------------------------------
78
79#Method Iterator(const SkRegion& region)
80#Line # constructs Region iterator ##
81#Populate
82
83#Example
84    SkRegion region;
85    region.setRect({1, 2, 3, 4});
86    SkRegion::Iterator iter(region);
87    auto r = iter.rect();
88    SkDebugf("rect={%d,%d,%d,%d}\n", r.fLeft, r.fTop, r.fRight, r.fBottom);
89#StdOut
90rect={1,2,3,4}
91##
92##
93
94#SeeAlso reset SkRegion Cliperator Spanerator
95
96#Method ##
97
98# ------------------------------------------------------------------------------
99
100#Method bool rewind()
101#Line # points Iterator to start ##
102#Populate
103
104#Example
105#Bug 8186
106    auto debugster = [](const char* label, SkRegion::Iterator& iter, bool addRewind) -> void {
107        if (addRewind) {
108            bool success = iter.rewind();
109            SkDebugf("%14s rewind success=%s\n", label, success ? "true" : "false");
110        }
111        auto r = iter.rect();
112        SkDebugf("%14s rect={%d,%d,%d,%d}\n", label, r.fLeft, r.fTop, r.fRight, r.fBottom);
113    };
114    SkRegion::Iterator iter;
115    debugster("empty iter", iter, true);
116    SkRegion region;
117    iter.reset(region);
118    debugster("empty region", iter, true);
119    region.setRect({1, 2, 3, 4});
120    iter.reset(region);
121    debugster("after set rect", iter, false);
122    debugster("after rewind", iter, true);
123#StdOut
124#Volatile
125    empty iter rewind success=false
126    empty iter rect={0,0,0,0}
127  empty region rewind success=true
128  empty region rect={0,0,0,0}
129after set rect rect={1,2,3,4}
130  after rewind rewind success=true
131  after rewind rect={1,2,3,4}
132##
133##
134
135#SeeAlso reset
136
137#Method ##
138
139# ------------------------------------------------------------------------------
140
141#Method void reset(const SkRegion& region)
142#Line # sets Region to iterate ##
143#Populate
144
145#Example
146    auto debugster = [](const char* label, SkRegion::Iterator& iter) -> void {
147        SkDebugf("%14s: done=%s\n", label, iter.done() ? "true" : "false");
148    };
149    SkRegion region;
150    SkRegion::Iterator iter(region);
151    debugster("empty region", iter);
152    region.setRect({1, 2, 3, 4});
153    debugster("after set rect", iter);
154    iter.reset(region);
155    debugster("after reset", iter);
156#StdOut
157  empty region: done=true
158after set rect: done=true
159   after reset: done=false
160##
161##
162
163#SeeAlso rewind
164
165#Method ##
166
167# ------------------------------------------------------------------------------
168
169#Method bool done() const
170#Line # returns if data parsing is complete ##
171#Populate
172
173#Example
174    SkRegion region;
175    SkRegion::Iterator iter(region);
176    SkDebugf("done=%s\n", iter.done() ? "true" : "false");
177    region.setRect({1, 2, 3, 4});
178    iter.rewind();
179    SkDebugf("done=%s\n", iter.done() ? "true" : "false");
180#StdOut
181done=true
182done=false
183##
184##
185
186#SeeAlso next rect
187
188#Method ##
189
190# ------------------------------------------------------------------------------
191
192#Method void next()
193#Line # advances to next IRect ##
194#Populate
195
196#Example
197    SkRegion region;
198    SkIRect rects[] = {{1, 2, 3, 4}, {5, 6, 7, 8}};
199    region.setRects(rects, SK_ARRAY_COUNT(rects));
200    SkRegion::Iterator iter(region);
201    do {
202        auto r2 = iter.rect();
203        SkDebugf("rect={%d,%d,%d,%d}\n", r2.fLeft, r2.fTop, r2.fRight, r2.fBottom);
204        iter.next();
205    } while (!iter.done());
206#StdOut
207rect={1,2,3,4}
208rect={5,6,7,8}
209##
210##
211
212#SeeAlso done rect
213
214#Method ##
215
216# ------------------------------------------------------------------------------
217
218#Method const SkIRect& rect() const
219#Line # returns part of Region as IRect ##
220#Populate
221
222#Example
223#Bug 8186
224    SkRegion region;
225    SkRegion::Iterator iter(region);
226    auto r1 = iter.rect();
227    SkDebugf("rect={%d,%d,%d,%d}\n", r1.fLeft, r1.fTop, r1.fRight, r1.fBottom);
228    region.setRect({1, 2, 3, 4});
229    iter.rewind();
230    auto r2 = iter.rect();
231    SkDebugf("rect={%d,%d,%d,%d}\n", r2.fLeft, r2.fTop, r2.fRight, r2.fBottom);
232#StdOut
233#Volatile
234rect={0,0,0,0}
235rect={1,2,3,4}
236##
237##
238
239#SeeAlso next done
240
241#Method ##
242
243# ------------------------------------------------------------------------------
244
245#Method const SkRegion* rgn() const
246#Line # returns original Region ##
247#Populate
248
249#Example
250    SkRegion region;
251    SkIRect rects[] = {{1, 2, 3, 4}, {3, 4, 5, 6}};
252    region.setRects(rects, SK_ARRAY_COUNT(rects));
253    SkRegion::Iterator iter(region);
254    auto r = iter.rect();
255    SkDebugf("rect={%d,%d,%d,%d}\n", r.fLeft, r.fTop, r.fRight, r.fBottom);
256    auto b = iter.rgn()->getBounds();
257    SkDebugf("bounds={%d,%d,%d,%d}\n", b.fLeft, b.fTop, b.fRight, b.fBottom);
258##
259
260#SeeAlso Iterator reset
261
262#Method ##
263
264#Class Iterator ##
265
266# ------------------------------------------------------------------------------
267
268#Class Cliperator
269#Line # iterator returning IRect within clip ##
270
271#Code
272    class Cliperator {
273    public:
274        Cliperator(const SkRegion& region, const SkIRect& clip);
275        bool done();
276        void next();
277        const SkIRect& rect() const;
278    };
279##
280
281Returns the sequence of rectangles, sorted along y-axis, then x-axis, that make
282up Region intersected with the specified clip rectangle.
283
284# ------------------------------------------------------------------------------
285
286#Method Cliperator(const SkRegion& region, const SkIRect& clip)
287#Line # constructs Region iterator with clip ##
288#Populate
289
290#Example
291    SkRegion region;
292    region.setRect({1, 2, 3, 4});
293    SkRegion::Cliperator clipper(region, {0, 0, 2, 3});
294    auto r = clipper.rect();
295    SkDebugf("rect={%d,%d,%d,%d}\n", r.fLeft, r.fTop, r.fRight, r.fBottom);
296#StdOut
297rect={1,2,2,3}
298##
299##
300
301#SeeAlso SkRegion Iterator Spanerator
302
303#Method ##
304
305# ------------------------------------------------------------------------------
306
307#Method bool done()
308#Line # returns if data parsing is complete ##
309#Populate
310
311#Example
312    auto debugster = [](const char* label, SkRegion& region) -> void {
313        SkRegion::Cliperator clipper(region, {0, 0, 5, 5});
314        SkDebugf("%14s done=%s\n", label, clipper.done() ? "true" : "false");
315    };
316    SkRegion region;
317    debugster("empty region", region);
318    region.setRect({1, 2, 3, 4});
319    debugster("after add rect", region);
320#StdOut
321  empty region done=true
322after add rect done=false
323##
324##
325
326#SeeAlso next rect
327
328#Method ##
329
330# ------------------------------------------------------------------------------
331
332#Method void  next()
333#Line # advances to next IRect within clip ##
334#Populate
335
336#Example
337    SkRegion region;
338    SkIRect rects[] = {{1, 2, 3, 4}, {5, 6, 7, 8}};
339    region.setRects(rects, SK_ARRAY_COUNT(rects));
340    SkRegion::Cliperator clipper(region, {0, 3, 8, 7});
341    do {
342        auto r2 = clipper.rect();
343        SkDebugf("rect={%d,%d,%d,%d}\n", r2.fLeft, r2.fTop, r2.fRight, r2.fBottom);
344        clipper.next();
345    } while (!clipper.done());
346#StdOut
347rect={1,3,3,4}
348rect={5,6,7,7}
349##
350##
351
352#SeeAlso done
353
354#Method ##
355
356# ------------------------------------------------------------------------------
357
358#Method const SkIRect& rect() const
359#Line # returns part of Region as IRect intersected with clip ##
360#Populate
361
362#Example
363#Bug 8186
364    auto debugster = [](const char* label, SkRegion& region) -> void {
365        SkRegion::Cliperator clipper(region, {0, 0, 5, 3});
366        auto r = clipper.rect();
367        SkDebugf("%14s rect={%d,%d,%d,%d}\n", label, r.fLeft, r.fTop, r.fRight, r.fBottom);
368    };
369    SkRegion region;
370    debugster("empty region", region);
371    region.setRect({1, 2, 3, 4});
372    debugster("after set rect", region);
373#StdOut
374#Volatile
375  empty region rect={1094713344,1065353216,0,-1}
376after set rect rect={1,2,3,3}
377##
378##
379
380#SeeAlso next done
381
382#Method ##
383
384#Class Cliperator ##
385
386# ------------------------------------------------------------------------------
387
388#Class Spanerator
389#Line # horizontal line segment iterator ##
390
391#Code
392    class Spanerator {
393    public:
394        Spanerator(const SkRegion& region, int y, int left, int right);
395        bool next(int* left, int* right);
396    };
397##
398
399Returns the line segment ends within Region that intersect a horizontal line.
400
401# ------------------------------------------------------------------------------
402
403#Method Spanerator(const SkRegion& region, int y, int left, int right)
404#Line # constructs Region iterator on scan line ##
405#Populate
406
407#Example
408    SkRegion region;
409    region.setRect({1, 2, 3, 4});
410    SkRegion::Spanerator spanner(region, 3, 2, 4);
411    int left, right;
412    bool result = spanner.next(&left, &right);
413    SkDebugf("result=%s left=%d right=%d\n", result ? "true" : "false", left, right);
414##
415
416#SeeAlso SkRegion Iterator Cliperator
417
418#Method ##
419
420# ------------------------------------------------------------------------------
421
422#Method bool next(int* left, int* right)
423#Line # advances to next span on horizontal line ##
424#Populate
425
426#Example
427    auto debugster = [](const char* label, SkRegion& region) -> void {
428        SkRegion::Spanerator spanner(region, 3, 2, 4);
429        int left, right;
430        bool result = spanner.next(&left, &right);
431        SkDebugf("%14s: result=%s", label, result ? "true" : "false");
432        if (result) SkDebugf(" left=%d right=%d", left, right);
433        SkDebugf("\n");
434    };
435    SkRegion region;
436    debugster("empty region", region);
437    region.setRect({1, 2, 3, 4});
438    debugster("after set rect", region);
439#StdOut
440  empty region: result=false
441after set rect: result=true left=2 right=3
442##
443##
444
445#SeeAlso done
446
447#Method ##
448
449#Class Spanerator ##
450
451# ------------------------------------------------------------------------------
452
453#Method SkRegion()
454#In Constructors
455#Line # constructs with default values ##
456#Populate
457
458#Example
459SkRegion region;
460SkIRect r = region.getBounds();
461SkDebugf("region bounds: {%d, %d, %d, %d}\n", r.fLeft, r.fTop, r.fRight, r.fBottom);
462#StdOut
463region bounds: {0, 0, 0, 0}
464##
465##
466
467#SeeAlso setEmpty
468
469#Method ##
470
471# ------------------------------------------------------------------------------
472
473#Method SkRegion(const SkRegion& region)
474#In Constructors
475#Line # makes a shallow copy ##
476#Populate
477
478#Example
479    auto debugster = [](const char* label, SkRegion& region) -> void {
480        auto r = region.getBounds();
481        SkDebugf("%14s: {%d,%d,%d,%d}\n", label, r.fLeft, r.fTop, r.fRight, r.fBottom);
482    };
483    SkRegion region({1, 2, 3, 4});
484    SkRegion region2(region);
485    debugster("region bounds", region);
486    debugster("region2 bounds", region2);
487    region.setEmpty();
488    SkDebugf("    after region set empty:\n");
489    debugster("region bounds", region);
490    debugster("region2 bounds", region2);
491#StdOut
492 region bounds: {1,2,3,4}
493region2 bounds: {1,2,3,4}
494    after region set empty:
495 region bounds: {0,0,0,0}
496region2 bounds: {1,2,3,4}
497##
498##
499
500#SeeAlso setRegion operator=(const SkRegion& region)
501
502#Method ##
503
504# ------------------------------------------------------------------------------
505
506#Method explicit SkRegion(const SkIRect& rect)
507#In Constructors
508#Line # constructs Region matching IRect ##
509#Populate
510
511#Example
512    SkRegion region({1, 2, 3, 4});
513    SkRegion region2;
514    region2.setRect({1, 2, 3, 4});
515    SkDebugf("region %c= region2\n", region == region2 ? '=' : '!');
516##
517
518#SeeAlso setRect setRegion
519
520#Method ##
521
522# ------------------------------------------------------------------------------
523
524#Method ~SkRegion()
525#In Constructors
526#Line # decreases Reference_Count of owned objects ##
527#Populate
528
529#Example
530#Description
531delete calls Region destructor, but copy of original in region2 is unaffected.
532##
533    SkRegion* region = new SkRegion({1, 2, 3, 4});
534    SkRegion region2(*region);
535    delete region;
536    auto r = region2.getBounds();
537    SkDebugf("region2 bounds: {%d,%d,%d,%d}\n", r.fLeft, r.fTop, r.fRight, r.fBottom);
538#StdOut
539region2 bounds: {1,2,3,4}
540##
541##
542
543#SeeAlso SkRegion() SkRegion(const SkRegion& region) SkRegion(const SkIRect& rect) operator=(const SkRegion& region)
544
545#Method ##
546
547# ------------------------------------------------------------------------------
548
549#Method SkRegion& operator=(const SkRegion& region)
550#In Operators
551#Line # makes a shallow copy ##
552#Populate
553
554#Example
555    auto debugster = [](const char* label, SkRegion& region) -> void {
556        auto r = region.getBounds();
557        SkDebugf("%14s: {%d,%d,%d,%d}\n", label, r.fLeft, r.fTop, r.fRight, r.fBottom);
558    };
559    SkRegion region1({1, 2, 3, 4});
560    SkRegion region2 = region1;
561    debugster("region1 bounds", region1);
562    debugster("region2 bounds", region2);
563#StdOut
564region1 bounds: {1,2,3,4}
565region2 bounds: {1,2,3,4}
566##
567##
568
569#SeeAlso set swap SkRegion(const SkRegion& region)
570
571#Method ##
572
573# ------------------------------------------------------------------------------
574
575#Method bool operator==(const SkRegion& other) const
576#In Operators
577#Line # compares Regions for equality ##
578#Populate
579
580#Example
581    auto debugster = [](const char* prefix, const SkRegion& a, const SkRegion& b) -> void {
582                SkDebugf("%s one %c= two\n", prefix, a == b ? '=' : '!');
583    };
584    SkRegion one;
585    SkRegion two;
586    debugster("empty", one, two);
587    one.setRect({1, 2, 3, 4});
588    debugster("set rect", one, two);
589    one.setEmpty();
590    debugster("set empty", one, two);
591#StdOut
592empty one == two
593set rect one != two
594set empty one == two
595##
596##
597
598#SeeAlso operator!=(const SkRegion& other) const operator=(const SkRegion& region)
599
600#Method ##
601
602# ------------------------------------------------------------------------------
603
604#Method bool operator!=(const SkRegion& other) const
605#In Operators
606#Line # compares Regions for inequality ##
607#Populate
608
609#Example
610    auto debugster = [](const char* prefix, const SkRegion& a, const SkRegion& b) -> void {
611                SkDebugf("%s one %c= two\n", prefix, a != b ? '!' : '=');
612    };
613    SkRegion one;
614    SkRegion two;
615    debugster("empty", one, two);
616    one.setRect({1, 2, 3, 4});
617    two.setRect({1, 2, 3, 3});
618    debugster("set rect", one, two);
619    two.op({1, 3, 3, 4}, SkRegion::kUnion_Op);
620    debugster("union rect", one, two);
621#StdOut
622empty one == two
623set rect one != two
624union rect one == two
625##
626##
627
628#SeeAlso operator==(const SkRegion& other) const operator=(const SkRegion& region)
629
630#Method ##
631
632# ------------------------------------------------------------------------------
633
634#Method bool set(const SkRegion& src)
635#In Constructors
636#Line # makes a shallow copy ##
637#Populate
638
639#Example
640    auto debugster = [](const char* label, SkRegion& region) -> void {
641        auto r = region.getBounds();
642        SkDebugf("%14s: {%d,%d,%d,%d}\n", label, r.fLeft, r.fTop, r.fRight, r.fBottom);
643    };
644    SkRegion region1({1, 2, 3, 4});
645    SkRegion region2;
646    region2.set(region1);
647    debugster("region1 bounds", region1);
648    debugster("region2 bounds", region2);
649#StdOut
650region1 bounds: {1,2,3,4}
651region2 bounds: {1,2,3,4}
652##
653##
654
655#SeeAlso operator=(const SkRegion& region) swap SkRegion(const SkRegion& region)
656
657#Method ##
658
659# ------------------------------------------------------------------------------
660
661#Method void swap(SkRegion& other)
662#In Operators
663#Line # exchanges Region pair ##
664#Populate
665
666#Example
667    auto debugster = [](const char* label, SkRegion& region) -> void {
668        auto r = region.getBounds();
669        SkDebugf("%14s: {%d,%d,%d,%d}\n", label, r.fLeft, r.fTop, r.fRight, r.fBottom);
670    };
671    SkRegion region1({1, 2, 3, 4});
672    SkRegion region2;
673    region1.swap(region2);
674    debugster("region1 bounds", region1);
675    debugster("region2 bounds", region2);
676#StdOut
677region1 bounds: {0,0,0,0}
678region2 bounds: {1,2,3,4}
679##
680##
681
682#SeeAlso operator=(const SkRegion& region) set SkRegion(const SkRegion& region)
683
684#Method ##
685
686# ------------------------------------------------------------------------------
687
688#Method bool isEmpty() const
689#In Property
690#Line # returns if bounds has no width or height ##
691#Populate
692
693#Example
694    auto debugster = [](const char* label, SkRegion& region) -> void {
695        SkDebugf("%14s: region is %s" "empty\n", label, region.isEmpty() ? "" : "not ");
696    };
697    SkRegion region;
698    debugster("initial", region);
699    region.setRect({1, 2, 3, 4});
700    debugster("set rect", region);
701    region.setEmpty();
702    debugster("set empty", region);
703#StdOut
704       initial: region is empty
705      set rect: region is not empty
706     set empty: region is empty
707##
708##
709
710#SeeAlso isRect isComplex operator==(const SkRegion& other) const
711
712#Method ##
713
714# ------------------------------------------------------------------------------
715
716#Method bool isRect() const
717#In Property
718#Line # returns if Region contains one IRect ##
719#Populate
720
721#Example
722    auto debugster = [](const char* label, const SkRegion& region) -> void {
723                SkDebugf("%s: region is %s" "rect\n", label, region.isRect() ? "" : "not ");
724    };
725    SkRegion region;
726    debugster("initial", region);
727    region.setRect({1, 2, 3, 4});
728    debugster("set rect", region);
729    region.setEmpty();
730    debugster("set empty", region);
731#StdOut
732initial: region is not rect
733set rect: region is rect
734set empty: region is not rect
735##
736##
737
738#SeeAlso isEmpty isComplex
739
740#Method ##
741
742# ------------------------------------------------------------------------------
743
744#Method bool isComplex() const
745#In Property
746#Line # returns true if Region contains more than one IRect ##
747#Populate
748
749#Example
750    auto debugster = [](const char* label, const SkRegion& region) -> void {
751                SkDebugf("%s: region is %s" "complex\n", label, region.isComplex() ? "" : "not ");
752    };
753    SkRegion region;
754    debugster("initial", region);
755    region.setRect({1, 2, 3, 4});
756    debugster("set rect", region);
757    region.op({2, 3, 4, 5}, SkRegion::kUnion_Op);
758    debugster("op rect", region);
759#StdOut
760initial: region is not complex
761set rect: region is not complex
762op rect: region is complex
763##
764##
765
766#SeeAlso isEmpty isRect
767
768#Method ##
769
770# ------------------------------------------------------------------------------
771
772#Method const SkIRect& getBounds() const
773#In Property
774#Line # returns maximum and minimum of IRect array ##
775#Populate
776
777#Example
778    SkRegion region({1, 2, 3, 4});
779    region.op({2, 3, 4, 5}, SkRegion::kUnion_Op);
780    auto r = region.getBounds();
781    SkDebugf("bounds: {%d,%d,%d,%d}\n", r.fLeft, r.fTop, r.fRight, r.fBottom);
782#StdOut
783bounds: {1,2,4,5}
784##
785##
786
787#SeeAlso isEmpty isRect
788
789#Method ##
790
791# ------------------------------------------------------------------------------
792
793#Method int computeRegionComplexity() const
794#In Property
795#Line # returns relative complexity ##
796#Populate
797
798#Example
799    auto debugster = [](const char* label, const SkRegion& region) -> void {
800                SkDebugf("%s: region complexity %d\n", label, region.computeRegionComplexity());
801    };
802    SkRegion region;
803    debugster("initial", region);
804    region.setRect({1, 2, 3, 4});
805    debugster("set rect", region);
806    region.op({2, 3, 4, 5}, SkRegion::kUnion_Op);
807    debugster("op rect", region);
808#StdOut
809initial: region complexity 0
810set rect: region complexity 1
811op rect: region complexity 3
812##
813##
814
815#SeeAlso isRect isComplex
816
817#Method ##
818
819# ------------------------------------------------------------------------------
820
821#Method bool getBoundaryPath(SkPath* path) const
822#In Property
823#Line # appends Region outline to Path ##
824#Populate
825
826#Example
827#Height 100
828    SkRegion region;
829    region.setRect({10, 20, 90, 60});
830    region.op({30, 40, 60, 80}, SkRegion::kXOR_Op);
831    canvas->drawRegion(region, SkPaint());
832    SkPath path;
833    region.getBoundaryPath(&path);
834    path.offset(100, 0);
835    canvas->drawPath(path, SkPaint());
836##
837
838#SeeAlso isEmpty isComplex
839
840#Method ##
841
842# ------------------------------------------------------------------------------
843
844#Method bool setEmpty()
845#In Constructors
846#Line # constructs with default values ##
847#Populate
848
849#Example
850    auto debugster = [](const char* label, SkRegion& region) -> void {
851        auto r = region.getBounds();
852        SkDebugf("%14s: {%d,%d,%d,%d}\n", label, r.fLeft, r.fTop, r.fRight, r.fBottom);
853    };
854    SkRegion region({1, 2, 3, 4});
855    debugster("region bounds", region);
856    region.setEmpty();
857    SkDebugf("    after region set empty:\n");
858    debugster("region bounds", region);
859#StdOut
860 region bounds: {1,2,3,4}
861    after region set empty:
862 region bounds: {0,0,0,0}
863##
864##
865
866#SeeAlso SkRegion()
867
868#Method ##
869
870# ------------------------------------------------------------------------------
871
872#Method bool setRect(const SkIRect& rect)
873#In Constructors
874#Line # constructs Region matching IRect ##
875#Populate
876
877#Example
878    SkRegion region({1, 2, 3, 4});
879    SkDebugf("region is %s" "empty\n", region.isEmpty() ? "" : "not ");
880    bool setEmpty = region.setRect({1, 2, 1, 4});
881    SkDebugf("region is %s" "empty\n", region.isEmpty() ? "" : "not ");
882    SkDebugf("setEmpty: %s\n", setEmpty ? "true" : "false");
883#StdOut
884region is not empty
885region is empty
886setEmpty: false
887##
888##
889
890#SeeAlso SkRegion(const SkIRect& rect)
891
892#Method ##
893
894# ------------------------------------------------------------------------------
895
896#Method bool setRect(int32_t left, int32_t top, int32_t right, int32_t bottom)
897#In Constructors
898#Line # constructs Region matching bounds ##
899#Populate
900
901#Example
902    auto debugster = [](const char* label, bool success, SkRegion& region) -> void {
903        auto r = region.getBounds();
904        SkDebugf("%14s: success:%s {%d,%d,%d,%d}\n", label, success ? "true" : "false",
905                 r.fLeft, r.fTop, r.fRight, r.fBottom);
906    };
907    SkRegion region;
908    bool success = region.setRect(1, 2, 3, 4);
909    debugster("set to: 1,2,3,4", success, region);
910    success = region.setRect(3, 2, 1, 4);
911    debugster("set to: 3,2,1,4", success, region);
912#StdOut
913set to: 1,2,3,4: success:true {1,2,3,4}
914set to: 3,2,1,4: success:false {0,0,0,0}
915##
916##
917
918#SeeAlso SkRegion(const SkIRect& rect)
919
920#Method ##
921
922# ------------------------------------------------------------------------------
923
924#Method bool setRects(const SkIRect rects[], int count)
925#In Constructors
926#Line # sets IRect array ##
927#Populate
928
929#Example
930#Height 70
931    SkIRect rects[] = { {10, 10, 40, 40}, {20, 20, 50, 50}, {30, 30, 60, 60} };
932    SkRegion region;
933    region.setRects(rects, SK_ARRAY_COUNT(rects));
934    canvas->drawRegion(region, SkPaint());
935    region.setEmpty();
936    for (auto add : rects) {
937        region.op(add, SkRegion::kUnion_Op);
938    }
939    region.translate(100, 0);
940    canvas->drawRegion(region, SkPaint());
941##
942
943#SeeAlso setRect op
944
945#Method ##
946
947# ------------------------------------------------------------------------------
948
949#Method bool setRegion(const SkRegion& region)
950#In Constructors
951#Line # copies Region ##
952#Populate
953
954#Example
955    auto debugster = [](const char* label, SkRegion& region) -> void {
956        auto r = region.getBounds();
957        SkDebugf("%14s: {%d,%d,%d,%d}\n", label, r.fLeft, r.fTop, r.fRight, r.fBottom);
958    };
959    SkRegion region({1, 2, 3, 4});
960    SkRegion region2;
961    region2.setRegion(region);
962    debugster("region bounds", region);
963    debugster("region2 bounds", region2);
964    region2.setEmpty();
965    SkDebugf("    after region set empty:\n");
966    debugster("region bounds", region);
967    debugster("region2 bounds", region2);
968#StdOut
969 region bounds: {1,2,3,4}
970region2 bounds: {1,2,3,4}
971    after region set empty:
972 region bounds: {1,2,3,4}
973region2 bounds: {0,0,0,0}
974##
975##
976
977#SeeAlso SkRegion(const SkRegion& region)
978
979#Method ##
980
981# ------------------------------------------------------------------------------
982
983#Method bool setPath(const SkPath& path, const SkRegion& clip)
984#In Constructors
985#Line # constructs Region from clipped Path ##
986#Populate
987
988#Example
989#Height 120
990    SkPaint paint;
991    paint.setTextSize(128);
992    SkPath textPath;
993    paint.getTextPath("Q", 1, 0, 110, &textPath);
994    SkIRect clipRect = {20, 20, 100, 120};
995    SkRegion clipRegion(clipRect);
996    SkRegion region;
997    region.setPath(textPath, clipRegion);
998    canvas->drawRegion(region, SkPaint());
999    clipRect.offset(100, 0);
1000    textPath.offset(100, 0);
1001    canvas->clipRect(SkRect::Make(clipRect), false);
1002    canvas->drawPath(textPath, SkPaint());
1003##
1004
1005#SeeAlso setRects op
1006
1007#Method ##
1008
1009# ------------------------------------------------------------------------------
1010
1011#Method bool intersects(const SkIRect& rect) const
1012#In Intersection
1013#Line # returns true if areas overlap ##
1014#Populate
1015
1016#Example
1017#Duration 4
1018#Height 128
1019    SkPaint paint;
1020    paint.setTextSize(128);
1021    SkPath textPath;
1022    paint.getTextPath("W", 1, 20, 110, &textPath);
1023    SkRegion region;
1024    region.setPath(textPath, SkRegion({0, 0, 256, 256}));
1025    canvas->drawRegion(region, SkPaint());
1026    SkIRect iRect = SkIRect::MakeXYWH(frame * 160, 55, 10, 10);
1027    paint.setColor(region.intersects(iRect) ? SK_ColorBLUE : SK_ColorRED);
1028    canvas->drawRect(SkRect::Make(iRect), paint);
1029##
1030
1031#SeeAlso contains SkRect::intersects
1032
1033#Method ##
1034
1035# ------------------------------------------------------------------------------
1036
1037#Method bool intersects(const SkRegion& other) const
1038#Populate
1039
1040#Example
1041#Duration 4
1042#Height 128
1043    SkPaint paint;
1044    paint.setTextSize(128);
1045    SkPath hPath, dotPath;
1046    paint.getTextPath("H", 1, 40, 110, &hPath);
1047    paint.getTextPath(",", 1, frame * 180, 95, &dotPath);
1048    SkRegion hRegion, dotRegion;
1049    hRegion.setPath(hPath, SkRegion({0, 0, 256, 256}));
1050    dotRegion.setPath(dotPath, SkRegion({0, 0, 256, 256}));
1051    canvas->drawRegion(hRegion, paint);
1052    paint.setColor(hRegion.intersects(dotRegion) ? SK_ColorBLUE : SK_ColorRED);
1053    canvas->drawRegion(dotRegion, paint);
1054##
1055
1056#SeeAlso contains SkRect::intersects
1057
1058#Method ##
1059
1060# ------------------------------------------------------------------------------
1061
1062#Method bool contains(int32_t x, int32_t y) const
1063#In Intersection
1064#Line # returns true if points are equal or inside ##
1065#Populate
1066
1067#Example
1068#Height 128
1069    SkPaint paint;
1070    paint.setTextSize(128);
1071    SkPath xPath;
1072    paint.getTextPath("X", 1, 20, 110, &xPath);
1073    SkRegion xRegion;
1074    xRegion.setPath(xPath, SkRegion({0, 0, 256, 256}));
1075    canvas->drawRegion(xRegion, paint);
1076    for (int y = 0; y < 128; y += 8) {
1077        for (int x = 0; x < 128; x += 8) {
1078           paint.setColor(xRegion.contains(x, y) ? SK_ColorWHITE : SK_ColorRED);
1079           canvas->drawPoint(x, y, paint);
1080        }
1081    }
1082##
1083
1084#SeeAlso intersects SkRect::contains
1085
1086#Method ##
1087
1088# ------------------------------------------------------------------------------
1089
1090#Method bool contains(const SkIRect& other) const
1091#Populate
1092
1093#Example
1094#Height 128
1095#Duration 4
1096    SkPaint paint;
1097    paint.setTextSize(128);
1098    SkPath xPath;
1099    paint.getTextPath("X", 1, 20, 110, &xPath);
1100    SkRegion xRegion;
1101    SkIRect drawBounds = {0, 0, 128, 128};
1102    xRegion.setPath(xPath, SkRegion(drawBounds));
1103    xRegion.op(drawBounds, SkRegion::kReverseDifference_Op);
1104    canvas->drawRegion(xRegion, paint);
1105    SkIRect test = SkIRect::MakeXYWH(frame* 128, 64, 5, 5);
1106    if (xRegion.contains(test)) {
1107        paint.setColor(SK_ColorYELLOW);
1108        canvas->drawRect(SkRect::Make(test), paint);
1109    }
1110##
1111
1112#SeeAlso intersects SkRect::contains
1113
1114#Method ##
1115
1116# ------------------------------------------------------------------------------
1117
1118#Method bool contains(const SkRegion& other) const
1119#Populate
1120
1121#Example
1122#Height 128
1123#Duration 4
1124    SkPaint paint;
1125    paint.setTextSize(128);
1126    SkPath xPath, testPath;
1127    paint.getTextPath("X", 1, 20, 110, &xPath);
1128    paint.getTextPath("`", 1, frame * 150 - 40, 150, &testPath);
1129    SkRegion xRegion, testRegion;
1130    SkIRect drawBounds = {0, 0, 128, 128};
1131    xRegion.setPath(xPath, SkRegion(drawBounds));
1132    testRegion.setPath(testPath, SkRegion(drawBounds));
1133    xRegion.op(drawBounds, SkRegion::kReverseDifference_Op);
1134    canvas->drawRegion(xRegion, paint);
1135    if (xRegion.contains(testRegion)) {
1136        paint.setColor(SK_ColorYELLOW);
1137        canvas->drawRegion(testRegion, paint);
1138    }
1139##
1140
1141#SeeAlso intersects SkRect::contains
1142
1143#Method ##
1144
1145# ------------------------------------------------------------------------------
1146
1147#Method bool quickContains(const SkIRect& r) const
1148#In Intersection
1149#Line # returns true quickly if points are equal or inside ##
1150#Populate
1151
1152#Example
1153    SkRegion region({1, 2, 3, 4});
1154    SkIRect test = {2, 2, 3, 3};
1155    SkDebugf("quickContains 1: %s\n", region.quickContains(test) ? "true" : "false");
1156    region.op({1, 4, 3, 6}, SkRegion::kUnion_Op);
1157    SkDebugf("quickContains 2: %s\n", region.quickContains(test) ? "true" : "false");
1158    region.op({1, 7, 3, 8}, SkRegion::kUnion_Op);
1159    SkDebugf("quickContains 3: %s\n", region.quickContains(test) ? "true" : "false");
1160#StdOut
1161quickContains 1: true
1162quickContains 2: true
1163quickContains 3: false
1164##
1165##
1166
1167#SeeAlso contains quickReject intersects
1168
1169#Method ##
1170
1171# ------------------------------------------------------------------------------
1172
1173#Method bool quickContains(int32_t left, int32_t top, int32_t right,
1174                       int32_t bottom) const
1175#Populate
1176
1177#Example
1178    auto debugster = [](const char* label, SkRegion& region) -> void {
1179        SkDebugf("%s: %s\n", label, region.quickContains(2, 2, 3, 3) ? "true" : "false");
1180    };
1181    SkRegion region({1, 2, 3, 4});
1182    debugster("quickContains 1", region);
1183    region.op({1, 4, 3, 6}, SkRegion::kUnion_Op);
1184    debugster("quickContains 2", region);
1185    region.op({1, 7, 3, 8}, SkRegion::kUnion_Op);
1186    debugster("quickContains 3", region);
1187#StdOut
1188quickContains 1: true
1189quickContains 2: true
1190quickContains 3: false
1191##
1192##
1193
1194#SeeAlso contains quickReject intersects
1195
1196#Method ##
1197
1198# ------------------------------------------------------------------------------
1199
1200#Method bool quickReject(const SkIRect& rect) const
1201#In Intersection
1202#Line # returns true quickly if points are outside ##
1203#Populate
1204
1205#Example
1206    SkRegion region({1, 2, 3, 4});
1207    SkIRect test = {4, 2, 5, 3};
1208    SkDebugf("quickReject 1: %s\n", region.quickReject(test) ? "true" : "false");
1209    region.op({1, 4, 3, 6}, SkRegion::kUnion_Op);
1210    SkDebugf("quickReject 2: %s\n", region.quickReject(test) ? "true" : "false");
1211    region.op({4, 7, 5, 8}, SkRegion::kUnion_Op);
1212    SkDebugf("quickReject 3: %s\n", region.quickReject(test) ? "true" : "false");
1213#StdOut
1214quickReject 1: true
1215quickReject 2: true
1216quickReject 3: false
1217##
1218##
1219
1220#SeeAlso quickContains contains intersects
1221
1222#Method ##
1223
1224# ------------------------------------------------------------------------------
1225
1226#Method bool quickReject(const SkRegion& rgn) const
1227#Populate
1228
1229#Example
1230    SkRegion region({1, 2, 3, 4});
1231    SkRegion test;
1232    SkIRect rects[] = {{4, 2, 5, 3}, {7, 2, 8, 3}};
1233    test.setRects(rects, SK_ARRAY_COUNT(rects));
1234    SkDebugf("quickReject 1: %s\n", region.quickReject(test) ? "true" : "false");
1235    region.op({1, 4, 3, 6}, SkRegion::kUnion_Op);
1236    SkDebugf("quickReject 2: %s\n", region.quickReject(test) ? "true" : "false");
1237    region.op({4, 7, 5, 8}, SkRegion::kUnion_Op);
1238    SkDebugf("quickReject 3: %s\n", region.quickReject(test) ? "true" : "false");
1239#StdOut
1240quickReject 1: true
1241quickReject 2: true
1242quickReject 3: false
1243##
1244##
1245
1246#SeeAlso quickContains contains intersects
1247
1248#Method ##
1249
1250# ------------------------------------------------------------------------------
1251
1252#Method void translate(int dx, int dy)
1253#In Transform
1254#Line # translates IPoints in Region ##
1255#Populate
1256
1257#Example
1258#Height 90
1259    SkRegion test;
1260    SkIRect rects[] = {{40, 20, 50, 30}, {70, 40, 80, 50}, { 60, 10, 70, 20}};
1261    test.setRects(rects, SK_ARRAY_COUNT(rects));
1262    SkPaint paint;
1263    for (auto color :  { SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN, SK_ColorMAGENTA } ) {
1264        paint.setColor(color);
1265        canvas->drawRegion(test, paint);
1266        test.translate(10, 10);
1267    }
1268##
1269
1270#SeeAlso SkCanvas::translate SkIRect::offset SkPath::offset
1271
1272#Method ##
1273
1274# ------------------------------------------------------------------------------
1275
1276#Method void translate(int dx, int dy, SkRegion* dst) const
1277#Populate
1278
1279#Example
1280    SkRegion test;
1281    SkIRect rects[] = {{40, 20, 50, 30}, {70, 40, 80, 50}, { 60, 10, 70, 20}};
1282    test.setRects(rects, SK_ARRAY_COUNT(rects));
1283    SkPaint paint;
1284    for (auto color :  { SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN, SK_ColorMAGENTA } ) {
1285        paint.setColor(color);
1286        canvas->drawRegion(test, paint);
1287        SkRegion second;
1288        test.translate(10, test.getBounds().fBottom, &second);
1289        test.op(second, SkRegion::kXOR_Op);
1290        test.translate(30, 0);
1291    }
1292##
1293
1294#SeeAlso SkCanvas::translate SkIRect::offset SkPath::offset
1295
1296#Method ##
1297
1298# ------------------------------------------------------------------------------
1299
1300#Enum Op
1301#Line # binary operator combining Regions ##
1302
1303#Code
1304    enum Op {
1305        kDifference_Op,
1306        kIntersect_Op,
1307        kUnion_Op,
1308        kXOR_Op,
1309        kReverseDifference_Op,
1310        kReplace_Op,
1311        kLastOp = kReplace_Op,
1312    };
1313##
1314
1315The logical operations that can be performed when combining two Regions.
1316
1317#Const kDifference_Op 0
1318#Line # target minus operand ##
1319Subtracts operand Region from target Region.
1320##
1321#Const kIntersect_Op 1
1322#Line # target intersected with operand ##
1323Intersects operand Region and target Region.
1324##
1325#Const kUnion_Op 2
1326#Line # target unioned with operand ##
1327Unions operand Region and target Region.
1328##
1329#Const kXOR_Op 3
1330#Line # target exclusive or with operand ##
1331Replaces target Region with area exclusive to both Regions.
1332##
1333#Const kReverseDifference_Op 4
1334#Line # operand minus target ##
1335Subtracts target Region from operand Region.
1336##
1337#Const kReplace_Op 5
1338#Line # replace target with operand ##
1339Replaces target Region with operand Region.
1340##
1341#Const kLastOp 5
1342#Line # last operator ##
1343##
1344
1345#Example
1346    SkRegion operand({35, 35, 85, 85});
1347    const char* labels[] = {"difference", "intersect", "union", "xor", "reverse diff", "replace"};
1348    int index = 0;
1349    SkPaint paint;
1350    for (auto op : { SkRegion::kDifference_Op, SkRegion::kIntersect_Op, SkRegion::kUnion_Op,
1351                     SkRegion::kXOR_Op, SkRegion::kReverseDifference_Op, SkRegion::kReplace_Op } ) {
1352        SkRegion target({10, 10, 60, 60});
1353        target.op(operand, op);
1354        canvas->drawRegion(target, paint);
1355        canvas->drawString(labels[index++], 40, 100, paint);
1356        canvas->translate(80, 0);
1357        if (SkRegion::kUnion_Op == op) {
1358            canvas->translate(-240, 120);
1359        }
1360    }
1361##
1362
1363#SeeAlso SkPathOp
1364
1365#Enum ##
1366
1367# ------------------------------------------------------------------------------
1368
1369#Const kOpCnt 6
1370#Line # number of operators defined ##
1371May be used to verify that Op is a legal value.
1372#Const ##
1373
1374# ------------------------------------------------------------------------------
1375
1376#Method bool op(const SkIRect& rect, Op op)
1377#In Transform
1378#Line # applies binary operator ##
1379#Populate
1380
1381#Example
1382#Height 128
1383    SkPaint paint;
1384    paint.setTextSize(128);
1385    SkPath xPath;
1386    paint.getTextPath("X", 1, 20, 110, &xPath);
1387    SkRegion xRegion;
1388    SkIRect drawBounds = {0, 0, 128, 128};
1389    xRegion.setPath(xPath, SkRegion(drawBounds));
1390    xRegion.op(drawBounds, SkRegion::kReverseDifference_Op);
1391    canvas->drawRegion(xRegion, paint);
1392##
1393
1394#SeeAlso setRects Op
1395
1396#Method ##
1397
1398# ------------------------------------------------------------------------------
1399
1400#Method bool op(int left, int top, int right, int bottom, Op op)
1401#Populate
1402
1403#Example
1404#Duration 4
1405#Height 128
1406    SkPaint paint;
1407    paint.setTextSize(128);
1408    SkPath xPath;
1409    paint.getTextPath("X", 1, 20, 110, &xPath);
1410    SkRegion xRegion;
1411    SkIRect drawBounds = {0, 0, 128, 128};
1412    xRegion.setPath(xPath, SkRegion(drawBounds));
1413    xRegion.op(drawBounds.fLeft + frame * drawBounds.width(), drawBounds.fTop,
1414               drawBounds.fRight, drawBounds.fBottom, SkRegion::kReverseDifference_Op);
1415    canvas->drawRegion(xRegion, paint);
1416##
1417
1418#SeeAlso setRects Op
1419
1420#Method ##
1421
1422# ------------------------------------------------------------------------------
1423
1424#Method bool op(const SkRegion& rgn, Op op)
1425#Populate
1426
1427#Example
1428#Duration 4
1429#Height 128
1430    SkPaint paint;
1431    paint.setTextSize(128);
1432    SkPath xPath, opPath;
1433    paint.getTextPath("X", 1, 20, 110, &xPath);
1434    opPath.addCircle(64, 64, frame * 64);
1435    SkRegion xRegion, opRegion;
1436    SkIRect drawBounds = {0, 0, 128, 128};
1437    opRegion.setPath(opPath, SkRegion(drawBounds));
1438    xRegion.setPath(xPath, SkRegion(drawBounds));
1439    xRegion.op(opRegion, SkRegion::kReverseDifference_Op);
1440    canvas->drawRegion(xRegion, paint);
1441##
1442
1443#SeeAlso setRects Op
1444
1445#Method ##
1446
1447# ------------------------------------------------------------------------------
1448
1449#Method bool op(const SkIRect& rect, const SkRegion& rgn, Op op)
1450#Populate
1451
1452#Example
1453#Duration 4
1454#Height 128
1455    SkPaint paint;
1456    paint.setTextSize(128);
1457    SkPath xPath, opPath;
1458    paint.getTextPath("X", 1, 20, 110, &xPath);
1459    opPath.addCircle(64, 64, frame * 64);
1460    SkRegion xRegion, opRegion, rectRegion;
1461    SkIRect drawBounds = {0, 0, 128, 128};
1462    opRegion.setPath(opPath, SkRegion(drawBounds));
1463    xRegion.setPath(xPath, SkRegion(drawBounds));
1464    drawBounds.inset(frame * drawBounds.width() / 2, 0);
1465    rectRegion.op(drawBounds, opRegion, SkRegion::kIntersect_Op);
1466    xRegion.op(rectRegion, SkRegion::kReverseDifference_Op);
1467    canvas->drawRegion(xRegion, paint);
1468##
1469
1470#SeeAlso setRects Op
1471
1472#Method ##
1473
1474# ------------------------------------------------------------------------------
1475
1476#Method bool op(const SkRegion& rgn, const SkIRect& rect, Op op)
1477#Populate
1478
1479#Example
1480#Duration 4
1481#Height 128
1482    SkPaint paint;
1483    paint.setTextSize(128);
1484    SkPath xPath, opPath;
1485    paint.getTextPath("X", 1, 20, 110, &xPath);
1486    opPath.addCircle(64, 64, frame * 64);
1487    SkRegion xRegion, opRegion, rectRegion;
1488    SkIRect drawBounds = {0, 0, 128, 128};
1489    opRegion.setPath(opPath, SkRegion(drawBounds));
1490    xRegion.setPath(xPath, SkRegion(drawBounds));
1491    drawBounds.inset(frame * drawBounds.width() / 2, 0);
1492    rectRegion.op(opRegion, drawBounds, SkRegion::kUnion_Op);
1493    xRegion.op(rectRegion, SkRegion::kReverseDifference_Op);
1494    canvas->drawRegion(xRegion, paint);
1495##
1496
1497#SeeAlso setRects Op
1498
1499#Method ##
1500
1501# ------------------------------------------------------------------------------
1502
1503#Method bool op(const SkRegion& rgna, const SkRegion& rgnb, Op op)
1504#Populate
1505
1506#Example
1507#Duration 4
1508#Height 128
1509    SkPaint paint;
1510    paint.setTextSize(128);
1511    SkPath xPath, opPath;
1512    paint.getTextPath("X", 1, 20, 110, &xPath);
1513    xPath.setFillType(SkPath::kInverseWinding_FillType);
1514    opPath.addCircle(64, 64, frame * 64);
1515    opPath.setFillType(SkPath::kInverseWinding_FillType);
1516    SkRegion xRegion, opRegion, rectRegion;
1517    SkIRect drawBounds = {0, 0, 128, 128};
1518    opRegion.setPath(opPath, SkRegion(drawBounds));
1519    xRegion.setPath(xPath, SkRegion(drawBounds));
1520    drawBounds.inset(frame * drawBounds.width() / 2, 0);
1521    rectRegion.setRect(drawBounds);
1522    rectRegion.op(xRegion, SkRegion::kIntersect_Op);
1523    xRegion.op(rectRegion, opRegion, SkRegion::kReverseDifference_Op);
1524    canvas->drawRegion(xRegion, paint);
1525##
1526
1527#SeeAlso setRects Op
1528
1529#Method ##
1530
1531# ------------------------------------------------------------------------------
1532
1533#Method size_t writeToMemory(void* buffer) const
1534#In Utility
1535#Line # writes to buffer ##
1536#Populate
1537
1538#Example
1539#Height 128
1540    SkPaint paint;
1541    paint.setTextSize(128);
1542    SkPath xPath;
1543    paint.getTextPath("X", 1, 20, 110, &xPath);
1544    SkIRect drawBounds = {0, 0, 128, 128};
1545    SkRegion xRegion;
1546    xRegion.setPath(xPath, SkRegion(drawBounds));
1547    size_t size = xRegion.writeToMemory(nullptr);
1548    sk_sp<SkData> data = SkData::MakeUninitialized(size);
1549    xRegion.writeToMemory(data->writable_data());
1550    SkRegion copy;
1551    copy.readFromMemory(data->data(), data->size());
1552    canvas->drawRegion(copy, paint);
1553##
1554
1555#SeeAlso readFromMemory
1556
1557#Method ##
1558
1559# ------------------------------------------------------------------------------
1560
1561#Method size_t readFromMemory(const void* buffer, size_t length)
1562#In Utility
1563#Line # reads from buffer ##
1564#Populate
1565
1566#Example
1567#Height 100
1568    SkRegion region({20, 20, 80, 80});
1569    size_t size = region.writeToMemory(nullptr);
1570    sk_sp<SkData> data = SkData::MakeUninitialized(size);
1571    region.writeToMemory(data->writable_data());
1572    SkRegion copy;
1573    copy.readFromMemory(data->data(), data->size());
1574    canvas->drawRegion(copy, SkPaint());
1575##
1576
1577#SeeAlso writeToMemory
1578
1579#Method ##
1580
1581#Class SkRegion ##
1582
1583#Topic Region ##
1584