mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-01-26 06:38:36 +00:00
Bug 698318 - Share ArcToBezier code. r=jrmuizel
This commit is contained in:
parent
4fc2827fb5
commit
ed14f0aa74
@ -115,15 +115,12 @@
|
||||
#include "mozilla/ipc/DocumentRendererParent.h"
|
||||
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "mozilla/gfx/PathHelpers.h"
|
||||
|
||||
#ifdef XP_WIN
|
||||
#include "gfxWindowsPlatform.h"
|
||||
#endif
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
// windows.h (included by chromium code) defines this, in its infinite wisdom
|
||||
#undef DrawText
|
||||
|
||||
@ -440,6 +437,9 @@ public:
|
||||
STYLE_FILL,
|
||||
STYLE_MAX
|
||||
};
|
||||
|
||||
nsresult LineTo(const Point& aPoint);
|
||||
nsresult BezierTo(const Point& aCP1, const Point& aCP2, const Point& aCP3);
|
||||
|
||||
protected:
|
||||
nsresult InitializeWithTarget(DrawTarget *surface, PRInt32 width, PRInt32 height);
|
||||
@ -2314,10 +2314,16 @@ nsCanvasRenderingContext2DAzure::LineTo(float x, float y)
|
||||
|
||||
EnsureWritablePath();
|
||||
|
||||
return LineTo(Point(x, y));;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsCanvasRenderingContext2DAzure::LineTo(const Point& aPoint)
|
||||
{
|
||||
if (mPathBuilder) {
|
||||
mPathBuilder->LineTo(Point(x, y));
|
||||
mPathBuilder->LineTo(aPoint);
|
||||
} else {
|
||||
mDSPathBuilder->LineTo(mTarget->GetTransform() * Point(x, y));
|
||||
mDSPathBuilder->LineTo(mTarget->GetTransform() * aPoint);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
@ -2353,13 +2359,21 @@ nsCanvasRenderingContext2DAzure::BezierCurveTo(float cp1x, float cp1y,
|
||||
|
||||
EnsureWritablePath();
|
||||
|
||||
return BezierTo(Point(cp1x, cp1y), Point(cp2x, cp2y), Point(x, y));
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsCanvasRenderingContext2DAzure::BezierTo(const Point& aCP1,
|
||||
const Point& aCP2,
|
||||
const Point& aCP3)
|
||||
{
|
||||
if (mPathBuilder) {
|
||||
mPathBuilder->BezierTo(Point(cp1x, cp1y), Point(cp2x, cp2y), Point(x, y));
|
||||
mPathBuilder->BezierTo(aCP1, aCP2, aCP3);
|
||||
} else {
|
||||
Matrix transform = mTarget->GetTransform();
|
||||
mDSPathBuilder->BezierTo(transform * Point(cp1x, cp1y),
|
||||
transform * Point(cp2x, cp2y),
|
||||
transform * Point(x, y));
|
||||
mDSPathBuilder->BezierTo(transform * aCP1,
|
||||
transform * aCP2,
|
||||
transform * aCP3);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
@ -2460,83 +2474,7 @@ nsCanvasRenderingContext2DAzure::Arc(float x, float y,
|
||||
|
||||
EnsureWritablePath();
|
||||
|
||||
// We convert to Bezier curve here, since we need to be able to write in
|
||||
// device space, but a transformed arc is no longer representable by an arc.
|
||||
|
||||
Point startPoint(x + cos(startAngle) * r, y + sin(startAngle) * r);
|
||||
|
||||
if (mPathBuilder) {
|
||||
mPathBuilder->LineTo(startPoint);
|
||||
} else {
|
||||
mDSPathBuilder->LineTo(mTarget->GetTransform() * startPoint);
|
||||
}
|
||||
|
||||
// Clockwise we always sweep from the smaller to the larger angle, ccw
|
||||
// it's vice versa.
|
||||
if (!ccw && (endAngle < startAngle)) {
|
||||
Float correction = ceil((startAngle - endAngle) / (2.0f * M_PI));
|
||||
endAngle += correction * 2.0f * M_PI;
|
||||
} else if (ccw && (startAngle < endAngle)) {
|
||||
Float correction = ceil((endAngle - startAngle) / (2.0f * M_PI));
|
||||
startAngle += correction * 2.0f * M_PI;
|
||||
}
|
||||
|
||||
// Sweeping more than 2 * pi is a full circle.
|
||||
if (!ccw && (endAngle - startAngle > 2 * M_PI)) {
|
||||
endAngle = startAngle + 2.0f * M_PI;
|
||||
} else if (ccw && (startAngle - endAngle > 2.0f * M_PI)) {
|
||||
endAngle = startAngle - 2.0f * M_PI;
|
||||
}
|
||||
|
||||
// Calculate the total arc we're going to sweep.
|
||||
Float arcSweepLeft = abs(endAngle - startAngle);
|
||||
|
||||
Float sweepDirection = ccw ? -1.0f : 1.0f;
|
||||
|
||||
Float currentStartAngle = startAngle;
|
||||
|
||||
while (arcSweepLeft > 0) {
|
||||
// We guarantee here the current point is the start point of the next
|
||||
// curve segment.
|
||||
Float currentEndAngle;
|
||||
|
||||
if (arcSweepLeft > M_PI / 2.0f) {
|
||||
currentEndAngle = currentStartAngle + M_PI / 2.0f * sweepDirection;
|
||||
} else {
|
||||
currentEndAngle = currentStartAngle + arcSweepLeft * sweepDirection;
|
||||
}
|
||||
|
||||
Point currentStartPoint(x + cos(currentStartAngle) * r,
|
||||
y + sin(currentStartAngle) * r);
|
||||
Point currentEndPoint(x + cos(currentEndAngle) * r,
|
||||
y + sin(currentEndAngle) * r);
|
||||
|
||||
// Calculate kappa constant for partial curve. The sign of angle in the
|
||||
// tangent will actually ensure this is negative for a counter clockwise
|
||||
// sweep, so changing signs later isn't needed.
|
||||
Float kappa = (4.0f / 3.0f) * tan((currentEndAngle - currentStartAngle) / 4.0f) * r;
|
||||
|
||||
Point tangentStart(-sin(currentStartAngle), cos(currentStartAngle));
|
||||
Point cp1 = currentStartPoint;
|
||||
cp1 += tangentStart * kappa;
|
||||
|
||||
Point revTangentEnd(sin(currentEndAngle), -cos(currentEndAngle));
|
||||
Point cp2 = currentEndPoint;
|
||||
cp2 += revTangentEnd * kappa;
|
||||
|
||||
if (mPathBuilder) {
|
||||
mPathBuilder->BezierTo(cp1, cp2, currentEndPoint);
|
||||
} else {
|
||||
mDSPathBuilder->BezierTo(mTarget->GetTransform() * cp1,
|
||||
mTarget->GetTransform() * cp2,
|
||||
mTarget->GetTransform() * currentEndPoint);
|
||||
}
|
||||
|
||||
arcSweepLeft -= M_PI / 2.0f;
|
||||
currentStartAngle = currentEndAngle;
|
||||
}
|
||||
|
||||
|
||||
ArcToBezier(this, Point(x, y), r, startAngle, endAngle, ccw);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
0
gfx/2d/Helpers.h
Normal file
0
gfx/2d/Helpers.h
Normal file
@ -56,6 +56,7 @@ EXPORTS_mozilla/gfx = \
|
||||
BaseMargin.h \
|
||||
BaseRect.h \
|
||||
BaseSize.h \
|
||||
PathHelpers.h \
|
||||
Point.h \
|
||||
Matrix.h \
|
||||
Rect.h \
|
||||
|
122
gfx/2d/PathHelpers.h
Normal file
122
gfx/2d/PathHelpers.h
Normal file
@ -0,0 +1,122 @@
|
||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Corporation code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Matt Woodrow <mwoodrow@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef MOZILLA_GFX_PATHHELPERS_H_
|
||||
#define MOZILLA_GFX_PATHHELPERS_H_
|
||||
|
||||
#include "2D.h"
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
template <typename T>
|
||||
void ArcToBezier(T* aSink, const Point &aOrigin, float aRadius, float aStartAngle,
|
||||
float aEndAngle, bool aAntiClockwise)
|
||||
{
|
||||
Point startPoint(aOrigin.x + cos(aStartAngle) * aRadius,
|
||||
aOrigin.y + sin(aStartAngle) * aRadius);
|
||||
|
||||
aSink->LineTo(startPoint);
|
||||
|
||||
// Clockwise we always sweep from the smaller to the larger angle, ccw
|
||||
// it's vice versa.
|
||||
if (!aAntiClockwise && (aEndAngle < aStartAngle)) {
|
||||
Float correction = ceil((aStartAngle - aEndAngle) / (2.0f * M_PI));
|
||||
aEndAngle += correction * 2.0f * M_PI;
|
||||
} else if (aAntiClockwise && (aStartAngle < aEndAngle)) {
|
||||
Float correction = ceil((aEndAngle - aStartAngle) / (2.0f * M_PI));
|
||||
aStartAngle += correction * 2.0f * M_PI;
|
||||
}
|
||||
|
||||
// Sweeping more than 2 * pi is a full circle.
|
||||
if (!aAntiClockwise && (aEndAngle - aStartAngle > 2 * M_PI)) {
|
||||
aEndAngle = aStartAngle + 2.0f * M_PI;
|
||||
} else if (aAntiClockwise && (aStartAngle - aEndAngle > 2.0f * M_PI)) {
|
||||
aEndAngle = aStartAngle - 2.0f * M_PI;
|
||||
}
|
||||
|
||||
// Calculate the total arc we're going to sweep.
|
||||
Float arcSweepLeft = fabs(aEndAngle - aStartAngle);
|
||||
|
||||
Float sweepDirection = aAntiClockwise ? -1.0f : 1.0f;
|
||||
|
||||
Float currentStartAngle = aStartAngle;
|
||||
|
||||
while (arcSweepLeft > 0) {
|
||||
// We guarantee here the current point is the start point of the next
|
||||
// curve segment.
|
||||
Float currentEndAngle;
|
||||
|
||||
if (arcSweepLeft > M_PI / 2.0f) {
|
||||
currentEndAngle = currentStartAngle + M_PI / 2.0f * sweepDirection;
|
||||
} else {
|
||||
currentEndAngle = currentStartAngle + arcSweepLeft * sweepDirection;
|
||||
}
|
||||
|
||||
Point currentStartPoint(aOrigin.x + cos(currentStartAngle) * aRadius,
|
||||
aOrigin.y + sin(currentStartAngle) * aRadius);
|
||||
Point currentEndPoint(aOrigin.x + cos(currentEndAngle) * aRadius,
|
||||
aOrigin.y + sin(currentEndAngle) * aRadius);
|
||||
|
||||
// Calculate kappa constant for partial curve. The sign of angle in the
|
||||
// tangent will actually ensure this is negative for a counter clockwise
|
||||
// sweep, so changing signs later isn't needed.
|
||||
Float kappa = (4.0f / 3.0f) * tan((currentEndAngle - currentStartAngle) / 4.0f) * aRadius;
|
||||
|
||||
Point tangentStart(-sin(currentStartAngle), cos(currentStartAngle));
|
||||
Point cp1 = currentStartPoint;
|
||||
cp1 += tangentStart * kappa;
|
||||
|
||||
Point revTangentEnd(sin(currentEndAngle), -cos(currentEndAngle));
|
||||
Point cp2 = currentEndPoint;
|
||||
cp2 += revTangentEnd * kappa;
|
||||
|
||||
aSink->BezierTo(cp1, cp2, currentEndPoint);
|
||||
|
||||
arcSweepLeft -= M_PI / 2.0f;
|
||||
currentStartAngle = currentEndAngle;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* MOZILLA_GFX_PATHHELPERS_H_ */
|
@ -40,6 +40,7 @@
|
||||
#include "DrawTargetSkia.h"
|
||||
#include "Logging.h"
|
||||
#include "HelpersSkia.h"
|
||||
#include "PathHelpers.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
@ -118,71 +119,8 @@ PathBuilderSkia::Close()
|
||||
void
|
||||
PathBuilderSkia::Arc(const Point &aOrigin, float aRadius, float aStartAngle,
|
||||
float aEndAngle, bool aAntiClockwise)
|
||||
{
|
||||
//TODO: Taken directly from azure canvas, we should share this somewhere
|
||||
Point startPoint(aOrigin.x + cos(aStartAngle) * aRadius,
|
||||
aOrigin.y + sin(aStartAngle) * aRadius);
|
||||
|
||||
LineTo(startPoint);
|
||||
|
||||
// Clockwise we always sweep from the smaller to the larger angle, ccw
|
||||
// it's vice versa.
|
||||
if (!aAntiClockwise && (aEndAngle < aStartAngle)) {
|
||||
Float correction = ceil((aStartAngle - aEndAngle) / (2.0f * M_PI));
|
||||
aEndAngle += correction * 2.0f * M_PI;
|
||||
} else if (aAntiClockwise && (aStartAngle < aEndAngle)) {
|
||||
Float correction = ceil((aEndAngle - aStartAngle) / (2.0f * M_PI));
|
||||
aStartAngle += correction * 2.0f * M_PI;
|
||||
}
|
||||
|
||||
// Sweeping more than 2 * pi is a full circle.
|
||||
if (!aAntiClockwise && (aEndAngle - aStartAngle > 2 * M_PI)) {
|
||||
aEndAngle = aStartAngle + 2.0f * M_PI;
|
||||
} else if (aAntiClockwise && (aStartAngle - aEndAngle > 2.0f * M_PI)) {
|
||||
aEndAngle = aStartAngle - 2.0f * M_PI;
|
||||
}
|
||||
|
||||
// Calculate the total arc we're going to sweep.
|
||||
Float arcSweepLeft = fabs(aEndAngle - aStartAngle);
|
||||
|
||||
Float sweepDirection = aAntiClockwise ? -1.0f : 1.0f;
|
||||
|
||||
Float currentStartAngle = aStartAngle;
|
||||
|
||||
while (arcSweepLeft > 0) {
|
||||
// We guarantee here the current point is the start point of the next
|
||||
// curve segment.
|
||||
Float currentEndAngle;
|
||||
|
||||
if (arcSweepLeft > M_PI / 2.0f) {
|
||||
currentEndAngle = currentStartAngle + M_PI / 2.0f * sweepDirection;
|
||||
} else {
|
||||
currentEndAngle = currentStartAngle + arcSweepLeft * sweepDirection;
|
||||
}
|
||||
|
||||
Point currentStartPoint(aOrigin.x + cos(currentStartAngle) * aRadius,
|
||||
aOrigin.y + sin(currentStartAngle) * aRadius);
|
||||
Point currentEndPoint(aOrigin.x + cos(currentEndAngle) * aRadius,
|
||||
aOrigin.y + sin(currentEndAngle) * aRadius);
|
||||
|
||||
// Calculate kappa constant for partial curve. The sign of angle in the
|
||||
// tangent will actually ensure this is negative for a counter clockwise
|
||||
// sweep, so changing signs later isn't needed.
|
||||
Float kappa = (4.0f / 3.0f) * tan((currentEndAngle - currentStartAngle) / 4.0f) * aRadius;
|
||||
|
||||
Point tangentStart(-sin(currentStartAngle), cos(currentStartAngle));
|
||||
Point cp1 = currentStartPoint;
|
||||
cp1 += tangentStart * kappa;
|
||||
|
||||
Point revTangentEnd(sin(currentEndAngle), -cos(currentEndAngle));
|
||||
Point cp2 = currentEndPoint;
|
||||
cp2 += revTangentEnd * kappa;
|
||||
|
||||
BezierTo(cp1, cp2, currentEndPoint);
|
||||
|
||||
arcSweepLeft -= M_PI / 2.0f;
|
||||
currentStartAngle = currentEndAngle;
|
||||
}
|
||||
{
|
||||
ArcToBezier(this, aOrigin, aRadius, aStartAngle, aEndAngle, aAntiClockwise);
|
||||
}
|
||||
|
||||
Point
|
||||
|
Loading…
x
Reference in New Issue
Block a user