Home | History | Annotate | Download | only in graphics
      1 /*
      2  * Copyright (C) 2006 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.graphics;
     18 
     19 import android.os.Parcel;
     20 import android.os.Parcelable;
     21 
     22 public class Region implements Parcelable {
     23     /**
     24      * @hide
     25      */
     26     public final int mNativeRegion;
     27 
     28     // the native values for these must match up with the enum in SkRegion.h
     29     public enum Op {
     30         DIFFERENCE(0),
     31         INTERSECT(1),
     32         UNION(2),
     33         XOR(3),
     34         REVERSE_DIFFERENCE(4),
     35         REPLACE(5);
     36 
     37         Op(int nativeInt) {
     38             this.nativeInt = nativeInt;
     39         }
     40 
     41         /**
     42          * @hide
     43          */
     44         public final int nativeInt;
     45     }
     46 
     47     /** Create an empty region
     48     */
     49     public Region() {
     50         this(nativeConstructor());
     51     }
     52 
     53     /** Return a copy of the specified region
     54     */
     55     public Region(Region region) {
     56         this(nativeConstructor());
     57         nativeSetRegion(mNativeRegion, region.mNativeRegion);
     58     }
     59 
     60     /** Return a region set to the specified rectangle
     61     */
     62     public Region(Rect r) {
     63         mNativeRegion = nativeConstructor();
     64         nativeSetRect(mNativeRegion, r.left, r.top, r.right, r.bottom);
     65     }
     66 
     67     /** Return a region set to the specified rectangle
     68     */
     69     public Region(int left, int top, int right, int bottom) {
     70         mNativeRegion = nativeConstructor();
     71         nativeSetRect(mNativeRegion, left, top, right, bottom);
     72     }
     73 
     74     /** Set the region to the empty region
     75     */
     76     public void setEmpty() {
     77         nativeSetRect(mNativeRegion, 0, 0, 0, 0);
     78     }
     79 
     80     /** Set the region to the specified region.
     81     */
     82     public boolean set(Region region) {
     83         return nativeSetRegion(mNativeRegion, region.mNativeRegion);
     84     }
     85 
     86     /** Set the region to the specified rectangle
     87     */
     88     public boolean set(Rect r) {
     89         return nativeSetRect(mNativeRegion, r.left, r.top, r.right, r.bottom);
     90     }
     91 
     92     /** Set the region to the specified rectangle
     93     */
     94     public boolean set(int left, int top, int right, int bottom) {
     95         return nativeSetRect(mNativeRegion, left, top, right, bottom);
     96     }
     97 
     98     /**
     99      * Set the region to the area described by the path and clip.
    100      * Return true if the resulting region is non-empty. This produces a region
    101      * that is identical to the pixels that would be drawn by the path
    102      * (with no antialiasing).
    103      */
    104     public boolean setPath(Path path, Region clip) {
    105         return nativeSetPath(mNativeRegion, path.ni(), clip.mNativeRegion);
    106     }
    107 
    108     /**
    109      * Return true if this region is empty
    110      */
    111     public native boolean isEmpty();
    112 
    113     /**
    114      * Return true if the region contains a single rectangle
    115      */
    116     public native boolean isRect();
    117 
    118     /**
    119      * Return true if the region contains more than one rectangle
    120      */
    121     public native boolean isComplex();
    122 
    123     /**
    124      * Return a new Rect set to the bounds of the region. If the region is
    125      * empty, the Rect will be set to [0, 0, 0, 0]
    126      */
    127     public Rect getBounds() {
    128         Rect r = new Rect();
    129         nativeGetBounds(mNativeRegion, r);
    130         return r;
    131     }
    132 
    133     /**
    134      * Set the Rect to the bounds of the region. If the region is empty, the
    135      * Rect will be set to [0, 0, 0, 0]
    136      */
    137     public boolean getBounds(Rect r) {
    138         if (r == null) {
    139             throw new NullPointerException();
    140         }
    141         return nativeGetBounds(mNativeRegion, r);
    142     }
    143 
    144     /**
    145      * Return the boundary of the region as a new Path. If the region is empty,
    146      * the path will also be empty.
    147      */
    148     public Path getBoundaryPath() {
    149         Path path = new Path();
    150         nativeGetBoundaryPath(mNativeRegion, path.ni());
    151         return path;
    152     }
    153 
    154     /**
    155      * Set the path to the boundary of the region. If the region is empty, the
    156      * path will also be empty.
    157      */
    158     public boolean getBoundaryPath(Path path) {
    159         return nativeGetBoundaryPath(mNativeRegion, path.ni());
    160     }
    161 
    162     /**
    163      * Return true if the region contains the specified point
    164      */
    165     public native boolean contains(int x, int y);
    166 
    167     /**
    168      * Return true if the region is a single rectangle (not complex) and it
    169      * contains the specified rectangle. Returning false is not a guarantee
    170      * that the rectangle is not contained by this region, but return true is a
    171      * guarantee that the rectangle is contained by this region.
    172      */
    173     public boolean quickContains(Rect r) {
    174         return quickContains(r.left, r.top, r.right, r.bottom);
    175     }
    176 
    177     /**
    178      * Return true if the region is a single rectangle (not complex) and it
    179      * contains the specified rectangle. Returning false is not a guarantee
    180      * that the rectangle is not contained by this region, but return true is a
    181      * guarantee that the rectangle is contained by this region.
    182      */
    183     public native boolean quickContains(int left, int top, int right,
    184                                         int bottom);
    185 
    186     /**
    187      * Return true if the region is empty, or if the specified rectangle does
    188      * not intersect the region. Returning false is not a guarantee that they
    189      * intersect, but returning true is a guarantee that they do not.
    190      */
    191     public boolean quickReject(Rect r) {
    192         return quickReject(r.left, r.top, r.right, r.bottom);
    193     }
    194 
    195     /**
    196      * Return true if the region is empty, or if the specified rectangle does
    197      * not intersect the region. Returning false is not a guarantee that they
    198      * intersect, but returning true is a guarantee that they do not.
    199      */
    200     public native boolean quickReject(int left, int top, int right, int bottom);
    201 
    202     /**
    203      * Return true if the region is empty, or if the specified region does not
    204      * intersect the region. Returning false is not a guarantee that they
    205      * intersect, but returning true is a guarantee that they do not.
    206      */
    207     public native boolean quickReject(Region rgn);
    208 
    209     /**
    210      * Translate the region by [dx, dy]. If the region is empty, do nothing.
    211      */
    212     public void translate(int dx, int dy) {
    213         translate(dx, dy, null);
    214     }
    215 
    216     /**
    217      * Set the dst region to the result of translating this region by [dx, dy].
    218      * If this region is empty, then dst will be set to empty.
    219      */
    220     public native void translate(int dx, int dy, Region dst);
    221 
    222     /**
    223      * Scale the region by the given scale amount. This re-constructs new region by
    224      * scaling the rects that this region consists of. New rectis are computed by scaling
    225      * coordinates by float, then rounded by roundf() function to integers. This may results
    226      * in less internal rects if 0 < scale < 1. Zero and Negative scale result in
    227      * an empty region. If this region is empty, do nothing.
    228      *
    229      * @hide
    230      */
    231     public void scale(float scale) {
    232         scale(scale, null);
    233     }
    234 
    235     /**
    236      * Set the dst region to the result of scaling this region by the given scale amount.
    237      * If this region is empty, then dst will be set to empty.
    238      * @hide
    239      */
    240     public native void scale(float scale, Region dst);
    241 
    242     public final boolean union(Rect r) {
    243         return op(r, Op.UNION);
    244     }
    245 
    246     /**
    247      * Perform the specified Op on this region and the specified rect. Return
    248      * true if the result of the op is not empty.
    249      */
    250     public boolean op(Rect r, Op op) {
    251         return nativeOp(mNativeRegion, r.left, r.top, r.right, r.bottom,
    252                         op.nativeInt);
    253     }
    254 
    255     /**
    256      * Perform the specified Op on this region and the specified rect. Return
    257      * true if the result of the op is not empty.
    258      */
    259     public boolean op(int left, int top, int right, int bottom, Op op) {
    260         return nativeOp(mNativeRegion, left, top, right, bottom,
    261                         op.nativeInt);
    262     }
    263 
    264     /**
    265      * Perform the specified Op on this region and the specified region. Return
    266      * true if the result of the op is not empty.
    267      */
    268     public boolean op(Region region, Op op) {
    269         return op(this, region, op);
    270     }
    271 
    272     /**
    273      * Set this region to the result of performing the Op on the specified rect
    274      * and region. Return true if the result is not empty.
    275      */
    276     public boolean op(Rect rect, Region region, Op op) {
    277         return nativeOp(mNativeRegion, rect, region.mNativeRegion,
    278                         op.nativeInt);
    279     }
    280 
    281     /**
    282      * Set this region to the result of performing the Op on the specified
    283      * regions. Return true if the result is not empty.
    284      */
    285     public boolean op(Region region1, Region region2, Op op) {
    286         return nativeOp(mNativeRegion, region1.mNativeRegion,
    287                         region2.mNativeRegion, op.nativeInt);
    288     }
    289 
    290     public String toString() {
    291         return nativeToString(mNativeRegion);
    292     }
    293 
    294     //////////////////////////////////////////////////////////////////////////
    295 
    296     public static final Parcelable.Creator<Region> CREATOR
    297         = new Parcelable.Creator<Region>() {
    298             /**
    299             * Rebuild a Region previously stored with writeToParcel().
    300              * @param p    Parcel object to read the region from
    301              * @return a new region created from the data in the parcel
    302              */
    303             public Region createFromParcel(Parcel p) {
    304                 int ni = nativeCreateFromParcel(p);
    305                 if (ni == 0) {
    306                     throw new RuntimeException();
    307                 }
    308                 return new Region(ni);
    309             }
    310             public Region[] newArray(int size) {
    311                 return new Region[size];
    312             }
    313     };
    314 
    315     public int describeContents() {
    316         return 0;
    317     }
    318 
    319     /**
    320      * Write the region and its pixels to the parcel. The region can be
    321      * rebuilt from the parcel by calling CREATOR.createFromParcel().
    322      * @param p    Parcel object to write the region data into
    323      */
    324     public void writeToParcel(Parcel p, int flags) {
    325         if (!nativeWriteToParcel(mNativeRegion, p)) {
    326             throw new RuntimeException();
    327         }
    328     }
    329 
    330     @Override
    331     public boolean equals(Object obj) {
    332         if (obj == null || !(obj instanceof Region)) {
    333             return false;
    334         }
    335         Region peer = (Region) obj;
    336         return nativeEquals(mNativeRegion, peer.mNativeRegion);
    337     }
    338 
    339     protected void finalize() throws Throwable {
    340         try {
    341             nativeDestructor(mNativeRegion);
    342         } finally {
    343             super.finalize();
    344         }
    345     }
    346 
    347     Region(int ni) {
    348         if (ni == 0) {
    349             throw new RuntimeException();
    350         }
    351         mNativeRegion = ni;
    352     }
    353 
    354     /* add dummy parameter so constructor can be called from jni without
    355        triggering 'not cloneable' exception */
    356     private Region(int ni, int dummy) {
    357         this(ni);
    358     }
    359 
    360     final int ni() {
    361         return mNativeRegion;
    362     }
    363 
    364     private static native boolean nativeEquals(int native_r1, int native_r2);
    365 
    366     private static native int nativeConstructor();
    367     private static native void nativeDestructor(int native_region);
    368 
    369     private static native boolean nativeSetRegion(int native_dst,
    370                                                   int native_src);
    371     private static native boolean nativeSetRect(int native_dst, int left,
    372                                                 int top, int right, int bottom);
    373     private static native boolean nativeSetPath(int native_dst, int native_path,
    374                                                 int native_clip);
    375     private static native boolean nativeGetBounds(int native_region, Rect rect);
    376     private static native boolean nativeGetBoundaryPath(int native_region,
    377                                                         int native_path);
    378 
    379     private static native boolean nativeOp(int native_dst, int left, int top,
    380                                            int right, int bottom, int op);
    381     private static native boolean nativeOp(int native_dst, Rect rect,
    382                                            int native_region, int op);
    383     private static native boolean nativeOp(int native_dst, int native_region1,
    384                                            int native_region2, int op);
    385 
    386     private static native int nativeCreateFromParcel(Parcel p);
    387     private static native boolean nativeWriteToParcel(int native_region,
    388                                                       Parcel p);
    389 
    390     private static native String nativeToString(int native_region);
    391 }
    392