gfx/2d/PathHelpers.h

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
     2  * This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #ifndef MOZILLA_GFX_PATHHELPERS_H_
     7 #define MOZILLA_GFX_PATHHELPERS_H_
     9 #include "2D.h"
    10 #include "mozilla/Constants.h"
    12 namespace mozilla {
    13 namespace gfx {
    15 template <typename T>
    16 void ArcToBezier(T* aSink, const Point &aOrigin, const Size &aRadius,
    17                  float aStartAngle, float aEndAngle, bool aAntiClockwise)
    18 {
    19   Point startPoint(aOrigin.x + cos(aStartAngle) * aRadius.width,
    20                    aOrigin.y + sin(aStartAngle) * aRadius.height);
    22   aSink->LineTo(startPoint);
    24   // Clockwise we always sweep from the smaller to the larger angle, ccw
    25   // it's vice versa.
    26   if (!aAntiClockwise && (aEndAngle < aStartAngle)) {
    27     Float correction = Float(ceil((aStartAngle - aEndAngle) / (2.0f * M_PI)));
    28     aEndAngle += float(correction * 2.0f * M_PI);
    29   } else if (aAntiClockwise && (aStartAngle < aEndAngle)) {
    30     Float correction = (Float)ceil((aEndAngle - aStartAngle) / (2.0f * M_PI));
    31     aStartAngle += float(correction * 2.0f * M_PI);
    32   }
    34   // Sweeping more than 2 * pi is a full circle.
    35   if (!aAntiClockwise && (aEndAngle - aStartAngle > 2 * M_PI)) {
    36     aEndAngle = float(aStartAngle + 2.0f * M_PI);
    37   } else if (aAntiClockwise && (aStartAngle - aEndAngle > 2.0f * M_PI)) {
    38     aEndAngle = float(aStartAngle - 2.0f * M_PI);
    39   }
    41   // Calculate the total arc we're going to sweep.
    42   Float arcSweepLeft = fabs(aEndAngle - aStartAngle);
    44   Float sweepDirection = aAntiClockwise ? -1.0f : 1.0f;
    46   Float currentStartAngle = aStartAngle;
    48   while (arcSweepLeft > 0) {
    49     // We guarantee here the current point is the start point of the next
    50     // curve segment.
    51     Float currentEndAngle;
    53     if (arcSweepLeft > M_PI / 2.0f) {
    54       currentEndAngle = Float(currentStartAngle + M_PI / 2.0f * sweepDirection);
    55     } else {
    56       currentEndAngle = currentStartAngle + arcSweepLeft * sweepDirection;
    57     }
    59     Point currentStartPoint(aOrigin.x + cos(currentStartAngle) * aRadius.width,
    60                             aOrigin.y + sin(currentStartAngle) * aRadius.height);
    61     Point currentEndPoint(aOrigin.x + cos(currentEndAngle) * aRadius.width,
    62                           aOrigin.y + sin(currentEndAngle) * aRadius.height);
    64     // Calculate kappa constant for partial curve. The sign of angle in the
    65     // tangent will actually ensure this is negative for a counter clockwise
    66     // sweep, so changing signs later isn't needed.
    67     Float kappaFactor = (4.0f / 3.0f) * tan((currentEndAngle - currentStartAngle) / 4.0f);
    68     Float kappaX = kappaFactor * aRadius.width;
    69     Float kappaY = kappaFactor * aRadius.height;
    71     Point tangentStart(-sin(currentStartAngle), cos(currentStartAngle));
    72     Point cp1 = currentStartPoint;
    73     cp1 += Point(tangentStart.x * kappaX, tangentStart.y * kappaY);
    75     Point revTangentEnd(sin(currentEndAngle), -cos(currentEndAngle));
    76     Point cp2 = currentEndPoint;
    77     cp2 += Point(revTangentEnd.x * kappaX, revTangentEnd.y * kappaY);
    79     aSink->BezierTo(cp1, cp2, currentEndPoint);
    81     arcSweepLeft -= Float(M_PI / 2.0f);
    82     currentStartAngle = currentEndAngle;
    83   }
    84 }
    86 /**
    87  * Appends a path represending a rounded rectangle to the path being built by
    88  * aPathBuilder.
    89  *
    90  * aRect           The rectangle to append.
    91  * aCornerRadii    Contains the radii of the top-left, top-right, bottom-right
    92  *                 and bottom-left corners, in that order.
    93  * aDrawClockwise  If set to true, the path will start at the left of the top
    94  *                 left edge and draw clockwise. If set to false the path will
    95  *                 start at the right of the top left edge and draw counter-
    96  *                 clockwise.
    97  */
    98 GFX2D_API void AppendRoundedRectToPath(PathBuilder* aPathBuilder,
    99                                        const Rect& aRect,
   100                                        const Size(& aCornerRadii)[4],
   101                                        bool aDrawClockwise = true);
   103 /**
   104  * Appends a path represending an ellipse to the path being built by
   105  * aPathBuilder.
   106  *
   107  * The ellipse extends aDimensions.width / 2.0 in the horizontal direction
   108  * from aCenter, and aDimensions.height / 2.0 in the vertical direction.
   109  */
   110 GFX2D_API void AppendEllipseToPath(PathBuilder* aPathBuilder,
   111                                    const Point& aCenter,
   112                                    const Size& aDimensions);
   114 static inline bool
   115 UserToDevicePixelSnapped(Rect& aRect, const Matrix& aTransform)
   116 {
   117   Point p1 = aTransform * aRect.TopLeft();
   118   Point p2 = aTransform * aRect.TopRight();
   119   Point p3 = aTransform * aRect.BottomRight();
   121   // Check that the rectangle is axis-aligned. For an axis-aligned rectangle,
   122   // two opposite corners define the entire rectangle. So check if
   123   // the axis-aligned rectangle with opposite corners p1 and p3
   124   // define an axis-aligned rectangle whose other corners are p2 and p4.
   125   // We actually only need to check one of p2 and p4, since an affine
   126   // transform maps parallelograms to parallelograms.
   127   if (p2 == Point(p1.x, p3.y) || p2 == Point(p3.x, p1.y)) {
   128       p1.Round();
   129       p3.Round();
   131       aRect.MoveTo(Point(std::min(p1.x, p3.x), std::min(p1.y, p3.y)));
   132       aRect.SizeTo(Size(std::max(p1.x, p3.x) - aRect.X(),
   133                         std::max(p1.y, p3.y) - aRect.Y()));
   134       return true;
   135   }
   137   return false;
   138 }
   140 } // namespace gfx
   141 } // namespace mozilla
   143 #endif /* MOZILLA_GFX_PATHHELPERS_H_ */

mercurial