File indexing completed on 2024-04-28 15:24:40
0001 /* 0002 Copyright (C) 2004, 2005, 2008 Nikolas Zimmermann <zimmermann@kde.org> 0003 2004, 2005, 2006, 2007 Rob Buis <buis@kde.org> 0004 0005 This file is part of the KDE project 0006 0007 This library is free software; you can redistribute it and/or 0008 modify it under the terms of the GNU Library General Public 0009 License as published by the Free Software Foundation; either 0010 version 2 of the License, or (at your option) any later version. 0011 0012 This library is distributed in the hope that it will be useful, 0013 but WITHOUT ANY WARRANTY; without even the implied warranty of 0014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0015 Library General Public License for more details. 0016 0017 You should have received a copy of the GNU Library General Public License 0018 along with this library; see the file COPYING.LIB. If not, write to 0019 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0020 Boston, MA 02110-1301, USA. 0021 */ 0022 0023 #include "wtf/Platform.h" 0024 0025 #if ENABLE(SVG) 0026 #include "SVGPreserveAspectRatio.h" 0027 0028 #include "SVGParserUtilities.h" 0029 #include "SVGSVGElement.h" 0030 0031 namespace WebCore 0032 { 0033 0034 SVGPreserveAspectRatio::SVGPreserveAspectRatio() 0035 : m_align(SVG_PRESERVEASPECTRATIO_XMIDYMID) 0036 , m_meetOrSlice(SVG_MEETORSLICE_MEET) 0037 { 0038 // FIXME: Should the two values default to UNKNOWN instead? 0039 } 0040 0041 SVGPreserveAspectRatio::~SVGPreserveAspectRatio() 0042 { 0043 } 0044 0045 void SVGPreserveAspectRatio::setAlign(unsigned short align) 0046 { 0047 m_align = align; 0048 } 0049 0050 unsigned short SVGPreserveAspectRatio::align() const 0051 { 0052 return m_align; 0053 } 0054 0055 void SVGPreserveAspectRatio::setMeetOrSlice(unsigned short meetOrSlice) 0056 { 0057 m_meetOrSlice = meetOrSlice; 0058 } 0059 0060 unsigned short SVGPreserveAspectRatio::meetOrSlice() const 0061 { 0062 return m_meetOrSlice; 0063 } 0064 0065 bool SVGPreserveAspectRatio::parsePreserveAspectRatio(const UChar *&currParam, const UChar *end, bool validate) 0066 { 0067 SVGPreserveAspectRatioType align = SVG_PRESERVEASPECTRATIO_NONE; 0068 SVGMeetOrSliceType meetOrSlice = SVG_MEETORSLICE_MEET; 0069 bool ret = false; 0070 0071 if (!skipOptionalSpaces(currParam, end)) { 0072 goto bail_out; 0073 } 0074 0075 if (*currParam == 'd') { 0076 /*if (!skipString(currParam, end, "defer")) 0077 goto bail_out; 0078 // FIXME: We just ignore the "defer" here. 0079 if (!skipOptionalSpaces(currParam, end)) 0080 goto bail_out;*/ 0081 } 0082 0083 if (*currParam == 'n') { 0084 /*if (!skipString(currParam, end, "none")) 0085 goto bail_out;*/ 0086 skipOptionalSpaces(currParam, end); 0087 } else if (*currParam == 'x') { 0088 if ((end - currParam) < 8) { 0089 goto bail_out; 0090 } 0091 if (currParam[1] != 'M' || currParam[4] != 'Y' || currParam[5] != 'M') { 0092 goto bail_out; 0093 } 0094 if (currParam[2] == 'i') { 0095 if (currParam[3] == 'n') { 0096 if (currParam[6] == 'i') { 0097 if (currParam[7] == 'n') { 0098 align = SVG_PRESERVEASPECTRATIO_XMINYMIN; 0099 } else if (currParam[7] == 'd') { 0100 align = SVG_PRESERVEASPECTRATIO_XMINYMID; 0101 } else { 0102 goto bail_out; 0103 } 0104 } else if (currParam[6] == 'a' && currParam[7] == 'x') { 0105 align = SVG_PRESERVEASPECTRATIO_XMINYMAX; 0106 } else { 0107 goto bail_out; 0108 } 0109 } else if (currParam[3] == 'd') { 0110 if (currParam[6] == 'i') { 0111 if (currParam[7] == 'n') { 0112 align = SVG_PRESERVEASPECTRATIO_XMIDYMIN; 0113 } else if (currParam[7] == 'd') { 0114 align = SVG_PRESERVEASPECTRATIO_XMIDYMID; 0115 } else { 0116 goto bail_out; 0117 } 0118 } else if (currParam[6] == 'a' && currParam[7] == 'x') { 0119 align = SVG_PRESERVEASPECTRATIO_XMIDYMAX; 0120 } else { 0121 goto bail_out; 0122 } 0123 } else { 0124 goto bail_out; 0125 } 0126 } else if (currParam[2] == 'a' && currParam[3] == 'x') { 0127 if (currParam[6] == 'i') { 0128 if (currParam[7] == 'n') { 0129 align = SVG_PRESERVEASPECTRATIO_XMAXYMIN; 0130 } else if (currParam[7] == 'd') { 0131 align = SVG_PRESERVEASPECTRATIO_XMAXYMID; 0132 } else { 0133 goto bail_out; 0134 } 0135 } else if (currParam[6] == 'a' && currParam[7] == 'x') { 0136 align = SVG_PRESERVEASPECTRATIO_XMAXYMAX; 0137 } else { 0138 goto bail_out; 0139 } 0140 } else { 0141 goto bail_out; 0142 } 0143 currParam += 8; 0144 skipOptionalSpaces(currParam, end); 0145 } else { 0146 goto bail_out; 0147 } 0148 0149 if (currParam < end) { 0150 if (*currParam == 'm') { 0151 /*if (!skipString(currParam, end, "meet")) 0152 goto bail_out; 0153 skipOptionalSpaces(currParam, end);*/ 0154 } else if (*currParam == 's') { 0155 /*if (!skipString(currParam, end, "slice")) 0156 goto bail_out; 0157 skipOptionalSpaces(currParam, end); 0158 if (align != SVG_PRESERVEASPECTRATIO_NONE) 0159 meetOrSlice = SVG_MEETORSLICE_SLICE;*/ 0160 } 0161 } 0162 0163 if (end != currParam && validate) { 0164 bail_out: 0165 // FIXME: Should the two values be set to UNKNOWN instead? 0166 align = SVG_PRESERVEASPECTRATIO_NONE; 0167 meetOrSlice = SVG_MEETORSLICE_MEET; 0168 } else { 0169 ret = true; 0170 } 0171 0172 if (m_align == align && m_meetOrSlice == meetOrSlice) { 0173 return ret; 0174 } 0175 0176 m_align = align; 0177 m_meetOrSlice = meetOrSlice; 0178 return ret; 0179 } 0180 0181 AffineTransform SVGPreserveAspectRatio::getCTM(double logicX, double logicY, 0182 double logicWidth, double logicHeight, 0183 double /*physX*/, double /*physY*/, 0184 double physWidth, double physHeight) 0185 { 0186 AffineTransform temp; 0187 0188 if (align() == SVG_PRESERVEASPECTRATIO_UNKNOWN) { 0189 return temp; 0190 } 0191 0192 double vpar = logicWidth / logicHeight; 0193 double svgar = physWidth / physHeight; 0194 0195 if (align() == SVG_PRESERVEASPECTRATIO_NONE) { 0196 temp.scale(physWidth / logicWidth, physHeight / logicHeight); 0197 temp.translate(-logicX, -logicY); 0198 } else if ((vpar < svgar && meetOrSlice() == SVG_MEETORSLICE_MEET) || (vpar >= svgar && meetOrSlice() == SVG_MEETORSLICE_SLICE)) { 0199 temp.scale(physHeight / logicHeight, physHeight / logicHeight); 0200 0201 if (align() == SVG_PRESERVEASPECTRATIO_XMINYMIN || align() == SVG_PRESERVEASPECTRATIO_XMINYMID || align() == SVG_PRESERVEASPECTRATIO_XMINYMAX) { 0202 temp.translate(-logicX, -logicY); 0203 } else if (align() == SVG_PRESERVEASPECTRATIO_XMIDYMIN || align() == SVG_PRESERVEASPECTRATIO_XMIDYMID || align() == SVG_PRESERVEASPECTRATIO_XMIDYMAX) { 0204 temp.translate(-logicX - (logicWidth - physWidth * logicHeight / physHeight) / 2, -logicY); 0205 } else { 0206 temp.translate(-logicX - (logicWidth - physWidth * logicHeight / physHeight), -logicY); 0207 } 0208 } else { 0209 temp.scale(physWidth / logicWidth, physWidth / logicWidth); 0210 0211 if (align() == SVG_PRESERVEASPECTRATIO_XMINYMIN || align() == SVG_PRESERVEASPECTRATIO_XMIDYMIN || align() == SVG_PRESERVEASPECTRATIO_XMAXYMIN) { 0212 temp.translate(-logicX, -logicY); 0213 } else if (align() == SVG_PRESERVEASPECTRATIO_XMINYMID || align() == SVG_PRESERVEASPECTRATIO_XMIDYMID || align() == SVG_PRESERVEASPECTRATIO_XMAXYMID) { 0214 temp.translate(-logicX, -logicY - (logicHeight - physHeight * logicWidth / physWidth) / 2); 0215 } else { 0216 temp.translate(-logicX, -logicY - (logicHeight - physHeight * logicWidth / physWidth)); 0217 } 0218 } 0219 0220 return temp; 0221 } 0222 0223 } 0224 0225 #endif // ENABLE(SVG)