1 /*
2  * Copyright 2005 The Android Open Source Project
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 /* Generated by tools/bookmaker from include/core/SkRegion.h and docs/SkRegion_Reference.bmh
9    on 2018-08-10 12:59:44. Additional documentation and examples can be found at:
10    https://skia.org/user/api/SkRegion_Reference
11 
12    You may edit either file directly. Structural changes to public interfaces require
13    editing both files. After editing docs/SkRegion_Reference.bmh, run:
14        bookmaker -b docs -i include/core/SkRegion.h -p
15    to create an updated version of this file.
16  */
17 
18 #ifndef SkRegion_DEFINED
19 #define SkRegion_DEFINED
20 
21 #include "SkRect.h"
22 
23 class SkPath;
24 class SkRgnBuilder;
25 
26 /** \class SkRegion
27     SkRegion describes the set of pixels used to clip SkCanvas. SkRegion is compact,
28     efficiently storing a single integer rectangle, or a run length encoded array
29     of rectangles. SkRegion may reduce the current SkCanvas clip, or may be drawn as
30     one or more integer rectangles. SkRegion iterator returns the scan lines or
31     rectangles contained by it, optionally intersecting a bounding rectangle.
32 */
33 class SK_API SkRegion {
34     typedef int32_t RunType;
35 public:
36 
37     /** Constructs an empty SkRegion. SkRegion is set to empty bounds
38         at (0, 0) with zero width and height.
39 
40         @return  empty SkRegion
41     */
42     SkRegion();
43 
44     /** Constructs a copy of an existing region.
45         Copy constructor makes two regions identical by value. Internally, region and
46         the returned result share pointer values. The underlying SkRect array is
47         copied when modified.
48 
49         Creating a SkRegion copy is very efficient and never allocates memory.
50         SkRegion are always copied by value from the interface; the underlying shared
51         pointers are not exposed.
52 
53         @param region  SkRegion to copy by value
54         @return        copy of SkRegion
55     */
56     SkRegion(const SkRegion& region);
57 
58     /** Constructs a rectangular SkRegion matching the bounds of rect.
59 
60         @param rect  bounds of constructed SkRegion
61         @return      rectangular SkRegion
62     */
63     explicit SkRegion(const SkIRect& rect);
64 
65     /** Releases ownership of any shared data and deletes data if SkRegion is sole owner.
66     */
67     ~SkRegion();
68 
69     /** Constructs a copy of an existing region.
70         Makes two regions identical by value. Internally, region and
71         the returned result share pointer values. The underlying SkRect array is
72         copied when modified.
73 
74         Creating a SkRegion copy is very efficient and never allocates memory.
75         SkRegion are always copied by value from the interface; the underlying shared
76         pointers are not exposed.
77 
78         @param region  SkRegion to copy by value
79         @return        SkRegion to copy by value
80     */
81     SkRegion& operator=(const SkRegion& region);
82 
83     /** Compares SkRegion and other; returns true if they enclose exactly
84         the same area.
85 
86         @param other  SkRegion to compare
87         @return       true if SkRegion pair are equivalent
88     */
89     bool operator==(const SkRegion& other) const;
90 
91     /** Compares SkRegion and other; returns true if they do not enclose the same area.
92 
93         @param other  SkRegion to compare
94         @return       true if SkRegion pair are not equivalent
95     */
96     bool operator!=(const SkRegion& other) const {
97         return !(*this == other);
98     }
99 
100     /** Sets SkRegion to src, and returns true if src bounds is not empty.
101         This makes SkRegion and src identical by value. Internally,
102         SkRegion and src share pointer values. The underlying SkRect array is
103         copied when modified.
104 
105         Creating a SkRegion copy is very efficient and never allocates memory.
106         SkRegion are always copied by value from the interface; the underlying shared
107         pointers are not exposed.
108 
109         @param src  SkRegion to copy
110         @return     copy of src
111     */
set(const SkRegion & src)112     bool set(const SkRegion& src) {
113         *this = src;
114         return !this->isEmpty();
115     }
116 
117     /** Exchanges SkIRect array of SkRegion and other. swap() internally exchanges pointers,
118         so it is lightweight and does not allocate memory.
119 
120         swap() usage has largely been replaced by operator=(const SkRegion& region).
121         SkPath do not copy their content on assignment until they are written to,
122         making assignment as efficient as swap().
123 
124         @param other  operator=(const SkRegion& region) set
125     */
126     void swap(SkRegion& other);
127 
128     /** Returns true if SkRegion is empty.
129         Empty SkRegion has bounds width or height less than or equal to zero.
130         SkRegion() constructs empty SkRegion; setEmpty()
131         and setRect() with dimensionless data make SkRegion empty.
132 
133         @return  true if bounds has no width or height
134     */
isEmpty()135     bool isEmpty() const { return fRunHead == emptyRunHeadPtr(); }
136 
137     /** Returns true if SkRegion is one SkIRect with positive dimensions.
138 
139         @return  true if SkRegion contains one SkIRect
140     */
isRect()141     bool isRect() const { return fRunHead == kRectRunHeadPtr; }
142 
143     /** Returns true if SkRegion is described by more than one rectangle.
144 
145         @return  true if SkRegion contains more than one SkIRect
146     */
isComplex()147     bool isComplex() const { return !this->isEmpty() && !this->isRect(); }
148 
149     /** Returns minimum and maximum axes values of SkIRect array.
150         Returns (0, 0, 0, 0) if SkRegion is empty.
151 
152         @return  combined bounds of all SkIRect elements
153     */
getBounds()154     const SkIRect& getBounds() const { return fBounds; }
155 
156     /** Returns a value that increases with the number of
157         elements in SkRegion. Returns zero if SkRegion is empty.
158         Returns one if SkRegion equals SkIRect; otherwise, returns
159         value greater than one indicating that SkRegion is complex.
160 
161         Call to compare SkRegion for relative complexity.
162 
163         @return  relative complexity
164     */
165     int computeRegionComplexity() const;
166 
167     /** Appends outline of SkRegion to path.
168         Returns true if SkRegion is not empty; otherwise, returns false, and leaves path
169         unmodified.
170 
171         @param path  SkPath to append to
172         @return      true if path changed
173     */
174     bool getBoundaryPath(SkPath* path) const;
175 
176     /** Constructs an empty SkRegion. SkRegion is set to empty bounds
177         at (0, 0) with zero width and height. Always returns false.
178 
179         @return  false
180     */
181     bool setEmpty();
182 
183     /** Constructs a rectangular SkRegion matching the bounds of rect.
184         If rect is empty, constructs empty and returns false.
185 
186         @param rect  bounds of constructed SkRegion
187         @return      true if rect is not empty
188     */
189     bool setRect(const SkIRect& rect);
190 
191     /** Constructs SkRegion with bounds (left, top, right, bottom).
192         Returns true if left is less than right and top is less than bottom; otherwise,
193         constructs empty SkRegion and returns false.
194 
195         @param left    edge of bounds on x-axis
196         @param top     edge of bounds on y-axis
197         @param right   edge of bounds on x-axis
198         @param bottom  edge of bounds on y-axis
199         @return        rectangular SkRegion
200     */
setRect(int32_t left,int32_t top,int32_t right,int32_t bottom)201     bool setRect(int32_t left, int32_t top, int32_t right, int32_t bottom) {
202         return this->setRect({ left, top, right, bottom });
203     }
204 
205     /** Constructs SkRegion as the union of SkIRect in rects array. If count is
206         zero, constructs empty SkRegion. Returns false if constructed SkRegion is empty.
207 
208         May be faster than repeated calls to op().
209 
210         @param rects  array of SkIRect
211         @param count  array size
212         @return       true if constructed SkRegion is not empty
213     */
214     bool setRects(const SkIRect rects[], int count);
215 
216     /** Constructs a copy of an existing region.
217         Makes two regions identical by value. Internally, region and
218         the returned result share pointer values. The underlying SkRect array is
219         copied when modified.
220 
221         Creating a SkRegion copy is very efficient and never allocates memory.
222         SkRegion are always copied by value from the interface; the underlying shared
223         pointers are not exposed.
224 
225         @param region  SkRegion to copy by value
226         @return        SkRegion to copy by value
227     */
228     bool setRegion(const SkRegion& region);
229 
230     /** Constructs SkRegion to match outline of path within clip.
231         Returns false if constructed SkRegion is empty.
232 
233         Constructed SkRegion draws the same pixels as path through clip when
234         anti-aliasing is disabled.
235 
236         @param path  SkPath providing outline
237         @param clip  SkRegion containing path
238         @return      true if constructed SkRegion is not empty
239     */
240     bool setPath(const SkPath& path, const SkRegion& clip);
241 
242     /** Returns true if SkRegion intersects rect.
243         Returns false if either rect or SkRegion is empty, or do not intersect.
244 
245         @param rect  SkIRect to intersect
246         @return      true if rect and SkRegion have area in common
247     */
248     bool intersects(const SkIRect& rect) const;
249 
250     /** Returns true if SkRegion intersects other.
251         Returns false if either other or SkRegion is empty, or do not intersect.
252 
253         @param other  SkRegion to intersect
254         @return       true if other and SkRegion have area in common
255     */
256     bool intersects(const SkRegion& other) const;
257 
258     /** Returns true if SkIPoint (x, y) is inside SkRegion.
259         Returns false if SkRegion is empty.
260 
261         @param x  test SkIPoint x-coordinate
262         @param y  test SkIPoint y-coordinate
263         @return   true if (x, y) is inside SkRegion
264     */
265     bool contains(int32_t x, int32_t y) const;
266 
267     /** Returns true if other is completely inside SkRegion.
268         Returns false if SkRegion or other is empty.
269 
270         @param other  SkIRect to contain
271         @return       true if other is inside SkRegion
272     */
273     bool contains(const SkIRect& other) const;
274 
275     /** Returns true if other is completely inside SkRegion.
276         Returns false if SkRegion or other is empty.
277 
278         @param other  SkRegion to contain
279         @return       true if other is inside SkRegion
280     */
281     bool contains(const SkRegion& other) const;
282 
283     /** Returns true if SkRegion is a single rectangle and contains r.
284         May return false even though SkRegion contains r.
285 
286         @param r  SkIRect to contain
287         @return   true quickly if r points are equal or inside
288     */
quickContains(const SkIRect & r)289     bool quickContains(const SkIRect& r) const {
290         return this->quickContains(r.fLeft, r.fTop, r.fRight, r.fBottom);
291     }
292 
293     /** Returns true if SkRegion is a single rectangle and contains SkIRect
294         (left, top, right, bottom).
295         Returns false if SkRegion is empty or SkIRect (left, top, right, bottom) is empty.
296         May return false even though SkRegion contains (left, top, right, bottom).
297 
298         @param left    edge of bounds on x-axis
299         @param top     edge of bounds on y-axis
300         @param right   edge of bounds on x-axis
301         @param bottom  edge of bounds on y-axis
302         @return        true quickly if SkIRect are equal or inside
303     */
quickContains(int32_t left,int32_t top,int32_t right,int32_t bottom)304     bool quickContains(int32_t left, int32_t top, int32_t right,
305                        int32_t bottom) const {
306         SkASSERT(this->isEmpty() == fBounds.isEmpty()); // valid region
307 
308         return left < right && top < bottom &&
309                fRunHead == kRectRunHeadPtr &&  // this->isRect()
310                /* fBounds.contains(left, top, right, bottom); */
311                fBounds.fLeft <= left && fBounds.fTop <= top &&
312                fBounds.fRight >= right && fBounds.fBottom >= bottom;
313     }
314 
315     /** Returns true if SkRegion does not intersect rect.
316         Returns true if rect is empty or SkRegion is empty.
317         May return false even though SkRegion does not intersect rect.
318 
319         @param rect  SkIRect to intersect
320         @return      true if rect does not intersect
321     */
quickReject(const SkIRect & rect)322     bool quickReject(const SkIRect& rect) const {
323         return this->isEmpty() || rect.isEmpty() ||
324                 !SkIRect::Intersects(fBounds, rect);
325     }
326 
327     /** Returns true if SkRegion does not intersect rgn.
328         Returns true if rgn is empty or SkRegion is empty.
329         May return false even though SkRegion does not intersect rgn.
330 
331         @param rgn  SkRegion to intersect
332         @return     true if rgn does not intersect
333     */
quickReject(const SkRegion & rgn)334     bool quickReject(const SkRegion& rgn) const {
335         return this->isEmpty() || rgn.isEmpty() ||
336                !SkIRect::Intersects(fBounds, rgn.fBounds);
337     }
338 
339     /** Offsets SkRegion by ivector (dx, dy). Has no effect if SkRegion is empty.
340 
341         @param dx  x-axis offset
342         @param dy  y-axis offset
343     */
translate(int dx,int dy)344     void translate(int dx, int dy) { this->translate(dx, dy, this); }
345 
346     /** Offsets SkRegion by ivector (dx, dy), writing result to dst. SkRegion may be passed
347         as dst parameter, translating SkRegion in place. Has no effect if dst is nullptr.
348         If SkRegion is empty, sets dst to empty.
349 
350         @param dx   x-axis offset
351         @param dy   y-axis offset
352         @param dst  translated result
353     */
354     void translate(int dx, int dy, SkRegion* dst) const;
355 
356     /** \enum SkRegion::Op
357         The logical operations that can be performed when combining two SkRegion.
358     */
359     enum Op {
360         kDifference_Op,                      //!< target minus operand
361         kIntersect_Op,                       //!< target intersected with operand
362         kUnion_Op,                           //!< target unioned with operand
363         kXOR_Op,                             //!< target exclusive or with operand
364         kReverseDifference_Op,               //!< operand minus target
365         kReplace_Op,                         //!< replace target with operand
366         kLastOp               = kReplace_Op, //!< last operator
367     };
368 
369     static const int kOpCnt = kLastOp + 1;
370 
371     /** Replaces SkRegion with the result of SkRegion op rect.
372         Returns true if replaced SkRegion is not empty.
373 
374         @param rect  SkIRect operand
375         @param op    operator, one of:
376                      kDifference_Op, kIntersect_Op, kUnion_Op, kXOR_Op, kReverseDifference_Op,
377                      kReplace_Op
378         @return      false if result is empty
379     */
op(const SkIRect & rect,Op op)380     bool op(const SkIRect& rect, Op op) {
381         if (this->isRect() && kIntersect_Op == op) {
382             if (!fBounds.intersect(rect)) {
383                 return this->setEmpty();
384             }
385             return true;
386         }
387         return this->op(*this, rect, op);
388     }
389 
390     /** Replaces SkRegion with the result of SkRegion op SkIRect (left, top, right, bottom).
391         Returns true if replaced SkRegion is not empty.
392 
393         @param left    edge of bounds on x-axis
394         @param top     edge of bounds on y-axis
395         @param right   edge of bounds on x-axis
396         @param bottom  edge of bounds on y-axis
397         @param op      operator, one of:
398                        kDifference_Op, kIntersect_Op, kUnion_Op, kXOR_Op, kReverseDifference_Op,
399                        kReplace_Op
400         @return        false if result is empty
401     */
op(int left,int top,int right,int bottom,Op op)402     bool op(int left, int top, int right, int bottom, Op op) {
403         SkIRect rect;
404         rect.set(left, top, right, bottom);
405         return this->op(*this, rect, op);
406     }
407 
408     /** Replaces SkRegion with the result of SkRegion op rgn.
409         Returns true if replaced SkRegion is not empty.
410 
411         @param rgn  SkRegion operand
412         @param op   operator, one of:
413                     kDifference_Op, kIntersect_Op, kUnion_Op, kXOR_Op, kReverseDifference_Op,
414                     kReplace_Op
415         @return     false if result is empty
416     */
op(const SkRegion & rgn,Op op)417     bool op(const SkRegion& rgn, Op op) { return this->op(*this, rgn, op); }
418 
419     /** Replaces SkRegion with the result of rect op rgn.
420         Returns true if replaced SkRegion is not empty.
421 
422         @param rect  SkIRect operand
423         @param rgn   SkRegion operand
424         @param op    operator, one of:
425                      kDifference_Op, kIntersect_Op, kUnion_Op, kXOR_Op, kReverseDifference_Op,
426                      kReplace_Op
427         @return      false if result is empty
428     */
429     bool op(const SkIRect& rect, const SkRegion& rgn, Op op);
430 
431     /** Replaces SkRegion with the result of rgn op rect.
432         Returns true if replaced SkRegion is not empty.
433 
434         @param rgn   SkRegion operand
435         @param rect  SkIRect operand
436         @param op    operator, one of:
437                      kDifference_Op, kIntersect_Op, kUnion_Op, kXOR_Op, kReverseDifference_Op,
438                      kReplace_Op
439         @return      false if result is empty
440     */
441     bool op(const SkRegion& rgn, const SkIRect& rect, Op op);
442 
443     /** Replaces SkRegion with the result of rgna op rgnb.
444         Returns true if replaced SkRegion is not empty.
445 
446         @param rgna  SkRegion operand
447         @param rgnb  SkRegion operand
448         @param op    operator, one of:
449                      kDifference_Op, kIntersect_Op, kUnion_Op, kXOR_Op, kReverseDifference_Op,
450                      kReplace_Op
451         @return      false if result is empty
452     */
453     bool op(const SkRegion& rgna, const SkRegion& rgnb, Op op);
454 
455 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
456     /** Private. Android framework only.
457 
458         @return  string representation of SkRegion
459     */
460     char* toString();
461 #endif
462 
463     /** \class SkRegion::Iterator
464         Returns sequence of rectangles, sorted along y-axis, then x-axis, that make
465         up SkRegion.
466     */
467     class SK_API Iterator {
468     public:
469 
470         /** Initializes SkRegion::Iterator with an empty SkRegion. done() on SkRegion::Iterator
471             returns true.
472             Call reset() to initialized SkRegion::Iterator at a later time.
473 
474             @return  empty SkRegion iterator
475         */
Iterator()476         Iterator() : fRgn(nullptr), fDone(true) {}
477 
478         /** Sets SkRegion::Iterator to return elements of SkIRect array in region.
479 
480             @param region  SkRegion to iterate
481             @return        SkRegion iterator
482         */
483         Iterator(const SkRegion& region);
484 
485         /** SkPoint SkRegion::Iterator to start of SkRegion.
486             Returns true if SkRegion was set; otherwise, returns false.
487 
488             @return  true if SkRegion was set
489         */
490         bool rewind();
491 
492         /** Resets iterator, using the new SkRegion.
493 
494             @param region  SkRegion to iterate
495         */
496         void reset(const SkRegion& region);
497 
498         /** Returns true if SkRegion::Iterator is pointing to final SkIRect in SkRegion.
499 
500             @return  true if data parsing is complete
501         */
done()502         bool done() const { return fDone; }
503 
504         /** Advances SkRegion::Iterator to next SkIRect in SkRegion if it is not done.
505         */
506         void next();
507 
508         /** Returns SkIRect element in SkRegion. Does not return predictable results if SkRegion
509             is empty.
510 
511             @return  part of SkRegion as SkIRect
512         */
rect()513         const SkIRect& rect() const { return fRect; }
514 
515         /** Returns SkRegion if set; otherwise, returns nullptr.
516 
517             @return  iterated SkRegion
518         */
rgn()519         const SkRegion* rgn() const { return fRgn; }
520 
521     private:
522         const SkRegion* fRgn;
523         const SkRegion::RunType*  fRuns;
524         SkIRect         fRect = {0, 0, 0, 0};
525         bool            fDone;
526     };
527 
528     /** \class SkRegion::Cliperator
529         Returns the sequence of rectangles, sorted along y-axis, then x-axis, that make
530         up SkRegion intersected with the specified clip rectangle.
531     */
532     class SK_API Cliperator {
533     public:
534 
535         /** Sets SkRegion::Cliperator to return elements of SkIRect array in SkRegion within clip.
536 
537             @param region  SkRegion to iterate
538             @param clip    bounds of iteration
539             @return        SkRegion iterator
540         */
541         Cliperator(const SkRegion& region, const SkIRect& clip);
542 
543         /** Returns true if SkRegion::Cliperator is pointing to final SkIRect in SkRegion.
544 
545             @return  true if data parsing is complete
546         */
done()547         bool done() { return fDone; }
548 
549         /** Advances iterator to next SkIRect in SkRegion contained by clip.
550         */
551         void  next();
552 
553         /** Returns SkIRect element in SkRegion, intersected with clip passed to
554             SkRegion::Cliperator constructor. Does not return predictable results if SkRegion
555             is empty.
556 
557             @return  part of SkRegion inside clip as SkIRect
558         */
rect()559         const SkIRect& rect() const { return fRect; }
560 
561     private:
562         Iterator    fIter;
563         SkIRect     fClip;
564         SkIRect     fRect = {0, 0, 0, 0};
565         bool        fDone;
566     };
567 
568     /** \class SkRegion::Spanerator
569         Returns the line segment ends within SkRegion that intersect a horizontal line.
570     */
571     class Spanerator {
572     public:
573 
574         /** Sets SkRegion::Spanerator to return line segments in SkRegion on scan line.
575 
576             @param region  SkRegion to iterate
577             @param y       horizontal line to intersect
578             @param left    bounds of iteration
579             @param right   bounds of iteration
580             @return        SkRegion iterator
581         */
582         Spanerator(const SkRegion& region, int y, int left, int right);
583 
584         /** Advances iterator to next span intersecting SkRegion within line segment provided
585             in constructor. Returns true if interval was found.
586 
587             @param left   pointer to span start; may be nullptr
588             @param right  pointer to span end; may be nullptr
589             @return       true if interval was found
590         */
591         bool next(int* left, int* right);
592 
593     private:
594         const SkRegion::RunType* fRuns;
595         int     fLeft, fRight;
596         bool    fDone;
597     };
598 
599     /** Writes SkRegion to buffer, and returns number of bytes written.
600         If buffer is nullptr, returns number number of bytes that would be written.
601 
602         @param buffer  storage for binary data
603         @return        size of SkRegion
604     */
605     size_t writeToMemory(void* buffer) const;
606 
607     /** Constructs SkRegion from buffer of size length. Returns bytes read.
608         Returned value will be multiple of four or zero if length was too small.
609 
610         @param buffer  storage for binary data
611         @param length  size of buffer
612         @return        bytes read
613     */
614     size_t readFromMemory(const void* buffer, size_t length);
615 
616 private:
617     static constexpr int kOpCount = kReplace_Op + 1;
618 
619     // T
620     // [B N L R S]
621     // S
622     static constexpr int kRectRegionRuns = 7;
623 
624     struct RunHead;
625 
emptyRunHeadPtr()626     static RunHead* emptyRunHeadPtr() { return (SkRegion::RunHead*) -1; }
627     static constexpr RunHead* kRectRunHeadPtr = nullptr;
628 
629     // allocate space for count runs
630     void allocateRuns(int count);
631     void allocateRuns(int count, int ySpanCount, int intervalCount);
632     void allocateRuns(const RunHead& src);
633 
634     SkDEBUGCODE(void dump() const;)
635 
636     SkIRect     fBounds;
637     RunHead*    fRunHead;
638 
639     void freeRuns();
640 
641     /**
642      *  Return the runs from this region, consing up fake runs if the region
643      *  is empty or a rect. In those 2 cases, we use tmpStorage to hold the
644      *  run data.
645      */
646     const RunType*  getRuns(RunType tmpStorage[], int* intervals) const;
647 
648     // This is called with runs[] that do not yet have their interval-count
649     // field set on each scanline. That is computed as part of this call
650     // (inside ComputeRunBounds).
651     bool setRuns(RunType runs[], int count);
652 
653     int count_runtype_values(int* itop, int* ibot) const;
654 
655     bool isValid() const;
656 
657     static void BuildRectRuns(const SkIRect& bounds,
658                               RunType runs[kRectRegionRuns]);
659 
660     // If the runs define a simple rect, return true and set bounds to that
661     // rect. If not, return false and ignore bounds.
662     static bool RunsAreARect(const SkRegion::RunType runs[], int count,
663                              SkIRect* bounds);
664 
665     /**
666      *  If the last arg is null, just return if the result is non-empty,
667      *  else store the result in the last arg.
668      */
669     static bool Oper(const SkRegion&, const SkRegion&, SkRegion::Op, SkRegion*);
670 
671     friend struct RunHead;
672     friend class Iterator;
673     friend class Spanerator;
674     friend class SkRegionPriv;
675     friend class SkRgnBuilder;
676     friend class SkFlatRegion;
677 };
678 
679 #endif
680