diff options
Diffstat (limited to 'WebCore/svg/SVGPreserveAspectRatio.cpp')
-rw-r--r-- | WebCore/svg/SVGPreserveAspectRatio.cpp | 174 |
1 files changed, 96 insertions, 78 deletions
diff --git a/WebCore/svg/SVGPreserveAspectRatio.cpp b/WebCore/svg/SVGPreserveAspectRatio.cpp index a129fe6..c9c452e 100644 --- a/WebCore/svg/SVGPreserveAspectRatio.cpp +++ b/WebCore/svg/SVGPreserveAspectRatio.cpp @@ -25,8 +25,9 @@ #include "SVGPreserveAspectRatio.h" #include "AffineTransform.h" +#include "FloatRect.h" #include "SVGParserUtilities.h" -#include "SVGSVGElement.h" +#include <wtf/text/StringConcatenate.h> namespace WebCore { @@ -34,27 +35,26 @@ SVGPreserveAspectRatio::SVGPreserveAspectRatio() : m_align(SVG_PRESERVEASPECTRATIO_XMIDYMID) , m_meetOrSlice(SVG_MEETORSLICE_MEET) { - // FIXME: Should the two values default to UNKNOWN instead? } -void SVGPreserveAspectRatio::setAlign(unsigned short align) +void SVGPreserveAspectRatio::setAlign(unsigned short align, ExceptionCode& ec) { - m_align = align; -} + if (align == SVG_PRESERVEASPECTRATIO_UNKNOWN || align > SVG_PRESERVEASPECTRATIO_XMAXYMAX) { + ec = NOT_SUPPORTED_ERR; + return; + } -unsigned short SVGPreserveAspectRatio::align() const -{ - return m_align; + m_align = static_cast<SVGPreserveAspectRatioType>(align); } -void SVGPreserveAspectRatio::setMeetOrSlice(unsigned short meetOrSlice) +void SVGPreserveAspectRatio::setMeetOrSlice(unsigned short meetOrSlice, ExceptionCode& ec) { - m_meetOrSlice = meetOrSlice; -} + if (meetOrSlice == SVG_MEETORSLICE_UNKNOWN || meetOrSlice > SVG_MEETORSLICE_SLICE) { + ec = NOT_SUPPORTED_ERR; + return; + } -unsigned short SVGPreserveAspectRatio::meetOrSlice() const -{ - return m_meetOrSlice; + m_meetOrSlice = static_cast<SVGMeetOrSliceType>(meetOrSlice); } SVGPreserveAspectRatio SVGPreserveAspectRatio::parsePreserveAspectRatio(const UChar*& currParam, const UChar* end, bool validate, bool& result) @@ -64,6 +64,7 @@ SVGPreserveAspectRatio SVGPreserveAspectRatio::parsePreserveAspectRatio(const UC aspectRatio.m_meetOrSlice = SVG_MEETORSLICE_MEET; result = false; + // FIXME: Rewrite this parser, without gotos! if (!skipOptionalSpaces(currParam, end)) goto bail_out; @@ -160,167 +161,184 @@ void SVGPreserveAspectRatio::transformRect(FloatRect& destRect, FloatRect& srcRe FloatSize imageSize = srcRect.size(); float origDestWidth = destRect.width(); float origDestHeight = destRect.height(); - if (meetOrSlice() == SVGPreserveAspectRatio::SVG_MEETORSLICE_MEET) { + switch (m_meetOrSlice) { + case SVGPreserveAspectRatio::SVG_MEETORSLICE_UNKNOWN: + break; + case SVGPreserveAspectRatio::SVG_MEETORSLICE_MEET: + { float widthToHeightMultiplier = srcRect.height() / srcRect.width(); - if (origDestHeight > (origDestWidth * widthToHeightMultiplier)) { + if (origDestHeight > origDestWidth * widthToHeightMultiplier) { destRect.setHeight(origDestWidth * widthToHeightMultiplier); - switch (align()) { + switch (m_align) { case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMINYMID: case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMIDYMID: case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMAXYMID: - destRect.setY(destRect.y() + origDestHeight / 2.0f - destRect.height() / 2.0f); + destRect.setY(destRect.y() + origDestHeight / 2 - destRect.height() / 2); break; case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMINYMAX: case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMIDYMAX: case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMAXYMAX: destRect.setY(destRect.y() + origDestHeight - destRect.height()); break; + default: + break; } } - if (origDestWidth > (origDestHeight / widthToHeightMultiplier)) { + if (origDestWidth > origDestHeight / widthToHeightMultiplier) { destRect.setWidth(origDestHeight / widthToHeightMultiplier); - switch (align()) { + switch (m_align) { case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMIDYMIN: case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMIDYMID: case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMIDYMAX: - destRect.setX(destRect.x() + origDestWidth / 2.0f - destRect.width() / 2.0f); + destRect.setX(destRect.x() + origDestWidth / 2 - destRect.width() / 2); break; case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMAXYMIN: case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMAXYMID: case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMAXYMAX: destRect.setX(destRect.x() + origDestWidth - destRect.width()); break; + default: + break; } } - } else if (meetOrSlice() == SVGPreserveAspectRatio::SVG_MEETORSLICE_SLICE) { + break; + } + case SVGPreserveAspectRatio::SVG_MEETORSLICE_SLICE: + { float widthToHeightMultiplier = srcRect.height() / srcRect.width(); // if the destination height is less than the height of the image we'll be drawing - if (origDestHeight < (origDestWidth * widthToHeightMultiplier)) { + if (origDestHeight < origDestWidth * widthToHeightMultiplier) { float destToSrcMultiplier = srcRect.width() / destRect.width(); srcRect.setHeight(destRect.height() * destToSrcMultiplier); - switch (align()) { + switch (m_align) { case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMINYMID: case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMIDYMID: case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMAXYMID: - srcRect.setY(destRect.y() + imageSize.height() / 2.0f - srcRect.height() / 2.0f); + srcRect.setY(destRect.y() + imageSize.height() / 2 - srcRect.height() / 2); break; case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMINYMAX: case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMIDYMAX: case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMAXYMAX: srcRect.setY(destRect.y() + imageSize.height() - srcRect.height()); break; + default: + break; } } // if the destination width is less than the width of the image we'll be drawing - if (origDestWidth < (origDestHeight / widthToHeightMultiplier)) { + if (origDestWidth < origDestHeight / widthToHeightMultiplier) { float destToSrcMultiplier = srcRect.height() / destRect.height(); srcRect.setWidth(destRect.width() * destToSrcMultiplier); - switch (align()) { + switch (m_align) { case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMIDYMIN: case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMIDYMID: case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMIDYMAX: - srcRect.setX(destRect.x() + imageSize.width() / 2.0f - srcRect.width() / 2.0f); + srcRect.setX(destRect.x() + imageSize.width() / 2 - srcRect.width() / 2); break; case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMAXYMIN: case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMAXYMID: case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMAXYMAX: srcRect.setX(destRect.x() + imageSize.width() - srcRect.width()); break; + default: + break; } } + break; + } } } -AffineTransform SVGPreserveAspectRatio::getCTM(double logicX, double logicY, - double logicWidth, double logicHeight, - double /*physX*/, double /*physY*/, - double physWidth, double physHeight) const +// FIXME: We should use floats here, like everywhere else! +AffineTransform SVGPreserveAspectRatio::getCTM(double logicX, double logicY, double logicWidth, double logicHeight, double physWidth, double physHeight) const { - AffineTransform temp; + AffineTransform transform; + if (m_align == SVG_PRESERVEASPECTRATIO_UNKNOWN) + return transform; - if (align() == SVG_PRESERVEASPECTRATIO_UNKNOWN) - return temp; + double logicalRatio = logicWidth / logicHeight; + double physRatio = physWidth / physHeight; - double vpar = logicWidth / logicHeight; - double svgar = physWidth / physHeight; + if (m_align == SVG_PRESERVEASPECTRATIO_NONE) { + transform.scaleNonUniform(physWidth / logicWidth, physHeight / logicHeight); + transform.translate(-logicX, -logicY); + return transform; + } - if (align() == SVG_PRESERVEASPECTRATIO_NONE) { - temp.scaleNonUniform(physWidth / logicWidth, physHeight / logicHeight); - temp.translate(-logicX, -logicY); - } else if ((vpar < svgar && (meetOrSlice() == SVG_MEETORSLICE_MEET)) || (vpar >= svgar && (meetOrSlice() == SVG_MEETORSLICE_SLICE))) { - temp.scaleNonUniform(physHeight / logicHeight, physHeight / logicHeight); + if ((logicalRatio < physRatio && (m_meetOrSlice == SVG_MEETORSLICE_MEET)) || (logicalRatio >= physRatio && (m_meetOrSlice == SVG_MEETORSLICE_SLICE))) { + transform.scaleNonUniform(physHeight / logicHeight, physHeight / logicHeight); - if (align() == SVG_PRESERVEASPECTRATIO_XMINYMIN || align() == SVG_PRESERVEASPECTRATIO_XMINYMID || align() == SVG_PRESERVEASPECTRATIO_XMINYMAX) - temp.translate(-logicX, -logicY); - else if (align() == SVG_PRESERVEASPECTRATIO_XMIDYMIN || align() == SVG_PRESERVEASPECTRATIO_XMIDYMID || align() == SVG_PRESERVEASPECTRATIO_XMIDYMAX) - temp.translate(-logicX - (logicWidth - physWidth * logicHeight / physHeight) / 2, -logicY); + if (m_align == SVG_PRESERVEASPECTRATIO_XMINYMIN || m_align == SVG_PRESERVEASPECTRATIO_XMINYMID || m_align == SVG_PRESERVEASPECTRATIO_XMINYMAX) + transform.translate(-logicX, -logicY); + else if (m_align == SVG_PRESERVEASPECTRATIO_XMIDYMIN || m_align == SVG_PRESERVEASPECTRATIO_XMIDYMID || m_align == SVG_PRESERVEASPECTRATIO_XMIDYMAX) + transform.translate(-logicX - (logicWidth - physWidth * logicHeight / physHeight) / 2, -logicY); else - temp.translate(-logicX - (logicWidth - physWidth * logicHeight / physHeight), -logicY); - } else { - temp.scaleNonUniform(physWidth / logicWidth, physWidth / logicWidth); - - if (align() == SVG_PRESERVEASPECTRATIO_XMINYMIN || align() == SVG_PRESERVEASPECTRATIO_XMIDYMIN || align() == SVG_PRESERVEASPECTRATIO_XMAXYMIN) - temp.translate(-logicX, -logicY); - else if (align() == SVG_PRESERVEASPECTRATIO_XMINYMID || align() == SVG_PRESERVEASPECTRATIO_XMIDYMID || align() == SVG_PRESERVEASPECTRATIO_XMAXYMID) - temp.translate(-logicX, -logicY - (logicHeight - physHeight * logicWidth / physWidth) / 2); - else - temp.translate(-logicX, -logicY - (logicHeight - physHeight * logicWidth / physWidth)); + transform.translate(-logicX - (logicWidth - physWidth * logicHeight / physHeight), -logicY); + + return transform; } - return temp; + transform.scaleNonUniform(physWidth / logicWidth, physWidth / logicWidth); + + if (m_align == SVG_PRESERVEASPECTRATIO_XMINYMIN || m_align == SVG_PRESERVEASPECTRATIO_XMIDYMIN || m_align == SVG_PRESERVEASPECTRATIO_XMAXYMIN) + transform.translate(-logicX, -logicY); + else if (m_align == SVG_PRESERVEASPECTRATIO_XMINYMID || m_align == SVG_PRESERVEASPECTRATIO_XMIDYMID || m_align == SVG_PRESERVEASPECTRATIO_XMAXYMID) + transform.translate(-logicX, -logicY - (logicHeight - physHeight * logicWidth / physWidth) / 2); + else + transform.translate(-logicX, -logicY - (logicHeight - physHeight * logicWidth / physWidth)); + + return transform; } String SVGPreserveAspectRatio::valueAsString() const { - String result; + String alignType; - switch ((SVGPreserveAspectRatioType) align()) { - default: + switch (m_align) { case SVG_PRESERVEASPECTRATIO_NONE: - result = "none"; + alignType = "none"; break; case SVG_PRESERVEASPECTRATIO_XMINYMIN: - result = "xMinYMin"; + alignType = "xMinYMin"; break; case SVG_PRESERVEASPECTRATIO_XMIDYMIN: - result = "xMidYMin"; + alignType = "xMidYMin"; break; case SVG_PRESERVEASPECTRATIO_XMAXYMIN: - result = "xMaxYMin"; + alignType = "xMaxYMin"; break; case SVG_PRESERVEASPECTRATIO_XMINYMID: - result = "xMinYMid"; + alignType = "xMinYMid"; break; case SVG_PRESERVEASPECTRATIO_XMIDYMID: - result = "xMidYMid"; + alignType = "xMidYMid"; break; case SVG_PRESERVEASPECTRATIO_XMAXYMID: - result = "xMaxYMid"; + alignType = "xMaxYMid"; break; case SVG_PRESERVEASPECTRATIO_XMINYMAX: - result = "xMinYMax"; + alignType = "xMinYMax"; break; case SVG_PRESERVEASPECTRATIO_XMIDYMAX: - result = "xMidYMax"; + alignType = "xMidYMax"; break; case SVG_PRESERVEASPECTRATIO_XMAXYMAX: - result = "xMaxYMax"; + alignType = "xMaxYMax"; + break; + case SVG_PRESERVEASPECTRATIO_UNKNOWN: + alignType = "unknown"; break; }; - switch ((SVGMeetOrSliceType) meetOrSlice()) { + switch (m_meetOrSlice) { default: case SVG_MEETORSLICE_UNKNOWN: - break; + return alignType; case SVG_MEETORSLICE_MEET: - result += " meet"; - break; + return makeString(alignType, " meet"); case SVG_MEETORSLICE_SLICE: - result += " slice"; - break; + return makeString(alignType, " slice"); }; - - return result; } } |