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