Home | History | Annotate | Download | only in api
      1 SkRegion
      2 ========
      3 
      4 *Regions - set operations with rectangles*
      5 
      6 <!-- Updated Mar 4, 2011 -->
      7 
      8 Regions are a highly compressed way to represent (integer) areas. Skia
      9 uses them to represent (internally) the current clip on the
     10 canvas. Regions take their inspiration from the data type with the
     11 same name on the original Macintosh (thank you Bill).
     12 
     13 Regions are opaque structures, but they can be queried via
     14 iterators. Best of all, they can be combined with other regions and
     15 with rectangles (which can be thought of as "simple" regions. If you
     16 remember Set operations from math class (intersection, union,
     17 difference, etc.), then you're all ready to use regions.
     18 
     19 <!--?prettify lang=cc?-->
     20 
     21     bool SkRegion::isEmpty();
     22     bool SkRegion::isRect();
     23     bool SkRegion::isComplex();
     24 
     25 Regions can be classified into one of three types: empty, rectangular,
     26 or complex.
     27 
     28 Empty regions are just that, empty. All empty regions are equal (using
     29 operator==). Compare this to rectangles (SkRect or SkIRect). Any
     30 rectangle with fLeft >= fRight or fTop >= fBottom is consider empty,
     31 but clearly there are different empty rectangles that are not equal.
     32 
     33 <!--?prettify lang=cc?-->
     34 
     35     SkRect a = { 0, 0, 0, 0 };
     36     SkRect b = { 1, 1, 1, 1 };
     37 
     38 Both a and b are empty, but they are definitely not equal to each
     39 other. However, with regions, all empty regions are equal. If you
     40 query its bounds, you will always get { 0, 0, 0, 0 }. Even if you
     41 translate it, it will still be all zeros.
     42 
     43 <!--?prettify lang=cc?-->
     44 
     45 <!--?prettify lang=cc?-->
     46 
     47     SkRegion a, b;   // regions default to empty
     48     assert(a == b);
     49     a.offset(10, 20);
     50     assert(a == b);
     51     assert(a.getBounds() == { 0, 0, 0, 0 });   // not legal C++, but you get the point
     52     assert(b.getBounds() == { 0, 0, 0, 0 });
     53 
     54 To initialize a region to something more interesting, use one of the
     55 set() methods
     56 
     57 <!--?prettify lang=cc?-->
     58 
     59     SkRegion a, b;
     60     a.setRect(10, 10, 50, 50);
     61     b.setRect(rect);    // see SkIRect
     62     c.setPath(path);   // see SkPath
     63 
     64 This is the first step that SkCanvas performs when one of its
     65 clip...() methods are called. The clip data is first transformed into
     66 device coordinates (see SkMatrix), and then a region is build from the
     67 data (either a rect or a path). The final step is to combine this new
     68 region with the existing clip using the specified operator.
     69 
     70 <!--?prettify lang=cc?-->
     71 
     72     enum Op {
     73         kUnion_Op,
     74         kIntersect_Op,
     75         kDifference_Op,
     76         kXor_Op,
     77         kReverseDifference_Op,
     78         kReplace_Op
     79     };
     80 
     81 By default, intersect op is used when a clip call is made, but the
     82 other operators are equally valid.
     83 
     84 <!--?prettify lang=cc?-->
     85 
     86     // returns true if the resulting clip is non-empty (i.e. drawing can
     87     // still occur)
     88     bool SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op) {
     89         SkRegion rgn;
     90     
     91         // peek at the CTM (current transformation matrix on the canvas)
     92         const SkMatrix& m = this->getTotalMatrix();
     93     
     94         if (m.rectStaysRect()) {    // check if a transformed rect can be
     95                                     // represented as another rect
     96 
     97             SkRect deviceRect;
     98             m.mapRect(&deviceRect, rect);
     99             SkIRect intRect;
    100             deviceRect.round(&intRect);
    101             rgn.setRect(intRect);
    102         } else {  // matrix rotates or skew (or is perspective)
    103             SkPath path;
    104             path.addRect(rect);
    105             path.transform(m);
    106             rgn.setPath(path);
    107         }
    108     
    109         // now combine the new region with the current one, using the specified *op*
    110         return fCurrentClip.op(rgn, op);
    111     }
    112