Fixes: http://bugs.webkit.org/show_bug.cgi?id=11797
[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 "SVGSVGElement.h"
28
29 namespace WebCore {
30
31 SVGPreserveAspectRatio::SVGPreserveAspectRatio(const SVGStyledElement* context)
32     : Shared<SVGPreserveAspectRatio>()
33     , m_align(SVG_PRESERVEASPECTRATIO_XMIDYMID)
34     , m_meetOrSlice(SVG_MEETORSLICE_MEET)
35     , m_context(context)
36 {
37 }
38
39 SVGPreserveAspectRatio::~SVGPreserveAspectRatio()
40 {
41 }
42
43 void SVGPreserveAspectRatio::setAlign(unsigned short align)
44 {
45     m_align = align;
46 }
47
48 unsigned short SVGPreserveAspectRatio::align() const
49 {
50     return m_align;
51 }
52
53 void SVGPreserveAspectRatio::setMeetOrSlice(unsigned short meetOrSlice)
54 {
55     m_meetOrSlice = meetOrSlice;
56 }
57
58 unsigned short SVGPreserveAspectRatio::meetOrSlice() const
59 {
60     return m_meetOrSlice;
61 }
62
63 void SVGPreserveAspectRatio::parsePreserveAspectRatio(const String& string)
64 {
65     // Spec: set the defaults
66     setAlign(SVG_PRESERVEASPECTRATIO_NONE);
67     setMeetOrSlice(SVG_MEETORSLICE_MEET);
68     
69     Vector<String> params = string.simplifyWhiteSpace().split(' ');
70
71     if (params[0] == "none")
72         m_align = SVG_PRESERVEASPECTRATIO_NONE;
73     else if (params[0] == "xMinYMin")
74         m_align = SVG_PRESERVEASPECTRATIO_XMINYMIN;
75     else if (params[0] == "xMidYMin")
76         m_align = SVG_PRESERVEASPECTRATIO_XMIDYMIN;
77     else if (params[0] == "xMaxYMin")
78         m_align = SVG_PRESERVEASPECTRATIO_XMAXYMIN;
79     else if (params[0] == "xMinYMid")
80         m_align = SVG_PRESERVEASPECTRATIO_XMINYMID;
81     else if (params[0] == "xMidYMid")
82         m_align = SVG_PRESERVEASPECTRATIO_XMIDYMID;
83     else if (params[0] == "xMaxYMid")
84         m_align = SVG_PRESERVEASPECTRATIO_XMAXYMID;
85     else if (params[0] == "xMinYMax")
86         m_align = SVG_PRESERVEASPECTRATIO_XMINYMAX;
87     else if (params[0] == "xMidYMax")
88         m_align = SVG_PRESERVEASPECTRATIO_XMIDYMAX;
89     else if (params[0] == "xMaxYMax")
90         m_align = SVG_PRESERVEASPECTRATIO_XMAXYMAX;
91
92     if (m_align != SVG_PRESERVEASPECTRATIO_NONE) {
93         if ((params.size() > 1) && (params[1] == "slice"))
94             m_meetOrSlice = SVG_MEETORSLICE_SLICE;
95         else
96             m_meetOrSlice = SVG_MEETORSLICE_MEET;
97     }
98
99     if (m_context)
100         m_context->notifyAttributeChange();
101 }
102
103 AffineTransform SVGPreserveAspectRatio::getCTM(float logicX, float logicY,
104                                                float logicWidth, float logicHeight,
105                                                float /*physX*/, float /*physY*/,
106                                                float physWidth, float physHeight)
107 {
108     AffineTransform temp;
109
110     if (align() == SVG_PRESERVEASPECTRATIO_UNKNOWN)
111         return temp;
112
113     float vpar = logicWidth / logicHeight;
114     float svgar = physWidth / physHeight;
115
116     if (align() == SVG_PRESERVEASPECTRATIO_NONE) {
117         temp.scale(physWidth / logicWidth, physHeight / logicHeight);
118         temp.translate(-logicX, -logicY);
119     } else if (vpar < svgar && (meetOrSlice() == SVG_MEETORSLICE_MEET) || vpar >= svgar && (meetOrSlice() == SVG_MEETORSLICE_SLICE)) {
120         temp.scale(physHeight / logicHeight, physHeight / logicHeight);
121
122         if (align() == SVG_PRESERVEASPECTRATIO_XMINYMIN || align() == SVG_PRESERVEASPECTRATIO_XMINYMID || align() == SVG_PRESERVEASPECTRATIO_XMINYMAX)
123             temp.translate(-logicX, -logicY);
124         else if (align() == SVG_PRESERVEASPECTRATIO_XMIDYMIN || align() == SVG_PRESERVEASPECTRATIO_XMIDYMID || align() == SVG_PRESERVEASPECTRATIO_XMIDYMAX)
125             temp.translate(-logicX - (logicWidth - physWidth * logicHeight / physHeight) / 2, -logicY);
126         else
127             temp.translate(-logicX - (logicWidth - physWidth * logicHeight / physHeight), -logicY);
128     } else {
129         temp.scale(physWidth / logicWidth, physWidth / logicWidth);
130
131         if (align() == SVG_PRESERVEASPECTRATIO_XMINYMIN || align() == SVG_PRESERVEASPECTRATIO_XMIDYMIN || align() == SVG_PRESERVEASPECTRATIO_XMAXYMIN)
132             temp.translate(-logicX, -logicY);
133         else if (align() == SVG_PRESERVEASPECTRATIO_XMINYMID || align() == SVG_PRESERVEASPECTRATIO_XMIDYMID || align() == SVG_PRESERVEASPECTRATIO_XMAXYMID)
134             temp.translate(-logicX, -logicY - (logicHeight - physHeight * logicWidth / physWidth) / 2);
135         else
136             temp.translate(-logicX, -logicY - (logicHeight - physHeight * logicWidth / physWidth));
137     }
138
139     return temp;
140 }
141
142 }
143
144 // vim:ts=4:noet
145 #endif // SVG_SUPPORT
146