* ksvg2/svg/SVGPreserveAspectRatio.cpp: Add a couple of comments.
[WebKit-https.git] / WebCore / ksvg2 / svg / SVGPreserveAspectRatio.cpp
1 /*
2     Copyright (C) 2004, 2005 Nikolas Zimmermann <wildfox@kde.org>
3                   2004, 2005, 2006 Rob Buis <buis@kde.org>
4
5     This file is part of the KDE project
6
7     This library is free software; you can redistribute it and/or
8     modify it under the terms of the GNU Library General Public
9     License as published by the Free Software Foundation; either
10     version 2 of the License, or (at your option) any later version.
11
12     This library is distributed in the hope that it will be useful,
13     but WITHOUT ANY WARRANTY; without even the implied warranty of
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15     Library General Public License for more details.
16
17     You should have received a copy of the GNU Library General Public License
18     along with this library; see the file COPYING.LIB.  If not, write to
19     the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20     Boston, MA 02111-1307, USA.
21 */
22
23 #include "config.h"
24 #ifdef SVG_SUPPORT
25 #include "SVGPreserveAspectRatio.h"
26
27 #include "SVGParserUtilities.h"
28 #include "SVGSVGElement.h"
29
30 namespace WebCore {
31
32 static bool checkString(const UChar*& ptr, const UChar*& end, const char* str)
33 {
34     int length = strlen(str);
35     if (end - ptr < length)
36         return false;
37     for (int i = 0; i < length; ++i)
38         if (ptr[i] != str[i])
39             return false;
40     ptr += length;
41     return true;
42 }
43
44 SVGPreserveAspectRatio::SVGPreserveAspectRatio(const SVGStyledElement* context)
45     : Shared<SVGPreserveAspectRatio>()
46     , m_align(SVG_PRESERVEASPECTRATIO_XMIDYMID)
47     , m_meetOrSlice(SVG_MEETORSLICE_MEET)
48     , m_context(context)
49 {
50     // FIXME: Should the two values default to UNKNOWN instead?
51 }
52
53 SVGPreserveAspectRatio::~SVGPreserveAspectRatio()
54 {
55 }
56
57 void SVGPreserveAspectRatio::setAlign(unsigned short align)
58 {
59     m_align = align;
60     // FIXME: Do we need a call to notifyAttributeChange here?
61 }
62
63 unsigned short SVGPreserveAspectRatio::align() const
64 {
65     return m_align;
66 }
67
68 void SVGPreserveAspectRatio::setMeetOrSlice(unsigned short meetOrSlice)
69 {
70     m_meetOrSlice = meetOrSlice;
71     // FIXME: Do we need a call to notifyAttributeChange here?
72 }
73
74 unsigned short SVGPreserveAspectRatio::meetOrSlice() const
75 {
76     return m_meetOrSlice;
77 }
78
79 void SVGPreserveAspectRatio::parsePreserveAspectRatio(const String& string)
80 {
81     SVGPreserveAspectRatioType align = SVG_PRESERVEASPECTRATIO_NONE;
82     SVGMeetOrSliceType meetOrSlice = SVG_MEETORSLICE_MEET;
83
84     const UChar* currParam = string.characters();
85     const UChar* end = currParam + string.length();
86
87     if (!skipOptionalSpaces(currParam, end))
88         goto bail_out;
89
90     if (*currParam == 'd') {
91         if (!checkString(currParam, end, "defer"))
92             goto bail_out;
93         // FIXME: We just ignore the "defer" here.
94         if (!skipOptionalSpaces(currParam, end))
95             goto bail_out;
96     }
97
98     if (*currParam == 'n') {
99         if (!checkString(currParam, end, "none"))
100             goto bail_out;
101         skipOptionalSpaces(currParam, end);
102     } else if (*currParam == 'x') {
103         if ((end - currParam) < 8)
104             goto bail_out;
105         if (currParam[1] != 'M' || currParam[4] != 'Y' || currParam[5] != 'M')
106             goto bail_out;
107         if (currParam[2] == 'i') {
108             if (currParam[3] == 'n') {
109                 if (currParam[6] == 'i') {
110                     if (currParam[7] == 'n')
111                         align = SVG_PRESERVEASPECTRATIO_XMINYMIN;
112                     else if (currParam[7] == 'd')
113                         align = SVG_PRESERVEASPECTRATIO_XMINYMID;
114                     else
115                         goto bail_out;
116                 } else if (currParam[6] == 'a' && currParam[7] == 'x')
117                      align = SVG_PRESERVEASPECTRATIO_XMINYMAX;
118                 else
119                      goto bail_out;
120              } else if (currParam[3] == 'd') {
121                 if (currParam[6] == 'i') {
122                     if (currParam[7] == 'n')
123                         align = SVG_PRESERVEASPECTRATIO_XMIDYMIN;
124                     else if (currParam[7] == 'd')
125                         align = SVG_PRESERVEASPECTRATIO_XMIDYMID;
126                     else
127                         goto bail_out;
128                 } else if (currParam[6] == 'a' && currParam[7] == 'x')
129                     align = SVG_PRESERVEASPECTRATIO_XMIDYMAX;
130                 else
131                     goto bail_out;
132             } else
133                 goto bail_out;
134         } else if (currParam[2] == 'a' && currParam[3] == 'x') {
135             if (currParam[6] == 'i') {
136                 if (currParam[7] == 'n')
137                     align = SVG_PRESERVEASPECTRATIO_XMAXYMIN;
138                 else if (currParam[7] == 'd')
139                     align = SVG_PRESERVEASPECTRATIO_XMAXYMID;
140                 else
141                     goto bail_out;
142             } else if (currParam[6] == 'a' && currParam[7] == 'x')
143                 align = SVG_PRESERVEASPECTRATIO_XMAXYMAX;
144             else
145                 goto bail_out;
146         } else
147             goto bail_out;
148         currParam += 8;
149         skipOptionalSpaces(currParam, end);
150     } else
151         goto bail_out;
152
153     if (currParam < end) {
154         if (*currParam == 'm') {
155             if (!checkString(currParam, end, "meet"))
156                 goto bail_out;
157             skipOptionalSpaces(currParam, end);
158         } else if (*currParam == 's') {
159             if (!checkString(currParam, end, "slice"))
160                 goto bail_out;
161             skipOptionalSpaces(currParam, end);
162             if (align != SVG_PRESERVEASPECTRATIO_NONE)
163                 meetOrSlice = SVG_MEETORSLICE_SLICE;    
164         }
165     }
166
167     if (end != currParam) {
168 bail_out:
169         // FIXME: Should the two values be set to UNKNOWN instead?
170         align = SVG_PRESERVEASPECTRATIO_NONE;
171         meetOrSlice = SVG_MEETORSLICE_MEET;
172     }
173
174     if (m_align == align && m_meetOrSlice == meetOrSlice)
175         return;
176
177     m_align = align;
178     m_meetOrSlice = meetOrSlice;
179     if (m_context)
180         m_context->notifyAttributeChange();
181 }
182
183 AffineTransform SVGPreserveAspectRatio::getCTM(float logicX, float logicY,
184                                                float logicWidth, float logicHeight,
185                                                float /*physX*/, float /*physY*/,
186                                                float physWidth, float physHeight)
187 {
188     AffineTransform temp;
189
190     if (align() == SVG_PRESERVEASPECTRATIO_UNKNOWN)
191         return temp;
192
193     float vpar = logicWidth / logicHeight;
194     float svgar = physWidth / physHeight;
195
196     if (align() == SVG_PRESERVEASPECTRATIO_NONE) {
197         temp.scale(physWidth / logicWidth, physHeight / logicHeight);
198         temp.translate(-logicX, -logicY);
199     } else if (vpar < svgar && (meetOrSlice() == SVG_MEETORSLICE_MEET) || vpar >= svgar && (meetOrSlice() == SVG_MEETORSLICE_SLICE)) {
200         temp.scale(physHeight / logicHeight, physHeight / logicHeight);
201
202         if (align() == SVG_PRESERVEASPECTRATIO_XMINYMIN || align() == SVG_PRESERVEASPECTRATIO_XMINYMID || align() == SVG_PRESERVEASPECTRATIO_XMINYMAX)
203             temp.translate(-logicX, -logicY);
204         else if (align() == SVG_PRESERVEASPECTRATIO_XMIDYMIN || align() == SVG_PRESERVEASPECTRATIO_XMIDYMID || align() == SVG_PRESERVEASPECTRATIO_XMIDYMAX)
205             temp.translate(-logicX - (logicWidth - physWidth * logicHeight / physHeight) / 2, -logicY);
206         else
207             temp.translate(-logicX - (logicWidth - physWidth * logicHeight / physHeight), -logicY);
208     } else {
209         temp.scale(physWidth / logicWidth, physWidth / logicWidth);
210
211         if (align() == SVG_PRESERVEASPECTRATIO_XMINYMIN || align() == SVG_PRESERVEASPECTRATIO_XMIDYMIN || align() == SVG_PRESERVEASPECTRATIO_XMAXYMIN)
212             temp.translate(-logicX, -logicY);
213         else if (align() == SVG_PRESERVEASPECTRATIO_XMINYMID || align() == SVG_PRESERVEASPECTRATIO_XMIDYMID || align() == SVG_PRESERVEASPECTRATIO_XMAXYMID)
214             temp.translate(-logicX, -logicY - (logicHeight - physHeight * logicWidth / physWidth) / 2);
215         else
216             temp.translate(-logicX, -logicY - (logicHeight - physHeight * logicWidth / physWidth));
217     }
218
219     return temp;
220 }
221
222 }
223
224 // vim:ts=4:noet
225 #endif // SVG_SUPPORT