LCOV - code coverage report
Current view: top level - layout/painting - DottedCornerFinder.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 1 251 0.4 %
Date: 2017-07-14 16:53:18 Functions: 0 14 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : // vim:cindent:ts=2:et:sw=2:
       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             : #include "DottedCornerFinder.h"
       8             : 
       9             : #include "mozilla/Move.h"
      10             : #include "BorderCache.h"
      11             : #include "BorderConsts.h"
      12             : 
      13             : namespace mozilla {
      14             : 
      15             : using namespace gfx;
      16             : 
      17             : static inline Float
      18           0 : Square(Float x)
      19             : {
      20           0 :   return x * x;
      21             : }
      22             : 
      23             : static Point
      24           0 : PointRotateCCW90(const Point& aP)
      25             : {
      26           0 :   return Point(aP.y, -aP.x);
      27             : }
      28             : 
      29             : struct BestOverlap
      30             : {
      31             :   Float overlap;
      32             :   size_t count;
      33             : 
      34           0 :   BestOverlap()
      35           0 :    : overlap(0.0f), count(0)
      36           0 :   {}
      37             : 
      38           0 :   BestOverlap(Float aOverlap, size_t aCount)
      39           0 :    : overlap(aOverlap), count(aCount)
      40           0 :   {}
      41             : };
      42             : 
      43             : static const size_t DottedCornerCacheSize = 256;
      44           3 : nsDataHashtable<FourFloatsHashKey, BestOverlap> DottedCornerCache;
      45             : 
      46           0 : DottedCornerFinder::DottedCornerFinder(const Bezier& aOuterBezier,
      47             :                                        const Bezier& aInnerBezier,
      48             :                                        Corner aCorner,
      49             :                                        Float aBorderRadiusX,
      50             :                                        Float aBorderRadiusY,
      51             :                                        const Point& aC0, Float aR0,
      52             :                                        const Point& aCn, Float aRn,
      53           0 :                                        const Size& aCornerDim)
      54             :  : mOuterBezier(aOuterBezier),
      55             :    mInnerBezier(aInnerBezier),
      56             :    mCorner(aCorner),
      57           0 :    mNormalSign((aCorner == C_TL || aCorner == C_BR) ? -1.0f : 1.0f),
      58             :    mC0(aC0), mCn(aCn),
      59           0 :    mR0(aR0), mRn(aRn), mMaxR(std::max(aR0, aRn)),
      60             :    mCenterCurveOrigin(mC0.x, mCn.y),
      61             :    mInnerCurveOrigin(mInnerBezier.mPoints[0].x, mInnerBezier.mPoints[3].y),
      62             :    mBestOverlap(0.0f),
      63             :    mHasZeroBorderWidth(false), mHasMore(true),
      64           0 :    mMaxCount(aCornerDim.width + aCornerDim.height),
      65             :    mType(OTHER),
      66           0 :    mI(0), mCount(0)
      67             : {
      68           0 :   NS_ASSERTION(mR0 > 0.0f || mRn > 0.0f,
      69             :                "At least one side should have non-zero radius.");
      70             : 
      71           0 :   mInnerWidth = fabs(mInnerBezier.mPoints[0].x - mInnerBezier.mPoints[3].x);
      72           0 :   mInnerHeight = fabs(mInnerBezier.mPoints[0].y - mInnerBezier.mPoints[3].y);
      73             : 
      74           0 :   DetermineType(aBorderRadiusX, aBorderRadiusY);
      75             : 
      76           0 :   Reset();
      77           0 : }
      78             : 
      79             : static bool
      80           0 : IsSingleCurve(Float aMinR, Float aMaxR,
      81             :               Float aMinBorderRadius, Float aMaxBorderRadius)
      82             : {
      83           0 :   return aMinR > 0.0f &&
      84           0 :          aMinBorderRadius > aMaxR * 4.0f &&
      85           0 :          aMinBorderRadius / aMaxBorderRadius > 0.5f;
      86             : }
      87             : 
      88             : void
      89           0 : DottedCornerFinder::DetermineType(Float aBorderRadiusX, Float aBorderRadiusY)
      90             : {
      91             :   // Calculate parameters for the center curve before swap.
      92           0 :   Float centerCurveWidth = fabs(mC0.x - mCn.x);
      93           0 :   Float centerCurveHeight = fabs(mC0.y - mCn.y);
      94           0 :   Point cornerPoint(mCn.x, mC0.y);
      95             : 
      96           0 :   bool swapped = false;
      97           0 :   if (mR0 < mRn) {
      98             :     // Always draw from wider side to thinner side.
      99           0 :     Swap(mC0, mCn);
     100           0 :     Swap(mR0, mRn);
     101           0 :     Swap(mInnerBezier.mPoints[0], mInnerBezier.mPoints[3]);
     102           0 :     Swap(mInnerBezier.mPoints[1], mInnerBezier.mPoints[2]);
     103           0 :     Swap(mOuterBezier.mPoints[0], mOuterBezier.mPoints[3]);
     104           0 :     Swap(mOuterBezier.mPoints[1], mOuterBezier.mPoints[2]);
     105           0 :     mNormalSign = -mNormalSign;
     106           0 :     swapped = true;
     107             :   }
     108             : 
     109             :   // See the comment at mType declaration for each condition.
     110             : 
     111           0 :   Float minR = std::min(mR0, mRn);
     112           0 :   Float minBorderRadius = std::min(aBorderRadiusX, aBorderRadiusY);
     113           0 :   Float maxBorderRadius = std::max(aBorderRadiusX, aBorderRadiusY);
     114           0 :   if (IsSingleCurve(minR, mMaxR, minBorderRadius, maxBorderRadius)) {
     115           0 :     if (mR0 == mRn) {
     116             :       Float borderLength;
     117           0 :       if (minBorderRadius == maxBorderRadius) {
     118           0 :         mType = PERFECT;
     119           0 :         borderLength = M_PI * centerCurveHeight / 2.0f;
     120             : 
     121           0 :         mCenterCurveR = centerCurveWidth;
     122             :       } else {
     123           0 :         mType = SINGLE_CURVE_AND_RADIUS;
     124             :         borderLength = GetQuarterEllipticArcLength(centerCurveWidth,
     125           0 :                                                    centerCurveHeight);
     126             :       }
     127             : 
     128           0 :       Float diameter = mR0 * 2.0f;
     129           0 :       size_t count = round(borderLength / diameter);
     130           0 :       if (count % 2) {
     131           0 :         count++;
     132             :       }
     133           0 :       mCount = count / 2 - 1;
     134           0 :       if (mCount > 0) {
     135           0 :         mBestOverlap = 1.0f - borderLength / (diameter * count);
     136             :       }
     137             :     } else {
     138           0 :       mType = SINGLE_CURVE;
     139             :     }
     140             :   }
     141             : 
     142           0 :   if (mType == SINGLE_CURVE_AND_RADIUS || mType == SINGLE_CURVE) {
     143           0 :     Size cornerSize(centerCurveWidth, centerCurveHeight);
     144           0 :     GetBezierPointsForCorner(&mCenterBezier, mCorner,
     145           0 :                              cornerPoint, cornerSize);
     146           0 :     if (swapped) {
     147           0 :       Swap(mCenterBezier.mPoints[0], mCenterBezier.mPoints[3]);
     148           0 :       Swap(mCenterBezier.mPoints[1], mCenterBezier.mPoints[2]);
     149             :     }
     150             :   }
     151             : 
     152           0 :   if (minR == 0.0f) {
     153           0 :     mHasZeroBorderWidth = true;
     154             :   }
     155             : 
     156           0 :   if ((mType == SINGLE_CURVE || mType == OTHER) && !mHasZeroBorderWidth) {
     157           0 :     FindBestOverlap(minR, minBorderRadius, maxBorderRadius);
     158             :   }
     159           0 : }
     160             : 
     161             : 
     162             : bool
     163           0 : DottedCornerFinder::HasMore(void) const
     164             : {
     165           0 :   if (mHasZeroBorderWidth) {
     166           0 :     return mI < mMaxCount && mHasMore;
     167             :   }
     168             : 
     169           0 :   return mI < mCount;
     170             : }
     171             : 
     172             : DottedCornerFinder::Result
     173           0 : DottedCornerFinder::Next(void)
     174             : {
     175           0 :   mI++;
     176             : 
     177           0 :   if (mType == PERFECT) {
     178           0 :     Float phi = mI * 4.0f * mR0 * (1 - mBestOverlap) / mCenterCurveR;
     179           0 :     if (mCorner == C_TL) {
     180           0 :       phi = -M_PI / 2.0f - phi;
     181           0 :     } else if (mCorner == C_TR) {
     182           0 :       phi = -M_PI / 2.0f + phi;
     183           0 :     } else if (mCorner == C_BR) {
     184           0 :       phi = M_PI / 2.0f - phi;
     185             :     } else {
     186           0 :       phi = M_PI / 2.0f + phi;
     187             :     }
     188             : 
     189           0 :     Point C(mCenterCurveOrigin.x + mCenterCurveR * cos(phi),
     190           0 :             mCenterCurveOrigin.y + mCenterCurveR * sin(phi));
     191           0 :     return DottedCornerFinder::Result(C, mR0);
     192             :   }
     193             : 
     194             :   // Find unfilled and filled circles.
     195           0 :   (void)FindNext(mBestOverlap);
     196           0 :   if (mHasMore) {
     197           0 :     (void)FindNext(mBestOverlap);
     198             :   }
     199             : 
     200           0 :   return Result(mLastC, mLastR);
     201             : }
     202             : 
     203             : void
     204           0 : DottedCornerFinder::Reset(void)
     205             : {
     206           0 :   mLastC = mC0;
     207           0 :   mLastR = mR0;
     208           0 :   mLastT = 0.0f;
     209           0 :   mHasMore = true;
     210           0 : }
     211             : 
     212             : void
     213           0 : DottedCornerFinder::FindPointAndRadius(Point& C, Float& r,
     214             :                                        const Point& innerTangent,
     215             :                                        const Point& normal, Float t)
     216             : {
     217             :   // Find radius for the given tangent point on the inner curve such that the
     218             :   // circle is also tangent to the outer curve.
     219             : 
     220           0 :   NS_ASSERTION(mType == OTHER, "Wrong mType");
     221             : 
     222           0 :   Float lower = 0.0f;
     223           0 :   Float upper = mMaxR;
     224           0 :   const Float DIST_MARGIN = 0.1f;
     225           0 :   for (size_t i = 0; i < MAX_LOOP; i++) {
     226           0 :     r = (upper + lower) / 2.0f;
     227           0 :     C = innerTangent + normal * r;
     228             : 
     229           0 :     Point Near = FindBezierNearestPoint(mOuterBezier, C, t);
     230           0 :     Float distSquare = (C - Near).LengthSquare();
     231             : 
     232           0 :     if (distSquare > Square(r + DIST_MARGIN)) {
     233           0 :       lower = r;
     234           0 :     } else if (distSquare < Square(r - DIST_MARGIN)) {
     235           0 :       upper = r;
     236             :     } else {
     237           0 :       break;
     238             :     }
     239             :   }
     240           0 : }
     241             : 
     242             : Float
     243           0 : DottedCornerFinder::FindNext(Float overlap)
     244             : {
     245           0 :   Float lower = mLastT;
     246           0 :   Float upper = 1.0f;
     247             :   Float t;
     248             : 
     249           0 :   Point C = mLastC;
     250           0 :   Float r = 0.0f;
     251             : 
     252           0 :   Float factor = (1.0f - overlap);
     253             : 
     254           0 :   Float circlesDist = 0.0f;
     255           0 :   Float expectedDist = 0.0f;
     256             : 
     257           0 :   const Float DIST_MARGIN = 0.1f;
     258           0 :   if (mType == SINGLE_CURVE_AND_RADIUS) {
     259           0 :     r = mR0;
     260             : 
     261           0 :     expectedDist = (r + mLastR) * factor;
     262             : 
     263             :     // Find C_i on the center curve.
     264           0 :     for (size_t i = 0; i < MAX_LOOP; i++) {
     265           0 :       t = (upper + lower) / 2.0f;
     266           0 :       C = GetBezierPoint(mCenterBezier, t);
     267             : 
     268             :       // Check overlap along arc.
     269           0 :       circlesDist = GetBezierLength(mCenterBezier, mLastT, t);
     270           0 :       if (circlesDist < expectedDist - DIST_MARGIN) {
     271           0 :         lower = t;
     272           0 :       } else if (circlesDist > expectedDist + DIST_MARGIN) {
     273           0 :         upper = t;
     274             :       } else {
     275           0 :         break;
     276             :       }
     277             :     }
     278           0 :   } else if (mType == SINGLE_CURVE) {
     279             :     // Find C_i on the center curve, and calculate r_i.
     280           0 :     for (size_t i = 0; i < MAX_LOOP; i++) {
     281           0 :       t = (upper + lower) / 2.0f;
     282           0 :       C = GetBezierPoint(mCenterBezier, t);
     283             : 
     284           0 :       Point Diff = GetBezierDifferential(mCenterBezier, t);
     285           0 :       Float DiffLength = Diff.Length();
     286           0 :       if (DiffLength == 0.0f) {
     287             :         // Basically this shouldn't happen.
     288             :         // If differential is 0, we cannot calculate tangent circle,
     289             :         // skip this point.
     290           0 :         t = (t + upper) / 2.0f;
     291           0 :         continue;
     292             :       }
     293             : 
     294           0 :       Point normal = PointRotateCCW90(Diff / DiffLength) * (-mNormalSign);
     295           0 :       r = CalculateDistanceToEllipticArc(C, normal, mInnerCurveOrigin,
     296             :                                          mInnerWidth, mInnerHeight);
     297             : 
     298             :       // Check overlap along arc.
     299           0 :       circlesDist = GetBezierLength(mCenterBezier, mLastT, t);
     300           0 :       expectedDist = (r + mLastR) * factor;
     301           0 :       if (circlesDist < expectedDist - DIST_MARGIN) {
     302           0 :         lower = t;
     303           0 :       } else if (circlesDist > expectedDist + DIST_MARGIN) {
     304           0 :         upper = t;
     305             :       } else {
     306           0 :         break;
     307             :       }
     308             :     }
     309             :   } else {
     310           0 :     Float distSquareMax = Square(mMaxR * 3.0f);
     311           0 :     Float circlesDistSquare = 0.0f;
     312             : 
     313             :     // Find C_i and r_i.
     314           0 :     for (size_t i = 0; i < MAX_LOOP; i++) {
     315           0 :       t = (upper + lower) / 2.0f;
     316           0 :       Point innerTangent = GetBezierPoint(mInnerBezier, t);
     317           0 :       if ((innerTangent - mLastC).LengthSquare() > distSquareMax) {
     318             :         // It's clear that this tangent point is too far, skip it.
     319           0 :         upper = t;
     320           0 :         continue;
     321             :       }
     322             : 
     323           0 :       Point Diff = GetBezierDifferential(mInnerBezier, t);
     324           0 :       Float DiffLength = Diff.Length();
     325           0 :       if (DiffLength == 0.0f) {
     326             :         // Basically this shouldn't happen.
     327             :         // If differential is 0, we cannot calculate tangent circle,
     328             :         // skip this point.
     329           0 :         t = (t + upper) / 2.0f;
     330           0 :         continue;
     331             :       }
     332             : 
     333           0 :       Point normal = PointRotateCCW90(Diff / DiffLength) * mNormalSign;
     334           0 :       FindPointAndRadius(C, r, innerTangent, normal, t);
     335             : 
     336             :       // Check overlap with direct distance.
     337           0 :       circlesDistSquare = (C - mLastC).LengthSquare();
     338           0 :       expectedDist = (r + mLastR) * factor;
     339           0 :       if (circlesDistSquare < Square(expectedDist - DIST_MARGIN)) {
     340           0 :         lower = t;
     341           0 :       } else if (circlesDistSquare > Square(expectedDist + DIST_MARGIN)) {
     342           0 :         upper = t;
     343             :       } else {
     344           0 :         break;
     345             :       }
     346             :     }
     347             : 
     348           0 :     circlesDist = sqrt(circlesDistSquare);
     349             :   }
     350             : 
     351           0 :   if (mHasZeroBorderWidth) {
     352             :     // When calculating circle around r=0, it may result in wrong radius that
     353             :     // is bigger than previous circle.  Detect it and stop calculating.
     354           0 :     const Float R_MARGIN = 0.1f;
     355           0 :     if (mLastR < R_MARGIN && r > mLastR) {
     356           0 :       mHasMore = false;
     357           0 :       mLastR = 0.0f;
     358           0 :       return 0.0f;
     359             :     }
     360             :   }
     361             : 
     362           0 :   mLastT = t;
     363           0 :   mLastC = C;
     364           0 :   mLastR = r;
     365             : 
     366           0 :   if (mHasZeroBorderWidth) {
     367           0 :     const Float T_MARGIN = 0.001f;
     368           0 :     if (mLastT >= 1.0f - T_MARGIN ||
     369           0 :         (mLastC - mCn).LengthSquare() < Square(mLastR)) {
     370           0 :       mHasMore = false;
     371             :     }
     372             :   }
     373             : 
     374           0 :   if (expectedDist == 0.0f) {
     375           0 :     return 0.0f;
     376             :   }
     377             : 
     378           0 :   return 1.0f - circlesDist * factor / expectedDist;
     379             : }
     380             : 
     381             : void
     382           0 : DottedCornerFinder::FindBestOverlap(Float aMinR, Float aMinBorderRadius,
     383             :                                     Float aMaxBorderRadius)
     384             : {
     385             :   // If overlap is not calculateable, find it with binary search,
     386             :   // such that there exists i that C_i == C_n with the given overlap.
     387             : 
     388             :   FourFloats key(aMinR, mMaxR,
     389           0 :                  aMinBorderRadius, aMaxBorderRadius);
     390           0 :   BestOverlap best;
     391           0 :   if (DottedCornerCache.Get(key, &best)) {
     392           0 :     mCount = best.count;
     393           0 :     mBestOverlap = best.overlap;
     394           0 :     return;
     395             :   }
     396             : 
     397           0 :   Float lower = 0.0f;
     398           0 :   Float upper = 0.5f;
     399             :   // Start from lower bound to find the minimum number of circles.
     400           0 :   Float overlap = 0.0f;
     401           0 :   mBestOverlap = overlap;
     402           0 :   size_t targetCount = 0;
     403             : 
     404           0 :   const Float OVERLAP_MARGIN = 0.1f;
     405           0 :   for (size_t j = 0; j < MAX_LOOP; j++) {
     406           0 :     Reset();
     407             : 
     408             :     size_t count;
     409             :     Float actualOverlap;
     410           0 :     if (!GetCountAndLastOverlap(overlap, &count, &actualOverlap)) {
     411           0 :       if (j == 0) {
     412           0 :         mCount = mMaxCount;
     413           0 :         break;
     414             :       }
     415             :     }
     416             : 
     417           0 :     if (j == 0) {
     418           0 :       if (count < 3 || (count == 3 && actualOverlap > 0.5f)) {
     419             :         // |count == 3 && actualOverlap > 0.5f| means there could be
     420             :         // a circle but it is too near from both ends.
     421             :         //
     422             :         // if actualOverlap == 0.0
     423             :         //               1       2       3
     424             :         //   +-------+-------+-------+-------+
     425             :         //   | ##### | ***** | ##### | ##### |
     426             :         //   |#######|*******|#######|#######|
     427             :         //   |###+###|***+***|###+###|###+###|
     428             :         //   |# C_0 #|* C_1 *|# C_2 #|# C_n #|
     429             :         //   | ##### | ***** | ##### | ##### |
     430             :         //   +-------+-------+-------+-------+
     431             :         //                   |
     432             :         //                   V
     433             :         //   +-------+---+-------+---+-------+
     434             :         //   | ##### |   | ##### |   | ##### |
     435             :         //   |#######|   |#######|   |#######|
     436             :         //   |###+###|   |###+###|   |###+###| Find the best overlap to place
     437             :         //   |# C_0 #|   |# C_1 #|   |# C_n #| C_1 at the middle of them
     438             :         //   | ##### |   | ##### |   | ##### |
     439             :         //   +-------+---+-------+---|-------+
     440             :         //
     441             :         // if actualOverlap == 0.5
     442             :         //               1       2     3
     443             :         //   +-------+-------+-------+---+
     444             :         //   | ##### | ***** | ##### |## |
     445             :         //   |#######|*******|##### C_n #|
     446             :         //   |###+###|***+***|###+###+###|
     447             :         //   |# C_0 #|* C_1 *|# C_2 #|###|
     448             :         //   | ##### | ***** | ##### |## |
     449             :         //   +-------+-------+-------+---+
     450             :         //                 |
     451             :         //                 V
     452             :         //   +-------+-+-------+-+-------+
     453             :         //   | ##### | | ##### | | ##### |
     454             :         //   |#######| |#######| |#######|
     455             :         //   |###+###| |###+###| |###+###| Even if we place C_1 at the middle
     456             :         //   |# C_0 #| |# C_1 #| |# C_n #| of them, it's too near from them
     457             :         //   | ##### | | ##### | | ##### |
     458             :         //   +-------+-+-------+-|-------+
     459             :         //                 |
     460             :         //                 V
     461             :         //   +-------+-----------+-------+
     462             :         //   | ##### |           | ##### |
     463             :         //   |#######|           |#######|
     464             :         //   |###+###|           |###+###| Do not draw any circle
     465             :         //   |# C_0 #|           |# C_n #|
     466             :         //   | ##### |           | ##### |
     467             :         //   +-------+-----------+-------+
     468           0 :         mCount = 0;
     469           0 :         break;
     470             :       }
     471             : 
     472             :       // targetCount should be 2n, as we're searching C_1 to C_n.
     473             :       //
     474             :       //   targetCount = 4
     475             :       //   mCount = 1
     476             :       //               1       2       3       4
     477             :       //   +-------+-------+-------+-------+-------+
     478             :       //   | ##### | ***** | ##### | ***** | ##### |
     479             :       //   |#######|*******|#######|*******|#######|
     480             :       //   |###+###|***+***|###+###|***+***|###+###|
     481             :       //   |# C_0 #|* C_1 *|# C_2 #|* C_3 *|# C_n #|
     482             :       //   | ##### | ***** | ##### | ***** | ##### |
     483             :       //   +-------+-------+-------+-------+-------+
     484             :       //                       1
     485             :       //
     486             :       //   targetCount = 6
     487             :       //   mCount = 2
     488             :       //               1       2       3       4       5       6
     489             :       //   +-------+-------+-------+-------+-------+-------+-------+
     490             :       //   | ##### | ***** | ##### | ***** | ##### | ***** | ##### |
     491             :       //   |#######|*******|#######|*******|#######|*******|#######|
     492             :       //   |###+###|***+***|###+###|***+***|###+###|***+***|###+###|
     493             :       //   |# C_0 #|* C_1 *|# C_2 #|* C_3 *|# C_4 #|* C_5 *|# C_n #|
     494             :       //   | ##### | ***** | ##### | ***** | ##### | ***** | ##### |
     495             :       //   +-------+-------+-------+-------+-------+-------+-------+
     496             :       //                       1               2
     497           0 :       if (count % 2) {
     498           0 :         targetCount = count + 1;
     499             :       } else {
     500           0 :         targetCount = count;
     501             :       }
     502             : 
     503           0 :       mCount = targetCount / 2 - 1;
     504             :     }
     505             : 
     506           0 :     if (count == targetCount) {
     507           0 :       mBestOverlap = overlap;
     508             : 
     509           0 :       if (fabs(actualOverlap - overlap) < OVERLAP_MARGIN) {
     510           0 :         break;
     511             :       }
     512             : 
     513             :       // We started from upper bound, no need to update range when j == 0.
     514           0 :       if (j > 0) {
     515           0 :         if (actualOverlap > overlap) {
     516           0 :           lower = overlap;
     517             :         } else {
     518           0 :           upper = overlap;
     519             :         }
     520             :       }
     521             :     } else {
     522             :       // |j == 0 && count != targetCount| means that |targetCount = count + 1|,
     523             :       // and we started from upper bound, no need to update range when j == 0.
     524           0 :       if (j > 0) {
     525           0 :         if (count > targetCount) {
     526           0 :           upper = overlap;
     527             :         } else {
     528           0 :           lower = overlap;
     529             :         }
     530             :       }
     531             :     }
     532             : 
     533           0 :     overlap = (upper + lower) / 2.0f;
     534             :   }
     535             : 
     536           0 :   if (DottedCornerCache.Count() > DottedCornerCacheSize) {
     537           0 :     DottedCornerCache.Clear();
     538             :   }
     539           0 :   DottedCornerCache.Put(key, BestOverlap(mBestOverlap, mCount));
     540             : }
     541             : 
     542             : bool
     543           0 : DottedCornerFinder::GetCountAndLastOverlap(Float aOverlap,
     544             :                                            size_t* aCount,
     545             :                                            Float* aActualOverlap)
     546             : {
     547             :   // Return the number of circles and the last circles' overlap for the
     548             :   // given overlap.
     549             : 
     550           0 :   Reset();
     551             : 
     552           0 :   const Float T_MARGIN = 0.001f;
     553           0 :   const Float DIST_MARGIN = 0.1f;
     554           0 :   const Float DIST_MARGIN_SQUARE = Square(DIST_MARGIN);
     555           0 :   for (size_t i = 0; i < mMaxCount; i++) {
     556           0 :     Float actualOverlap = FindNext(aOverlap);
     557           0 :     if (mLastT >= 1.0f - T_MARGIN ||
     558           0 :         (mLastC - mCn).LengthSquare() < DIST_MARGIN_SQUARE) {
     559           0 :       *aCount = i + 1;
     560           0 :       *aActualOverlap = actualOverlap;
     561           0 :       return true;
     562             :     }
     563             :   }
     564             : 
     565           0 :   return false;
     566             : }
     567             : 
     568             : } // namespace mozilla

Generated by: LCOV version 1.13