зеркало из https://github.com/mozilla/gecko-dev.git
Bug 910138 - clean-up of arc math. r=me
This commit is contained in:
Родитель
ae58ec8c78
Коммит
d4eec00ff3
|
@ -31,22 +31,17 @@ inline Float ComputeKappaFactor(Float aAngle)
|
|||
*/
|
||||
template <typename T>
|
||||
inline void PartialArcToBezier(T* aSink,
|
||||
const Size& aRadius,
|
||||
const Point& aStartPoint, const Point& aEndPoint,
|
||||
const Point& aStartOffset, const Point& aEndOffset,
|
||||
Float aKappaFactor = kKappaFactor,
|
||||
const Matrix& aTransform = Matrix())
|
||||
const Matrix& aTransform,
|
||||
Float aKappaFactor = kKappaFactor)
|
||||
{
|
||||
Float kappaX = aKappaFactor * aRadius.width;
|
||||
Float kappaY = aKappaFactor * aRadius.height;
|
||||
|
||||
Point cp1 =
|
||||
aStartPoint + Point(-aStartOffset.y * kappaX, aStartOffset.x * kappaY);
|
||||
aStartOffset + Point(-aStartOffset.y, aStartOffset.x) * aKappaFactor;
|
||||
|
||||
Point cp2 =
|
||||
aEndPoint + Point(aEndOffset.y * kappaX, -aEndOffset.x * kappaY);
|
||||
aEndOffset + Point(aEndOffset.y, -aEndOffset.x) * aKappaFactor;
|
||||
|
||||
aSink->BezierTo(aTransform * cp1, aTransform * cp2, aTransform * aEndPoint);
|
||||
aSink->BezierTo(aTransform * cp1, aTransform * cp2, aTransform * aEndOffset);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -61,16 +56,13 @@ inline void AcuteArcToBezier(T* aSink,
|
|||
{
|
||||
aSink->LineTo(aStartPoint);
|
||||
if (!aRadius.IsEmpty()) {
|
||||
Float kappaX = aKappaFactor * aRadius.width / aRadius.height;
|
||||
Float kappaY = aKappaFactor * aRadius.height / aRadius.width;
|
||||
Point startOffset = aStartPoint - aOrigin;
|
||||
startOffset.x /= aRadius.width;
|
||||
startOffset.y /= aRadius.height;
|
||||
Point endOffset = aEndPoint - aOrigin;
|
||||
endOffset.x /= aRadius.width;
|
||||
endOffset.y /= aRadius.height;
|
||||
PartialArcToBezier(aSink, aRadius,
|
||||
aStartPoint, aEndPoint,
|
||||
startOffset, endOffset,
|
||||
aKappaFactor);
|
||||
aSink->BezierTo(aStartPoint + Point(-startOffset.y * kappaX, startOffset.x * kappaY),
|
||||
aEndPoint + Point(endOffset.y * kappaX, -endOffset.x * kappaY),
|
||||
aEndPoint);
|
||||
} else if (aEndPoint != aStartPoint) {
|
||||
aSink->LineTo(aEndPoint);
|
||||
}
|
||||
|
@ -113,31 +105,26 @@ void ArcToBezier(T* aSink, const Point &aOrigin, const Size &aRadius,
|
|||
|
||||
Float currentStartAngle = aStartAngle;
|
||||
Point currentStartOffset(cosf(aStartAngle), sinf(aStartAngle));
|
||||
Point currentStartPoint(currentStartOffset.x * aRadius.width,
|
||||
currentStartOffset.y * aRadius.height);
|
||||
Matrix transform(cosf(aRotation), sinf(aRotation), -sinf(aRotation), cosf(aRotation), aOrigin.x, aOrigin.y);
|
||||
aSink->LineTo(transform * currentStartPoint);
|
||||
Matrix transform = Matrix::Scaling(aRadius.width, aRadius.height);
|
||||
if (aRotation != 0.0f) {
|
||||
transform *= Matrix::Rotation(aRotation);
|
||||
}
|
||||
transform.PostTranslate(aOrigin);
|
||||
aSink->LineTo(transform * currentStartOffset);
|
||||
|
||||
while (arcSweepLeft > 0) {
|
||||
Float currentEndAngle =
|
||||
currentStartAngle + std::min(arcSweepLeft, Float(M_PI / 2.0f)) * sweepDirection;
|
||||
|
||||
Point currentEndOffset(cosf(currentEndAngle), sinf(currentEndAngle));
|
||||
Point currentEndPoint(currentEndOffset.x * aRadius.width,
|
||||
currentEndOffset.y * aRadius.height);
|
||||
|
||||
PartialArcToBezier(aSink, aRadius,
|
||||
currentStartPoint, currentEndPoint,
|
||||
currentStartOffset, currentEndOffset,
|
||||
ComputeKappaFactor(currentEndAngle - currentStartAngle),
|
||||
transform);
|
||||
PartialArcToBezier(aSink, currentStartOffset, currentEndOffset, transform,
|
||||
ComputeKappaFactor(currentEndAngle - currentStartAngle));
|
||||
|
||||
// We guarantee here the current point is the start point of the next
|
||||
// curve segment.
|
||||
arcSweepLeft -= Float(M_PI / 2.0f);
|
||||
currentStartAngle = currentEndAngle;
|
||||
currentStartOffset = currentEndOffset;
|
||||
currentStartPoint = currentEndPoint;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -147,26 +134,21 @@ void ArcToBezier(T* aSink, const Point &aOrigin, const Size &aRadius,
|
|||
template <typename T>
|
||||
void EllipseToBezier(T* aSink, const Point &aOrigin, const Size &aRadius)
|
||||
{
|
||||
Matrix transform(aRadius.width, 0, 0, aRadius.height, aOrigin.x, aOrigin.y);
|
||||
Point currentStartOffset(1, 0);
|
||||
Point currentStartPoint(aOrigin.x + aRadius.width, aOrigin.y);
|
||||
|
||||
aSink->LineTo(currentStartPoint);
|
||||
aSink->LineTo(transform * currentStartOffset);
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
// cos(x+pi/2) == -sin(x)
|
||||
// sin(x+pi/2) == cos(x)
|
||||
Point currentEndOffset(-currentStartOffset.y, currentStartOffset.x);
|
||||
Point currentEndPoint(aOrigin.x + currentEndOffset.x * aRadius.width,
|
||||
aOrigin.y + currentEndOffset.y * aRadius.height);
|
||||
|
||||
PartialArcToBezier(aSink, aRadius,
|
||||
currentStartPoint, currentEndPoint,
|
||||
currentStartOffset, currentEndOffset);
|
||||
PartialArcToBezier(aSink, currentStartOffset, currentEndOffset, transform);
|
||||
|
||||
// We guarantee here the current point is the start point of the next
|
||||
// curve segment.
|
||||
currentStartOffset = currentEndOffset;
|
||||
currentStartPoint = currentEndPoint;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче