diff options
Diffstat (limited to 'Source/WebCore/svg/SVGLengthContext.cpp')
-rw-r--r-- | Source/WebCore/svg/SVGLengthContext.cpp | 152 |
1 files changed, 78 insertions, 74 deletions
diff --git a/Source/WebCore/svg/SVGLengthContext.cpp b/Source/WebCore/svg/SVGLengthContext.cpp index 07b2045bf..fff1e879f 100644 --- a/Source/WebCore/svg/SVGLengthContext.cpp +++ b/Source/WebCore/svg/SVGLengthContext.cpp @@ -3,6 +3,7 @@ * Copyright (C) 2004, 2005, 2006, 2007 Rob Buis <buis@kde.org> * Copyright (C) 2007 Apple Inc. All rights reserved. * Copyright (C) Research In Motion Limited 2011. All rights reserved. + * Copyright (C) 2014 Adobe Systems Incorporated. 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 @@ -21,18 +22,16 @@ */ #include "config.h" - -#if ENABLE(SVG) #include "SVGLengthContext.h" #include "CSSHelper.h" #include "ExceptionCode.h" #include "FontMetrics.h" #include "Frame.h" +#include "LengthFunctions.h" #include "RenderSVGRoot.h" #include "RenderSVGViewportContainer.h" #include "RenderView.h" -#include "SVGNames.h" #include "SVGSVGElement.h" namespace WebCore { @@ -48,7 +47,7 @@ SVGLengthContext::SVGLengthContext(const SVGElement* context, const FloatRect& v { } -FloatRect SVGLengthContext::resolveRectangle(const SVGElement* context, SVGUnitTypes::SVGUnitType type, const FloatRect& viewport, const SVGLength& x, const SVGLength& y, const SVGLength& width, const SVGLength& height) +FloatRect SVGLengthContext::resolveRectangle(const SVGElement* context, SVGUnitTypes::SVGUnitType type, const FloatRect& viewport, const SVGLengthValue& x, const SVGLengthValue& y, const SVGLengthValue& width, const SVGLengthValue& height) { ASSERT(type != SVGUnitTypes::SVG_UNIT_TYPE_UNKNOWN); if (type == SVGUnitTypes::SVG_UNIT_TYPE_USERSPACEONUSE) { @@ -63,7 +62,7 @@ FloatRect SVGLengthContext::resolveRectangle(const SVGElement* context, SVGUnitT height.value(lengthContext)); } -FloatPoint SVGLengthContext::resolvePoint(const SVGElement* context, SVGUnitTypes::SVGUnitType type, const SVGLength& x, const SVGLength& y) +FloatPoint SVGLengthContext::resolvePoint(const SVGElement* context, SVGUnitTypes::SVGUnitType type, const SVGLengthValue& x, const SVGLengthValue& y) { ASSERT(type != SVGUnitTypes::SVG_UNIT_TYPE_UNKNOWN); if (type == SVGUnitTypes::SVG_UNIT_TYPE_USERSPACEONUSE) { @@ -75,7 +74,7 @@ FloatPoint SVGLengthContext::resolvePoint(const SVGElement* context, SVGUnitType return FloatPoint(x.valueAsPercentage(), y.valueAsPercentage()); } -float SVGLengthContext::resolveLength(const SVGElement* context, SVGUnitTypes::SVGUnitType type, const SVGLength& x) +float SVGLengthContext::resolveLength(const SVGElement* context, SVGUnitTypes::SVGUnitType type, const SVGLengthValue& x) { ASSERT(type != SVGUnitTypes::SVG_UNIT_TYPE_UNKNOWN); if (type == SVGUnitTypes::SVG_UNIT_TYPE_USERSPACEONUSE) { @@ -87,30 +86,54 @@ float SVGLengthContext::resolveLength(const SVGElement* context, SVGUnitTypes::S return x.valueAsPercentage(); } -float SVGLengthContext::convertValueToUserUnits(float value, SVGLengthMode mode, SVGLengthType fromUnit, ExceptionCode& ec) const +float SVGLengthContext::valueForLength(const Length& length, SVGLengthMode mode) +{ + if (length.isPercent()) { + auto result = convertValueFromPercentageToUserUnits(length.value() / 100, mode); + if (result.hasException()) + return 0; + return result.releaseReturnValue(); + } + if (length.isAuto() || !length.isSpecified()) + return 0; + + FloatSize viewportSize; + determineViewport(viewportSize); + + switch (mode) { + case LengthModeWidth: + return floatValueForLength(length, viewportSize.width()); + case LengthModeHeight: + return floatValueForLength(length, viewportSize.height()); + case LengthModeOther: + return floatValueForLength(length, std::sqrt(viewportSize.diagonalLengthSquared() / 2)); + }; + return 0; +} + +ExceptionOr<float> SVGLengthContext::convertValueToUserUnits(float value, SVGLengthMode mode, SVGLengthType fromUnit) const { // If the SVGLengthContext carries a custom viewport, force resolving against it. if (!m_overridenViewport.isEmpty()) { // 100% = 100.0 instead of 1.0 for historical reasons, this could eventually be changed if (fromUnit == LengthTypePercentage) value /= 100; - return convertValueFromPercentageToUserUnits(value, mode, ec); + return convertValueFromPercentageToUserUnits(value, mode); } switch (fromUnit) { case LengthTypeUnknown: - ec = NOT_SUPPORTED_ERR; - return 0; + return Exception { NOT_SUPPORTED_ERR }; case LengthTypeNumber: return value; case LengthTypePX: return value; case LengthTypePercentage: - return convertValueFromPercentageToUserUnits(value / 100, mode, ec); + return convertValueFromPercentageToUserUnits(value / 100, mode); case LengthTypeEMS: - return convertValueFromEMSToUserUnits(value, ec); + return convertValueFromEMSToUserUnits(value); case LengthTypeEXS: - return convertValueFromEXSToUserUnits(value, ec); + return convertValueFromEXSToUserUnits(value); case LengthTypeCM: return value * cssPixelsPerInch / 2.54f; case LengthTypeMM: @@ -127,20 +150,19 @@ float SVGLengthContext::convertValueToUserUnits(float value, SVGLengthMode mode, return 0; } -float SVGLengthContext::convertValueFromUserUnits(float value, SVGLengthMode mode, SVGLengthType toUnit, ExceptionCode& ec) const +ExceptionOr<float> SVGLengthContext::convertValueFromUserUnits(float value, SVGLengthMode mode, SVGLengthType toUnit) const { switch (toUnit) { case LengthTypeUnknown: - ec = NOT_SUPPORTED_ERR; - return 0; + return Exception { NOT_SUPPORTED_ERR }; case LengthTypeNumber: return value; case LengthTypePercentage: - return convertValueFromUserUnitsToPercentage(value * 100, mode, ec); + return convertValueFromUserUnitsToPercentage(value * 100, mode); case LengthTypeEMS: - return convertValueFromUserUnitsToEMS(value, ec); + return convertValueFromUserUnitsToEMS(value); case LengthTypeEXS: - return convertValueFromUserUnitsToEXS(value, ec); + return convertValueFromUserUnitsToEXS(value); case LengthTypePX: return value; case LengthTypeCM: @@ -159,13 +181,11 @@ float SVGLengthContext::convertValueFromUserUnits(float value, SVGLengthMode mod return 0; } -float SVGLengthContext::convertValueFromUserUnitsToPercentage(float value, SVGLengthMode mode, ExceptionCode& ec) const +ExceptionOr<float> SVGLengthContext::convertValueFromUserUnitsToPercentage(float value, SVGLengthMode mode) const { FloatSize viewportSize; - if (!determineViewport(viewportSize)) { - ec = NOT_SUPPORTED_ERR; - return 0; - } + if (!determineViewport(viewportSize)) + return Exception { NOT_SUPPORTED_ERR }; switch (mode) { case LengthModeWidth: @@ -173,20 +193,18 @@ float SVGLengthContext::convertValueFromUserUnitsToPercentage(float value, SVGLe case LengthModeHeight: return value / viewportSize.height() * 100; case LengthModeOther: - return value / (sqrtf(viewportSize.diagonalLengthSquared() / 2)) * 100; + return value / (std::sqrt(viewportSize.diagonalLengthSquared() / 2)) * 100; }; ASSERT_NOT_REACHED(); return 0; } -float SVGLengthContext::convertValueFromPercentageToUserUnits(float value, SVGLengthMode mode, ExceptionCode& ec) const +ExceptionOr<float> SVGLengthContext::convertValueFromPercentageToUserUnits(float value, SVGLengthMode mode) const { FloatSize viewportSize; - if (!determineViewport(viewportSize)) { - ec = NOT_SUPPORTED_ERR; - return 0; - } + if (!determineViewport(viewportSize)) + return Exception { NOT_SUPPORTED_ERR }; switch (mode) { case LengthModeWidth: @@ -194,14 +212,14 @@ float SVGLengthContext::convertValueFromPercentageToUserUnits(float value, SVGLe case LengthModeHeight: return value * viewportSize.height(); case LengthModeOther: - return value * sqrtf(viewportSize.diagonalLengthSquared() / 2); + return value * std::sqrt(viewportSize.diagonalLengthSquared() / 2); }; ASSERT_NOT_REACHED(); return 0; } -static inline RenderStyle* renderStyleForLengthResolving(const SVGElement* context) +static inline const RenderStyle* renderStyleForLengthResolving(const SVGElement* context) { if (!context) return nullptr; @@ -215,67 +233,55 @@ static inline RenderStyle* renderStyleForLengthResolving(const SVGElement* conte // There must be at least a RenderSVGRoot renderer, carrying a style. ASSERT_NOT_REACHED(); - return 0; + return nullptr; } -float SVGLengthContext::convertValueFromUserUnitsToEMS(float value, ExceptionCode& ec) const +ExceptionOr<float> SVGLengthContext::convertValueFromUserUnitsToEMS(float value) const { - RenderStyle* style = renderStyleForLengthResolving(m_context); - if (!style) { - ec = NOT_SUPPORTED_ERR; - return 0; - } + auto* style = renderStyleForLengthResolving(m_context); + if (!style) + return Exception { NOT_SUPPORTED_ERR }; float fontSize = style->fontSize(); - if (!fontSize) { - ec = NOT_SUPPORTED_ERR; - return 0; - } + if (!fontSize) + return Exception { NOT_SUPPORTED_ERR }; return value / fontSize; } -float SVGLengthContext::convertValueFromEMSToUserUnits(float value, ExceptionCode& ec) const +ExceptionOr<float> SVGLengthContext::convertValueFromEMSToUserUnits(float value) const { - RenderStyle* style = renderStyleForLengthResolving(m_context); - if (!style) { - ec = NOT_SUPPORTED_ERR; - return 0; - } + auto* style = renderStyleForLengthResolving(m_context); + if (!style) + return Exception { NOT_SUPPORTED_ERR }; return value * style->fontSize(); } -float SVGLengthContext::convertValueFromUserUnitsToEXS(float value, ExceptionCode& ec) const +ExceptionOr<float> SVGLengthContext::convertValueFromUserUnitsToEXS(float value) const { - RenderStyle* style = renderStyleForLengthResolving(m_context); - if (!style) { - ec = NOT_SUPPORTED_ERR; - return 0; - } + auto* style = renderStyleForLengthResolving(m_context); + if (!style) + return Exception { NOT_SUPPORTED_ERR }; // Use of ceil allows a pixel match to the W3Cs expected output of coords-units-03-b.svg // if this causes problems in real world cases maybe it would be best to remove this - float xHeight = ceilf(style->fontMetrics().xHeight()); - if (!xHeight) { - ec = NOT_SUPPORTED_ERR; - return 0; - } + float xHeight = std::ceil(style->fontMetrics().xHeight()); + if (!xHeight) + return Exception { NOT_SUPPORTED_ERR }; return value / xHeight; } -float SVGLengthContext::convertValueFromEXSToUserUnits(float value, ExceptionCode& ec) const +ExceptionOr<float> SVGLengthContext::convertValueFromEXSToUserUnits(float value) const { - RenderStyle* style = renderStyleForLengthResolving(m_context); - if (!style) { - ec = NOT_SUPPORTED_ERR; - return 0; - } + auto* style = renderStyleForLengthResolving(m_context); + if (!style) + return Exception { NOT_SUPPORTED_ERR }; // Use of ceil allows a pixel match to the W3Cs expected output of coords-units-03-b.svg // if this causes problems in real world cases maybe it would be best to remove this - return value * ceilf(style->fontMetrics().xHeight()); + return value * std::ceil(style->fontMetrics().xHeight()); } bool SVGLengthContext::determineViewport(FloatSize& viewportSize) const @@ -291,23 +297,21 @@ bool SVGLengthContext::determineViewport(FloatSize& viewportSize) const // Root <svg> element lengths are resolved against the top level viewport. if (m_context->isOutermostSVGSVGElement()) { - viewportSize = toSVGSVGElement(m_context)->currentViewportSize(); + viewportSize = downcast<SVGSVGElement>(*m_context).currentViewportSize(); return true; } // Take size from nearest viewport element. SVGElement* viewportElement = m_context->viewportElement(); - if (!viewportElement || !isSVGSVGElement(viewportElement)) + if (!is<SVGSVGElement>(viewportElement)) return false; - const SVGSVGElement* svg = toSVGSVGElement(viewportElement); - viewportSize = svg->currentViewBoxRect().size(); + const SVGSVGElement& svg = downcast<SVGSVGElement>(*viewportElement); + viewportSize = svg.currentViewBoxRect().size(); if (viewportSize.isEmpty()) - viewportSize = svg->currentViewportSize(); + viewportSize = svg.currentViewportSize(); return true; } } - -#endif |