diff options
author | Steve Block <steveblock@google.com> | 2011-05-06 11:45:16 +0100 |
---|---|---|
committer | Steve Block <steveblock@google.com> | 2011-05-12 13:44:10 +0100 |
commit | cad810f21b803229eb11403f9209855525a25d57 (patch) | |
tree | 29a6fd0279be608e0fe9ffe9841f722f0f4e4269 /WebCore/svg/SVGPathParser.cpp | |
parent | 121b0cf4517156d0ac5111caf9830c51b69bae8f (diff) | |
download | external_webkit-cad810f21b803229eb11403f9209855525a25d57.zip external_webkit-cad810f21b803229eb11403f9209855525a25d57.tar.gz external_webkit-cad810f21b803229eb11403f9209855525a25d57.tar.bz2 |
Merge WebKit at r75315: Initial merge by git.
Change-Id: I570314b346ce101c935ed22a626b48c2af266b84
Diffstat (limited to 'WebCore/svg/SVGPathParser.cpp')
-rw-r--r-- | WebCore/svg/SVGPathParser.cpp | 488 |
1 files changed, 0 insertions, 488 deletions
diff --git a/WebCore/svg/SVGPathParser.cpp b/WebCore/svg/SVGPathParser.cpp deleted file mode 100644 index a0d6847..0000000 --- a/WebCore/svg/SVGPathParser.cpp +++ /dev/null @@ -1,488 +0,0 @@ -/* - * Copyright (C) 2002, 2003 The Karbon Developers - * Copyright (C) 2006 Alexander Kellett <lypanov@kde.org> - * Copyright (C) 2006, 2007 Rob Buis <buis@kde.org> - * Copyright (C) 2007, 2009 Apple Inc. All rights reserved. - * Copyright (C) Research In Motion Limited 2010. All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" - -#if ENABLE(SVG) -#include "SVGPathParser.h" - -#include "AffineTransform.h" -#include <wtf/MathExtras.h> - -static const float gOneOverThree = 1 / 3.f; - -namespace WebCore { - -SVGPathParser::SVGPathParser() - : m_consumer(0) -{ -} - -void SVGPathParser::parseClosePathSegment() -{ - // Reset m_currentPoint for the next path. - if (m_pathParsingMode == NormalizedParsing) - m_currentPoint = m_subPathPoint; - m_closePath = true; - m_consumer->closePath(); -} - -bool SVGPathParser::parseMoveToSegment() -{ - FloatPoint targetPoint; - if (!m_source->parseMoveToSegment(targetPoint)) - return false; - - if (m_pathParsingMode == NormalizedParsing) { - if (m_mode == RelativeCoordinates) - m_currentPoint += targetPoint; - else - m_currentPoint = targetPoint; - m_subPathPoint = m_currentPoint; - m_consumer->moveTo(m_currentPoint, m_closePath, AbsoluteCoordinates); - } else - m_consumer->moveTo(targetPoint, m_closePath, m_mode); - m_closePath = false; - return true; -} - -bool SVGPathParser::parseLineToSegment() -{ - FloatPoint targetPoint; - if (!m_source->parseLineToSegment(targetPoint)) - return false; - - if (m_pathParsingMode == NormalizedParsing) { - if (m_mode == RelativeCoordinates) - m_currentPoint += targetPoint; - else - m_currentPoint = targetPoint; - m_consumer->lineTo(m_currentPoint, AbsoluteCoordinates); - } else - m_consumer->lineTo(targetPoint, m_mode); - return true; -} - -bool SVGPathParser::parseLineToHorizontalSegment() -{ - float toX; - if (!m_source->parseLineToHorizontalSegment(toX)) - return false; - - if (m_pathParsingMode == NormalizedParsing) { - if (m_mode == RelativeCoordinates) - m_currentPoint.move(toX, 0); - else - m_currentPoint.setX(toX); - m_consumer->lineTo(m_currentPoint, AbsoluteCoordinates); - } else - m_consumer->lineToHorizontal(toX, m_mode); - return true; -} - -bool SVGPathParser::parseLineToVerticalSegment() -{ - float toY; - if (!m_source->parseLineToVerticalSegment(toY)) - return false; - - if (m_pathParsingMode == NormalizedParsing) { - if (m_mode == RelativeCoordinates) - m_currentPoint.move(0, toY); - else - m_currentPoint.setY(toY); - m_consumer->lineTo(m_currentPoint, AbsoluteCoordinates); - } else - m_consumer->lineToVertical(toY, m_mode); - return true; -} - -bool SVGPathParser::parseCurveToCubicSegment() -{ - FloatPoint point1; - FloatPoint point2; - FloatPoint targetPoint; - if (!m_source->parseCurveToCubicSegment(point1, point2, targetPoint)) - return false; - - if (m_pathParsingMode == NormalizedParsing) { - if (m_mode == RelativeCoordinates) { - point1 += m_currentPoint; - point2 += m_currentPoint; - targetPoint += m_currentPoint; - } - m_consumer->curveToCubic(point1, point2, targetPoint, AbsoluteCoordinates); - - m_controlPoint = point2; - m_currentPoint = targetPoint; - } else - m_consumer->curveToCubic(point1, point2, targetPoint, m_mode); - return true; -} - -bool SVGPathParser::parseCurveToCubicSmoothSegment() -{ - FloatPoint point2; - FloatPoint targetPoint; - if (!m_source->parseCurveToCubicSmoothSegment(point2, targetPoint)) - return false; - - if (m_lastCommand != PathSegCurveToCubicAbs - && m_lastCommand != PathSegCurveToCubicRel - && m_lastCommand != PathSegCurveToCubicSmoothAbs - && m_lastCommand != PathSegCurveToCubicSmoothRel) - m_controlPoint = m_currentPoint; - - if (m_pathParsingMode == NormalizedParsing) { - FloatPoint point1 = m_currentPoint; - point1.scale(2, 2); - point1.move(-m_controlPoint.x(), -m_controlPoint.y()); - if (m_mode == RelativeCoordinates) { - point2 += m_currentPoint; - targetPoint += m_currentPoint; - } - - m_consumer->curveToCubic(point1, point2, targetPoint, AbsoluteCoordinates); - - m_controlPoint = point2; - m_currentPoint = targetPoint; - } else - m_consumer->curveToCubicSmooth(point2, targetPoint, m_mode); - return true; -} - -bool SVGPathParser::parseCurveToQuadraticSegment() -{ - FloatPoint point1; - FloatPoint targetPoint; - if (!m_source->parseCurveToQuadraticSegment(point1, targetPoint)) - return false; - - if (m_pathParsingMode == NormalizedParsing) { - m_controlPoint = point1; - FloatPoint point1 = m_currentPoint; - point1.move(2 * m_controlPoint.x(), 2 * m_controlPoint.y()); - FloatPoint point2(targetPoint.x() + 2 * m_controlPoint.x(), targetPoint.y() + 2 * m_controlPoint.y()); - if (m_mode == RelativeCoordinates) { - point1.move(2 * m_currentPoint.x(), 2 * m_currentPoint.y()); - point2.move(3 * m_currentPoint.x(), 3 * m_currentPoint.y()); - targetPoint += m_currentPoint; - } - point1.scale(gOneOverThree, gOneOverThree); - point2.scale(gOneOverThree, gOneOverThree); - - m_consumer->curveToCubic(point1, point2, targetPoint, AbsoluteCoordinates); - - if (m_mode == RelativeCoordinates) - m_controlPoint += m_currentPoint; - m_currentPoint = targetPoint; - } else - m_consumer->curveToQuadratic(point1, targetPoint, m_mode); - return true; -} - -bool SVGPathParser::parseCurveToQuadraticSmoothSegment() -{ - FloatPoint targetPoint; - if (!m_source->parseCurveToQuadraticSmoothSegment(targetPoint)) - return false; - - if (m_lastCommand != PathSegCurveToQuadraticAbs - && m_lastCommand != PathSegCurveToQuadraticRel - && m_lastCommand != PathSegCurveToQuadraticSmoothAbs - && m_lastCommand != PathSegCurveToQuadraticSmoothRel) - m_controlPoint = m_currentPoint; - - if (m_pathParsingMode == NormalizedParsing) { - FloatPoint cubicPoint = m_currentPoint; - cubicPoint.scale(2, 2); - cubicPoint.move(-m_controlPoint.x(), -m_controlPoint.y()); - FloatPoint point1(m_currentPoint.x() + 2 * cubicPoint.x(), m_currentPoint.y() + 2 * cubicPoint.y()); - FloatPoint point2(targetPoint.x() + 2 * cubicPoint.x(), targetPoint.y() + 2 * cubicPoint.y()); - if (m_mode == RelativeCoordinates) { - point2 += m_currentPoint; - targetPoint += m_currentPoint; - } - point1.scale(gOneOverThree, gOneOverThree); - point2.scale(gOneOverThree, gOneOverThree); - - m_consumer->curveToCubic(point1, point2, targetPoint, AbsoluteCoordinates); - - m_controlPoint = cubicPoint; - m_currentPoint = targetPoint; - } else - m_consumer->curveToQuadraticSmooth(targetPoint, m_mode); - return true; -} - -bool SVGPathParser::parseArcToSegment() -{ - float rx; - float ry; - float angle; - bool largeArc; - bool sweep; - FloatPoint targetPoint; - if (!m_source->parseArcToSegment(rx, ry, angle, largeArc, sweep, targetPoint)) - return false; - - // If rx = 0 or ry = 0 then this arc is treated as a straight line segment (a "lineto") joining the endpoints. - // http://www.w3.org/TR/SVG/implnote.html#ArcOutOfRangeParameters - rx = fabsf(rx); - ry = fabsf(ry); - if (!rx || !ry) { - if (m_pathParsingMode == NormalizedParsing) { - if (m_mode == RelativeCoordinates) - m_currentPoint += targetPoint; - else - m_currentPoint = targetPoint; - m_consumer->lineTo(m_currentPoint, AbsoluteCoordinates); - } else - m_consumer->lineTo(targetPoint, m_mode); - return true; - } - - if (m_pathParsingMode == NormalizedParsing) { - FloatPoint point1 = m_currentPoint; - if (m_mode == RelativeCoordinates) - targetPoint += m_currentPoint; - m_currentPoint = targetPoint; - return decomposeArcToCubic(angle, rx, ry, point1, targetPoint, largeArc, sweep); - } - m_consumer->arcTo(rx, ry, angle, largeArc, sweep, targetPoint, m_mode); - return true; -} - -bool SVGPathParser::parsePathDataFromSource(PathParsingMode pathParsingMode) -{ - ASSERT(m_source); - ASSERT(m_consumer); - - m_pathParsingMode = pathParsingMode; - - m_controlPoint = FloatPoint(); - m_currentPoint = FloatPoint(); - m_subPathPoint = FloatPoint(); - m_closePath = true; - - // Skip any leading spaces. - if (!m_source->moveToNextToken()) - return false; - - SVGPathSegType command; - m_source->parseSVGSegmentType(command); - m_lastCommand = PathSegUnknown; - - // Path must start with moveto. - if (command != PathSegMoveToAbs && command != PathSegMoveToRel) - return false; - - while (true) { - // Skip spaces between command and first coordinate. - m_source->moveToNextToken(); - m_mode = AbsoluteCoordinates; - switch (command) { - case PathSegMoveToRel: - m_mode = RelativeCoordinates; - case PathSegMoveToAbs: - if (!parseMoveToSegment()) - return false; - break; - case PathSegLineToRel: - m_mode = RelativeCoordinates; - case PathSegLineToAbs: - if (!parseLineToSegment()) - return false; - break; - case PathSegLineToHorizontalRel: - m_mode = RelativeCoordinates; - case PathSegLineToHorizontalAbs: - if (!parseLineToHorizontalSegment()) - return false; - break; - case PathSegLineToVerticalRel: - m_mode = RelativeCoordinates; - case PathSegLineToVerticalAbs: - if (!parseLineToVerticalSegment()) - return false; - break; - case PathSegClosePath: - parseClosePathSegment(); - break; - case PathSegCurveToCubicRel: - m_mode = RelativeCoordinates; - case PathSegCurveToCubicAbs: - if (!parseCurveToCubicSegment()) - return false; - break; - case PathSegCurveToCubicSmoothRel: - m_mode = RelativeCoordinates; - case PathSegCurveToCubicSmoothAbs: - if (!parseCurveToCubicSmoothSegment()) - return false; - break; - case PathSegCurveToQuadraticRel: - m_mode = RelativeCoordinates; - case PathSegCurveToQuadraticAbs: - if (!parseCurveToQuadraticSegment()) - return false; - break; - case PathSegCurveToQuadraticSmoothRel: - m_mode = RelativeCoordinates; - case PathSegCurveToQuadraticSmoothAbs: - if (!parseCurveToQuadraticSmoothSegment()) - return false; - break; - case PathSegArcRel: - m_mode = RelativeCoordinates; - case PathSegArcAbs: - if (!parseArcToSegment()) - return false; - break; - default: - return false; - } - if (!m_consumer->continueConsuming()) - return true; - - m_lastCommand = command; - - if (!m_source->hasMoreData()) - return true; - - command = m_source->nextCommand(command); - - if (m_lastCommand != PathSegCurveToCubicAbs - && m_lastCommand != PathSegCurveToCubicRel - && m_lastCommand != PathSegCurveToCubicSmoothAbs - && m_lastCommand != PathSegCurveToCubicSmoothRel - && m_lastCommand != PathSegCurveToQuadraticAbs - && m_lastCommand != PathSegCurveToQuadraticRel - && m_lastCommand != PathSegCurveToQuadraticSmoothAbs - && m_lastCommand != PathSegCurveToQuadraticSmoothRel) - m_controlPoint = m_currentPoint; - - m_consumer->incrementPathSegmentCount(); - } - - return false; -} - -void SVGPathParser::cleanup() -{ - ASSERT(m_source); - ASSERT(m_consumer); - - m_consumer->cleanup(); - m_source = 0; - m_consumer = 0; -} - -// This works by converting the SVG arc to "simple" beziers. -// Partly adapted from Niko's code in kdelibs/kdecore/svgicons. -// See also SVG implementation notes: http://www.w3.org/TR/SVG/implnote.html#ArcConversionEndpointToCenter -bool SVGPathParser::decomposeArcToCubic(float angle, float rx, float ry, FloatPoint& point1, FloatPoint& point2, bool largeArcFlag, bool sweepFlag) -{ - FloatSize midPointDistance = point1 - point2; - midPointDistance.scale(0.5f); - - AffineTransform pointTransform; - pointTransform.rotate(-angle); - - FloatPoint transformedMidPoint = pointTransform.mapPoint(FloatPoint(midPointDistance.width(), midPointDistance.height())); - float squareRx = rx * rx; - float squareRy = ry * ry; - float squareX = transformedMidPoint.x() * transformedMidPoint.x(); - float squareY = transformedMidPoint.y() * transformedMidPoint.y(); - - // Check if the radii are big enough to draw the arc, scale radii if not. - // http://www.w3.org/TR/SVG/implnote.html#ArcCorrectionOutOfRangeRadii - float radiiScale = squareX / squareRx + squareY / squareRy; - if (radiiScale > 1) { - rx *= sqrtf(radiiScale); - ry *= sqrtf(radiiScale); - } - - pointTransform.makeIdentity(); - pointTransform.scale(1 / rx, 1 / ry); - pointTransform.rotate(-angle); - - point1 = pointTransform.mapPoint(point1); - point2 = pointTransform.mapPoint(point2); - FloatSize delta = point2 - point1; - - float d = delta.width() * delta.width() + delta.height() * delta.height(); - float scaleFactorSquared = std::max(1 / d - 0.25f, 0.f); - - float scaleFactor = sqrtf(scaleFactorSquared); - if (sweepFlag == largeArcFlag) - scaleFactor = -scaleFactor; - - delta.scale(scaleFactor); - FloatPoint centerPoint = FloatPoint(0.5f * (point1.x() + point2.x()) - delta.height(), - 0.5f * (point1.y() + point2.y()) + delta.width()); - - float theta1 = atan2f(point1.y() - centerPoint.y(), point1.x() - centerPoint.x()); - float theta2 = atan2f(point2.y() - centerPoint.y(), point2.x() - centerPoint.x()); - - float thetaArc = theta2 - theta1; - if (thetaArc < 0 && sweepFlag) - thetaArc += 2 * piFloat; - else if (thetaArc > 0 && !sweepFlag) - thetaArc -= 2 * piFloat; - - pointTransform.makeIdentity(); - pointTransform.rotate(angle); - pointTransform.scale(rx, ry); - - // Some results of atan2 on some platform implementations are not exact enough. So that we get more - // cubic curves than expected here. Adding 0.001f reduces the count of sgements to the correct count. - int segments = ceilf(fabsf(thetaArc / (piOverTwoFloat + 0.001f))); - for (int i = 0; i < segments; ++i) { - float startTheta = theta1 + i * thetaArc / segments; - float endTheta = theta1 + (i + 1) * thetaArc / segments; - - float t = (8 / 6.f) * tanf(0.25f * (endTheta - startTheta)); - if (!isfinite(t)) - return false; - float sinStartTheta = sinf(startTheta); - float cosStartTheta = cosf(startTheta); - float sinEndTheta = sinf(endTheta); - float cosEndTheta = cosf(endTheta); - - point1 = FloatPoint(cosStartTheta - t * sinStartTheta, sinStartTheta + t * cosStartTheta); - point1.move(centerPoint.x(), centerPoint.y()); - FloatPoint targetPoint = FloatPoint(cosEndTheta, sinEndTheta); - targetPoint.move(centerPoint.x(), centerPoint.y()); - point2 = targetPoint; - point2.move(t * sinEndTheta, -t * cosEndTheta); - - m_consumer->curveToCubic(pointTransform.mapPoint(point1), pointTransform.mapPoint(point2), - pointTransform.mapPoint(targetPoint), AbsoluteCoordinates); - } - return true; -} - -} - -#endif // ENABLE(SVG) |