#include "SVGPreserveAspectRatio.h"
#include "AffineTransform.h"
+#include "FloatRect.h"
#include "SVGParserUtilities.h"
-#include "SVGSVGElement.h"
+#include <wtf/text/StringConcatenate.h>
namespace WebCore {
: 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)
aspectRatio.m_meetOrSlice = SVG_MEETORSLICE_MEET;
result = false;
+ // FIXME: Rewrite this parser, without gotos!
if (!skipOptionalSpaces(currParam, end))
goto bail_out;
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;
}
}