2006-09-09 Eric Seidel <eric@eseidel.com>
[WebKit-https.git] / WebCore / ksvg2 / svg / SVGPreserveAspectRatio.cpp
1 /*
2     Copyright (C) 2004, 2005 Nikolas Zimmermann <wildfox@kde.org>
3                   2004, 2005 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 "DeprecatedStringList.h"
26
27 #include "ksvg.h"
28 #include "SVGMatrix.h"
29 #include "SVGSVGElement.h"
30 #include "SVGPreserveAspectRatio.h"
31
32 namespace WebCore {
33
34 SVGPreserveAspectRatio::SVGPreserveAspectRatio(const SVGStyledElement *context)
35     : Shared<SVGPreserveAspectRatio>()
36     , m_align(SVG_PRESERVEASPECTRATIO_XMIDYMID)
37     , m_meetOrSlice(SVG_MEETORSLICE_MEET)
38     , m_context(context)
39 {
40 }
41
42 SVGPreserveAspectRatio::~SVGPreserveAspectRatio()
43 {
44 }
45
46 void SVGPreserveAspectRatio::setAlign(unsigned short align)
47 {
48     m_align = align;
49 }
50
51 unsigned short SVGPreserveAspectRatio::align() const
52 {
53     return m_align;
54 }
55
56 void SVGPreserveAspectRatio::setMeetOrSlice(unsigned short meetOrSlice)
57 {
58     m_meetOrSlice = meetOrSlice;
59 }
60
61 unsigned short SVGPreserveAspectRatio::meetOrSlice() const
62 {
63     return m_meetOrSlice;
64 }
65
66 void SVGPreserveAspectRatio::parsePreserveAspectRatio(const String& string)
67 {
68     // Spec: set the defaults
69     setAlign(SVG_PRESERVEASPECTRATIO_NONE);
70     setMeetOrSlice(SVG_MEETORSLICE_MEET);
71     
72     DeprecatedStringList params = DeprecatedStringList::split(' ', string.deprecatedString().simplifyWhiteSpace());
73
74     if (params[0] == "none")
75         m_align = SVG_PRESERVEASPECTRATIO_NONE;
76     else if (params[0] == "xMinYMin")
77         m_align = SVG_PRESERVEASPECTRATIO_XMINYMIN;
78     else if (params[0] == "xMidYMin")
79         m_align = SVG_PRESERVEASPECTRATIO_XMIDYMIN;
80     else if (params[0] == "xMaxYMin")
81         m_align = SVG_PRESERVEASPECTRATIO_XMAXYMIN;
82     else if (params[0] == "xMinYMid")
83         m_align = SVG_PRESERVEASPECTRATIO_XMINYMID;
84     else if (params[0] == "xMidYMid")
85         m_align = SVG_PRESERVEASPECTRATIO_XMIDYMID;
86     else if (params[0] == "xMaxYMid")
87         m_align = SVG_PRESERVEASPECTRATIO_XMAXYMID;
88     else if (params[0] == "xMinYMax")
89         m_align = SVG_PRESERVEASPECTRATIO_XMINYMAX;
90     else if (params[0] == "xMidYMax")
91         m_align = SVG_PRESERVEASPECTRATIO_XMIDYMAX;
92     else if (params[0] == "xMaxYMax")
93         m_align = SVG_PRESERVEASPECTRATIO_XMAXYMAX;
94
95     if (m_align != SVG_PRESERVEASPECTRATIO_NONE) {
96         if ((params.count() > 1) && (params[1] == "slice"))
97             m_meetOrSlice = SVG_MEETORSLICE_SLICE;
98         else
99             m_meetOrSlice = SVG_MEETORSLICE_MEET;
100     }
101
102     if (m_context)
103         m_context->notifyAttributeChange();
104 }
105
106 SVGMatrix *SVGPreserveAspectRatio::getCTM(float logicX, float logicY, float logicWidth, float logicHeight,
107                                                   float /*physX*/, float /*physY*/, 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