gfx/skia/trunk/include/core/SkRRect.h

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     1 /*
     2  * Copyright 2012 Google Inc.
     3  *
     4  * Use of this source code is governed by a BSD-style license that can be
     5  * found in the LICENSE file.
     6  */
     8 #ifndef SkRRect_DEFINED
     9 #define SkRRect_DEFINED
    11 #include "SkRect.h"
    12 #include "SkPoint.h"
    14 class SkPath;
    15 class SkMatrix;
    17 // Path forward:
    18 //   core work
    19 //      add validate method (all radii positive, all radii sums < rect size, etc.)
    20 //      add contains(SkRect&)  - for clip stack
    21 //      add contains(SkRRect&) - for clip stack
    22 //      add heart rect computation (max rect inside RR)
    23 //      add 9patch rect computation
    24 //      add growToInclude(SkPath&)
    25 //   analysis
    26 //      use growToInclude to fit skp round rects & generate stats (RRs vs. real paths)
    27 //      check on # of rectorus's the RRs could handle
    28 //   rendering work
    29 //      update SkPath.addRRect() to only use quads
    30 //      add GM and bench
    31 //   further out
    32 //      detect and triangulate RRectorii rather than falling back to SW in Ganesh
    33 //
    35 /** \class SkRRect
    37     The SkRRect class represents a rounded rect with a potentially different
    38     radii for each corner. It does not have a constructor so must be
    39     initialized with one of the initialization functions (e.g., setEmpty,
    40     setRectRadii, etc.)
    42     This class is intended to roughly match CSS' border-*-*-radius capabilities.
    43     This means:
    44         If either of a corner's radii are 0 the corner will be square.
    45         Negative radii are not allowed (they are clamped to zero).
    46         If the corner curves overlap they will be proportionally reduced to fit.
    47 */
    48 class SK_API SkRRect {
    49 public:
    50     /**
    51      * Enum to capture the various possible subtypes of RR. Accessed
    52      * by type(). The subtypes become progressively less restrictive.
    53      */
    54     enum Type {
    55         // !< Internal indicator that the sub type must be computed.
    56         kUnknown_Type = -1,
    58         // !< The RR is empty
    59         kEmpty_Type,
    61         //!< The RR is actually a (non-empty) rect (i.e., at least one radius
    62         //!< at each corner is zero)
    63         kRect_Type,
    65         //!< The RR is actually a (non-empty) oval (i.e., all x radii are equal
    66         //!< and >= width/2 and all the y radii are equal and >= height/2
    67         kOval_Type,
    69         //!< The RR is non-empty and all the x radii are equal & all y radii
    70         //!< are equal but it is not an oval (i.e., there are lines between
    71         //!< the curves) nor a rect (i.e., both radii are non-zero)
    72         kSimple_Type,
    74         //!< A fully general (non-empty) RR. Some of the x and/or y radii are
    75         //!< different from the others and there must be one corner where
    76         //!< both radii are non-zero.
    77         kComplex_Type,
    78     };
    80     /**
    81      * Returns the RR's sub type.
    82      */
    83     Type getType() const {
    84         SkDEBUGCODE(this->validate();)
    86         if (kUnknown_Type == fType) {
    87             this->computeType();
    88         }
    89         SkASSERT(kUnknown_Type != fType);
    90         return fType;
    91     }
    93     Type type() const { return this->getType(); }
    95     inline bool isEmpty() const { return kEmpty_Type == this->getType(); }
    96     inline bool isRect() const { return kRect_Type == this->getType(); }
    97     inline bool isOval() const { return kOval_Type == this->getType(); }
    98     inline bool isSimple() const { return kSimple_Type == this->getType(); }
    99     inline bool isSimpleCircular() const {
   100         return this->isSimple() && fRadii[0].fX == fRadii[0].fY;
   101     }
   102     inline bool isComplex() const { return kComplex_Type == this->getType(); }
   104     bool allCornersCircular() const;
   106     /**
   107      * Are both x-radii the same on the two left corners, and similar for the top, right, and
   108      * bottom. When this is the case the four ellipse centers form a rectangle.
   109      */
   110     bool isNinePatch() const {
   111         return fRadii[kUpperLeft_Corner].fX == fRadii[kLowerLeft_Corner].fX &&
   112                fRadii[kUpperRight_Corner].fX == fRadii[kLowerRight_Corner].fX &&
   113                fRadii[kUpperLeft_Corner].fY == fRadii[kUpperRight_Corner].fY &&
   114                fRadii[kLowerLeft_Corner].fY == fRadii[kLowerRight_Corner].fY;
   115     }
   117     SkScalar width() const { return fRect.width(); }
   118     SkScalar height() const { return fRect.height(); }
   120     /**
   121      * Set this RR to the empty rectangle (0,0,0,0) with 0 x & y radii.
   122      */
   123     void setEmpty() {
   124         fRect.setEmpty();
   125         memset(fRadii, 0, sizeof(fRadii));
   126         fType = kEmpty_Type;
   128         SkDEBUGCODE(this->validate();)
   129     }
   131     /**
   132      * Set this RR to match the supplied rect. All radii will be 0.
   133      */
   134     void setRect(const SkRect& rect) {
   135         if (rect.isEmpty()) {
   136             this->setEmpty();
   137             return;
   138         }
   140         fRect = rect;
   141         memset(fRadii, 0, sizeof(fRadii));
   142         fType = kRect_Type;
   144         SkDEBUGCODE(this->validate();)
   145     }
   147     /**
   148      * Set this RR to match the supplied oval. All x radii will equal half the
   149      * width and all y radii will equal half the height.
   150      */
   151     void setOval(const SkRect& oval) {
   152         if (oval.isEmpty()) {
   153             this->setEmpty();
   154             return;
   155         }
   157         SkScalar xRad = SkScalarHalf(oval.width());
   158         SkScalar yRad = SkScalarHalf(oval.height());
   160         fRect = oval;
   161         for (int i = 0; i < 4; ++i) {
   162             fRadii[i].set(xRad, yRad);
   163         }
   164         fType = kOval_Type;
   166         SkDEBUGCODE(this->validate();)
   167     }
   169     /**
   170      * Initialize the RR with the same radii for all four corners.
   171      */
   172     void setRectXY(const SkRect& rect, SkScalar xRad, SkScalar yRad);
   174     /**
   175      * Initialize the RR with potentially different radii for all four corners.
   176      */
   177     void setRectRadii(const SkRect& rect, const SkVector radii[4]);
   179     // The radii are stored in UL, UR, LR, LL order.
   180     enum Corner {
   181         kUpperLeft_Corner,
   182         kUpperRight_Corner,
   183         kLowerRight_Corner,
   184         kLowerLeft_Corner
   185     };
   187     const SkRect& rect() const { return fRect; }
   188     const SkVector& radii(Corner corner) const { return fRadii[corner]; }
   189     const SkRect& getBounds() const { return fRect; }
   191     /**
   192      *  When a rrect is simple, all of its radii are equal. This returns one
   193      *  of those radii. This call requires the rrect to be non-complex.
   194      */
   195     const SkVector& getSimpleRadii() const {
   196         SkASSERT(!this->isComplex());
   197         return fRadii[0];
   198     }
   200     friend bool operator==(const SkRRect& a, const SkRRect& b) {
   201         return a.fRect == b.fRect &&
   202                SkScalarsEqual(a.fRadii[0].asScalars(),
   203                               b.fRadii[0].asScalars(), 8);
   204     }
   206     friend bool operator!=(const SkRRect& a, const SkRRect& b) {
   207         return a.fRect != b.fRect ||
   208                !SkScalarsEqual(a.fRadii[0].asScalars(),
   209                                b.fRadii[0].asScalars(), 8);
   210     }
   212     /**
   213      *  Call inset on the bounds, and adjust the radii to reflect what happens
   214      *  in stroking: If the corner is sharp (no curvature), leave it alone,
   215      *  otherwise we grow/shrink the radii by the amount of the inset. If a
   216      *  given radius becomes negative, it is pinned to 0.
   217      *
   218      *  It is valid for dst == this.
   219      */
   220     void inset(SkScalar dx, SkScalar dy, SkRRect* dst) const;
   222     void inset(SkScalar dx, SkScalar dy) {
   223         this->inset(dx, dy, this);
   224     }
   226     /**
   227      *  Call outset on the bounds, and adjust the radii to reflect what happens
   228      *  in stroking: If the corner is sharp (no curvature), leave it alone,
   229      *  otherwise we grow/shrink the radii by the amount of the inset. If a
   230      *  given radius becomes negative, it is pinned to 0.
   231      *
   232      *  It is valid for dst == this.
   233      */
   234     void outset(SkScalar dx, SkScalar dy, SkRRect* dst) const {
   235         this->inset(-dx, -dy, dst);
   236     }
   237     void outset(SkScalar dx, SkScalar dy) {
   238         this->inset(-dx, -dy, this);
   239     }
   241     /**
   242      * Translate the rrect by (dx, dy).
   243      */
   244     void offset(SkScalar dx, SkScalar dy) {
   245         fRect.offset(dx, dy);
   246     }
   248     /**
   249      *  Returns true if 'rect' is wholy inside the RR, and both
   250      *  are not empty.
   251      */
   252     bool contains(const SkRect& rect) const;
   254     SkDEBUGCODE(void validate() const;)
   256     enum {
   257         kSizeInMemory = 12 * sizeof(SkScalar)
   258     };
   260     /**
   261      *  Write the rrect into the specified buffer. This is guaranteed to always
   262      *  write kSizeInMemory bytes, and that value is guaranteed to always be
   263      *  a multiple of 4. Return kSizeInMemory.
   264      */
   265     size_t writeToMemory(void* buffer) const;
   267     /**
   268      * Reads the rrect from the specified buffer
   269      *
   270      * If the specified buffer is large enough, this will read kSizeInMemory bytes,
   271      * and that value is guaranteed to always be a multiple of 4.
   272      *
   273      * @param buffer Memory to read from
   274      * @param length Amount of memory available in the buffer
   275      * @return number of bytes read (must be a multiple of 4) or
   276      *         0 if there was not enough memory available
   277      */
   278     size_t readFromMemory(const void* buffer, size_t length);
   280     /**
   281      *  Transform by the specified matrix, and put the result in dst.
   282      *
   283      *  @param matrix SkMatrix specifying the transform. Must only contain
   284      *      scale and/or translate, or this call will fail.
   285      *  @param dst SkRRect to store the result. It is an error to use this,
   286      *      which would make this function no longer const.
   287      *  @return true on success, false on failure. If false, dst is unmodified.
   288      */
   289     bool transform(const SkMatrix& matrix, SkRRect* dst) const;
   291 private:
   292     SkRect fRect;
   293     // Radii order is UL, UR, LR, LL. Use Corner enum to index into fRadii[]
   294     SkVector fRadii[4];
   295     mutable Type fType;
   296     // TODO: add padding so we can use memcpy for flattening and not copy
   297     // uninitialized data
   299     void computeType() const;
   300     bool checkCornerContainment(SkScalar x, SkScalar y) const;
   302     // to access fRadii directly
   303     friend class SkPath;
   304 };
   306 #endif

mercurial