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