tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

DottedCornerFinder.h (14086B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #ifndef mozilla_DottedCornerFinder_h_
      8 #define mozilla_DottedCornerFinder_h_
      9 
     10 #include "gfxRect.h"
     11 #include "mozilla/gfx/2D.h"
     12 #include "mozilla/gfx/BezierUtils.h"
     13 
     14 namespace mozilla {
     15 
     16 // Calculate C_i and r_i for each filled/unfilled circles in dotted corner.
     17 // Returns circle with C_{2j} and r_{2j} where 0 < 2j < n.
     18 //
     19 //                            ____-----------+
     20 //                      __----  *****     ###|
     21 //                __----      *********  ####|
     22 //           __---  #####    ***********#####|
     23 //        _--     #########  *****+*****#####+ C_0
     24 //      _-       ########### *** C_1****#####|
     25 //     /         #####+#####  *********  ####|
     26 //    /       .  ### C_2 ###    *****     ###|
     27 //   |            #########       ____-------+
     28 //   |     .        #####____-----
     29 //  |              __----
     30 //  |    .       /
     31 // |           /
     32 // |  *****   |
     33 // | ******* |
     34 // |*********|
     35 // |****+****|
     36 // | C_{n-1} |
     37 // | ******* |
     38 // |  *****  |
     39 // |  #####  |
     40 // | ####### |
     41 // |#########|
     42 // +----+----+
     43 //     C_n
     44 
     45 class DottedCornerFinder {
     46  typedef mozilla::gfx::Bezier Bezier;
     47  typedef mozilla::gfx::Float Float;
     48  typedef mozilla::gfx::Point Point;
     49  typedef mozilla::gfx::Size Size;
     50 
     51 public:
     52  struct Result {
     53    // Center point of dot and its radius.
     54    Point C;
     55    Float r;
     56 
     57    Result(const Point& aC, Float aR) : C(aC), r(aR) { MOZ_ASSERT(aR >= 0); }
     58  };
     59 
     60  //                        aBorderRadiusX
     61  //                       aCornerDim.width
     62  //                     |<----------------->|
     63  //                     |                   | v
     64  //                   --+-------------___---+--
     65  //                   ^ |         __--      | |
     66  //                   | |       _-          | | aR0
     67  //                   | |     /         aC0 +--
     68  //                   | |   /               | ^
     69  //                   | |  |                |
     70  //  aBorderRadiusY   | | |             __--+
     71  // aCornerDim.height | ||            _-
     72  //                   | ||           /
     73  //                   | |           /
     74  //                   | |          |
     75  //                   | |          |
     76  //                   | |         |
     77  //                   | |         |
     78  //                   v |    aCn  |
     79  //                   --+----+----+
     80  //                     |    |
     81  //                     |<-->|
     82  //                      aRn
     83  //
     84  // aCornerDim and (aBorderRadiusX, aBorderRadiusY) can be different when
     85  // aBorderRadiusX is smaller than aRn*2 or
     86  // aBorderRadiusY is smaller than aR0*2.
     87  //
     88  //                                        aCornerDim.width
     89  //                                      |<----------------->|
     90  //                                      |                   |
     91  //                                      | aBorderRadiusX    |
     92  //                                      |<--------->|       |
     93  //                                      |           |       |
     94  //                   -------------------+-------__--+-------+--
     95  //                   ^                ^ |     _-            | ^
     96  //                   |                | |   /               | |
     97  //                   |                | |  /                | |
     98  //                   | aBorderRadiusY | | |                 | | aR0
     99  //                   |                | ||                  | |
    100  //                   |                | |                   | |
    101  // aCornerDim.height |                v |                   | v
    102  //                   |                --+               aC0 +--
    103  //                   |                  |                   |
    104  //                   |                  |                   |
    105  //                   |                  |                   |
    106  //                   |                  |                   |
    107  //                   |                  |                   |
    108  //                   v                  |        aCn        |
    109  //                   -------------------+---------+---------+
    110  //                                      |         |
    111  //                                      |<------->|
    112  //                                          aRn
    113  DottedCornerFinder(const Bezier& aOuterBezier, const Bezier& aInnerBezier,
    114                     mozilla::Corner aCorner, Float aBorderRadiusX,
    115                     Float aBorderRadiusY, const Point& aC0, Float aR0,
    116                     const Point& aCn, Float aRn, const Size& aCornerDim);
    117 
    118  bool HasMore(void) const;
    119  Result Next(void);
    120 
    121 private:
    122  static const size_t MAX_LOOP = 32;
    123 
    124  // Bezier control points for the outer curve, the inner curve, and a curve
    125  // that center points of circles are on (center curve).
    126  //
    127  //               ___---+ outer curve
    128  //           __--      |
    129  //         _-          |
    130  //       /        __---+ center curve
    131  //     /      __--     |
    132  //    |     /          |
    133  //   |    /        __--+ inner curve
    134  //  |    |       _-
    135  //  |    |      /
    136  // |     |     /
    137  // |    |     |
    138  // |    |     |
    139  // |    |    |
    140  // |    |    |
    141  // |    |    |
    142  // +----+----+
    143  Bezier mOuterBezier;
    144  Bezier mInnerBezier;
    145  Bezier mCenterBezier;
    146 
    147  mozilla::Corner mCorner;
    148 
    149  // Sign of the normal vector used in radius calculation, flipped depends on
    150  // corner and start and end radii.
    151  Float mNormalSign;
    152 
    153  // Center points and raii for start and end circles, mR0 >= mRn.
    154  // mMaxR = max(mR0, mRn)
    155  //
    156  //                           v
    157  //               ___---+------
    158  //           __--     #|#    | mRn
    159  //         _-        ##|##   |
    160  //       /           ##+## ---
    161  //     /              mCn    ^
    162  //    |               #|#
    163  //   |             __--+
    164  //  |            _-
    165  //  |           /
    166  // |           /
    167  // |          |
    168  // |          |
    169  // |  #####  |
    170  // | ####### |
    171  // |#########|
    172  // +----+----+
    173  // |## mC0 ##|
    174  // | ####### |
    175  // |  #####  |
    176  // |    |
    177  // |<-->|
    178  //
    179  //  mR0
    180  //
    181  Point mC0;
    182  Point mCn;
    183  Float mR0;
    184  Float mRn;
    185  Float mMaxR;
    186 
    187  // Parameters for the center curve with perfect circle and the inner curve.
    188  // The center curve doesn't necessarily share the origin with others.
    189  //
    190  //               ___---+
    191  //           __--      |
    192  //         _-          |
    193  //       /        __-+ |
    194  //     /      __--     |
    195  //    |     /          |
    196  //   |    /        __--+--
    197  //  |    |       _-    | ^
    198  //  |    |      /      | |
    199  // |     |     /       | |
    200  // |    |     |        | |
    201  // |    |     |        | | mInnerHeight
    202  // |    |    |         | |
    203  // |    +    |         | |
    204  // |         |         | v
    205  // +---------+---------+
    206  //           |         | mInnerCurveOrigin
    207  //           |<------->|
    208  //           mInnerWidth
    209  //
    210  //               ___---+
    211  //           __--
    212  //         _-
    213  //       /        __-+
    214  //     /      __--   |
    215  //    |     /        |
    216  //   |    /        __--+
    217  //  |    |       _-  |
    218  //  |    |      /    |
    219  // |     |     /     |
    220  // |    |     |      |
    221  // |    |     |      |
    222  // |    |    |       |
    223  // |    +--- | ------+
    224  // |    |    |       | mCenterCurveOrigin
    225  // +    |    +       |
    226  //      |            |
    227  //      |            |
    228  //      |            |
    229  //      |            |
    230  //      |<---------->|
    231  //       mCenterCurveR
    232  //
    233  Point mCenterCurveOrigin;
    234  Float mCenterCurveR;
    235  Point mInnerCurveOrigin;
    236  Float mInnerWidth;
    237  Float mInnerHeight;
    238 
    239  Point mLastC;
    240  Float mLastR;
    241  Float mLastT;
    242 
    243  // Overlap between two circles.
    244  // It uses arc length on PERFECT, SINGLE_CURVE_AND_RADIUS, and SINGLE_CURVE,
    245  // and direct distance on OTHER.
    246  Float mBestOverlap;
    247 
    248  // If one of border-widths is 0, do not calculate overlap, and draw circles
    249  // until it reaches the other side or exceeds mMaxCount.
    250  bool mHasZeroBorderWidth;
    251  bool mHasMore;
    252 
    253  // The maximum number of filled/unfilled circles.
    254  size_t mMaxCount;
    255 
    256  enum {
    257    //                      radius.width
    258    //                 |<----------------->|
    259    //                 |                   |
    260    //               --+-------------___---+----
    261    //               ^ |         __--     #|#  ^
    262    //               | |       _-        ##|## |
    263    //               | |     /           ##+## | top-width
    264    //               | |   /             ##|## |
    265    //               | |  |               #|#  v
    266    //               | | |             __--+----
    267    // radius.height | ||            _-
    268    //               | ||           /
    269    //               | |           /
    270    //               | |          |
    271    //               | |          |
    272    //               | |  #####  |
    273    //               | | ####### |
    274    //               v |#########|
    275    //               --+----+----+
    276    //                 |#########|
    277    //                 | ####### |
    278    //                 |  #####  |
    279    //                 |         |
    280    //                 |<------->|
    281    //                  left-width
    282 
    283    // * top-width == left-width
    284    // * radius.width == radius.height
    285    // * top-width < radius.width * 2
    286    //
    287    // All circles has same radii and are on single perfect circle's arc.
    288    // Overlap is known.
    289    //
    290    // Split the perfect circle's arc into 2n segments, each segment's length is
    291    // top-width * (1 - overlap).  Place each circle's center point C_i on each
    292    // end of the segment, each circle's radius r_i is top-width / 2
    293    //
    294    //                       #####
    295    //                      #######
    296    // perfect             #########
    297    // circle's          ___---+####
    298    // arc     ##### __--  ## C_0 ##
    299    //   |    #####_-       ###|###
    300    //   |   ####+####       ##|##
    301    //   |   ##/C_i ##         |
    302    //   |    |######          |
    303    //   |   | #####           |
    304    //   +->|                  |
    305    //     |                   |
    306    //   ##|##                 |
    307    //  ###|###                |
    308    // ####|####               |
    309    // ####+-------------------+
    310    // ## C_n ##
    311    //  #######
    312    //   #####
    313    PERFECT,
    314 
    315    // * top-width == left-width
    316    // * 0.5 < radius.width / radius.height < 2.0
    317    // * top-width < min(radius.width, radius.height) * 2
    318    //
    319    // All circles has same radii and are on single elliptic arc.
    320    // Overlap is known.
    321    //
    322    // Split the elliptic arc into 2n segments, each segment's length is
    323    // top-width * (1 - overlap).  Place each circle's center point C_i on each
    324    // end of the segment, each circle's radius r_i is top-width / 2
    325    //
    326    //                            #####
    327    //                           #######
    328    //             #####        #########
    329    //            #######   ____----+####
    330    // elliptic  ######__---    ## C_0 ##
    331    // arc       ##__+-###       ###|###
    332    //   |      / # C_i #         ##|##
    333    //   +--> /    #####            |
    334    //       |                      |
    335    //   ###|#                      |
    336    //  ###|###                     |
    337    // ####|####                    |
    338    // ####+------------------------+
    339    // ## C_n ##
    340    //  #######
    341    //   #####
    342    SINGLE_CURVE_AND_RADIUS,
    343 
    344    // * top-width != left-width
    345    // * 0 < min(top-width, left-width)
    346    // * 0.5 < radius.width / radius.height < 2.0
    347    // * max(top-width, left-width) < min(radius.width, radius.height) * 2
    348    //
    349    // All circles are on single elliptic arc.
    350    // Overlap is unknown.
    351    //
    352    // Place each circle's center point C_i on elliptic arc, each circle's
    353    // radius r_i is the distance between the center point and the inner curve.
    354    // The arc segment's length between C_i and C_{i-1} is
    355    // (r_i + r_{i-1}) * (1 - overlap).
    356    //
    357    //  outer curve
    358    //           /
    359    //          /
    360    //         /         / center curve
    361    //        / ####### /
    362    //       /##       /#
    363    //      +#        /  #
    364    //     /#        /    #
    365    //    / #   C_i /     #
    366    //   /  #      +      #  /
    367    //  /   #     /  \    # / inner curve
    368    //      #    /     \  #/
    369    //       #  /   r_i  \+
    370    //        #/       ##/
    371    //        / ####### /
    372    //                 /
    373    SINGLE_CURVE,
    374 
    375    // Other cases.
    376    // Circles are not on single elliptic arc.
    377    // Overlap are unknown.
    378    //
    379    // Place tangent point innerTangent on the inner curve and find circle's
    380    // center point C_i and radius r_i where the circle is also tangent to the
    381    // outer curve.
    382    // Distance between C_i and C_{i-1} is (r_i + r_{i-1}) * (1 - overlap).
    383    //
    384    //  outer curve
    385    //           /
    386    //          /
    387    //         /
    388    //        / #######
    389    //       /##       ##
    390    //      +#           #
    391    //     /# \           #
    392    //    / #    \        #
    393    //   /  #      +      #  /
    394    //  /   #   C_i  \    # / inner curve
    395    //      #          \  #/
    396    //       #      r_i  \+
    397    //        ##       ##/ innerTangent
    398    //          ####### /
    399    //                 /
    400    OTHER
    401  } mType;
    402 
    403  size_t mI;
    404  size_t mCount;
    405 
    406  // Determine mType from parameters.
    407  void DetermineType(Float aBorderRadiusX, Float aBorderRadiusY);
    408 
    409  // Reset calculation.
    410  void Reset(void);
    411 
    412  // Find radius for the given tangent point on the inner curve such that the
    413  // circle is also tangent to the outer curve.
    414  void FindPointAndRadius(Point& C, Float& r, const Point& innerTangent,
    415                          const Point& normal, Float t);
    416 
    417  // Find next dot.
    418  Float FindNext(Float overlap);
    419 
    420  // Find mBestOverlap for parameters.
    421  void FindBestOverlap(Float aMinR, Float aMinBorderRadius,
    422                       Float aMaxBorderRadius);
    423 
    424  // Fill corner with dots with given overlap, and return the number of dots
    425  // and last two dots's overlap.
    426  bool GetCountAndLastOverlap(Float aOverlap, size_t* aCount,
    427                              Float* aActualOverlap);
    428 };
    429 
    430 }  // namespace mozilla
    431 
    432 #endif /* mozilla_DottedCornerFinder_h_ */