File indexing completed on 2024-04-28 15:24:40

0001 /*
0002     Copyright (C) 2004, 2005, 2008 Nikolas Zimmermann <zimmermann@kde.org>
0003                   2004, 2005, 2006, 2007 Rob Buis <buis@kde.org>
0004 
0005     This file is part of the KDE project
0006 
0007     This library is free software; you can redistribute it and/or
0008     modify it under the terms of the GNU Library General Public
0009     License as published by the Free Software Foundation; either
0010     version 2 of the License, or (at your option) any later version.
0011 
0012     This library is distributed in the hope that it will be useful,
0013     but WITHOUT ANY WARRANTY; without even the implied warranty of
0014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0015     Library General Public License for more details.
0016 
0017     You should have received a copy of the GNU Library General Public License
0018     along with this library; see the file COPYING.LIB.  If not, write to
0019     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0020     Boston, MA 02110-1301, USA.
0021 */
0022 
0023 #include "wtf/Platform.h"
0024 
0025 #if ENABLE(SVG)
0026 #include "SVGPreserveAspectRatio.h"
0027 
0028 #include "SVGParserUtilities.h"
0029 #include "SVGSVGElement.h"
0030 
0031 namespace WebCore
0032 {
0033 
0034 SVGPreserveAspectRatio::SVGPreserveAspectRatio()
0035     : m_align(SVG_PRESERVEASPECTRATIO_XMIDYMID)
0036     , m_meetOrSlice(SVG_MEETORSLICE_MEET)
0037 {
0038     // FIXME: Should the two values default to UNKNOWN instead?
0039 }
0040 
0041 SVGPreserveAspectRatio::~SVGPreserveAspectRatio()
0042 {
0043 }
0044 
0045 void SVGPreserveAspectRatio::setAlign(unsigned short align)
0046 {
0047     m_align = align;
0048 }
0049 
0050 unsigned short SVGPreserveAspectRatio::align() const
0051 {
0052     return m_align;
0053 }
0054 
0055 void SVGPreserveAspectRatio::setMeetOrSlice(unsigned short meetOrSlice)
0056 {
0057     m_meetOrSlice = meetOrSlice;
0058 }
0059 
0060 unsigned short SVGPreserveAspectRatio::meetOrSlice() const
0061 {
0062     return m_meetOrSlice;
0063 }
0064 
0065 bool SVGPreserveAspectRatio::parsePreserveAspectRatio(const UChar *&currParam, const UChar *end, bool validate)
0066 {
0067     SVGPreserveAspectRatioType align = SVG_PRESERVEASPECTRATIO_NONE;
0068     SVGMeetOrSliceType meetOrSlice = SVG_MEETORSLICE_MEET;
0069     bool ret = false;
0070 
0071     if (!skipOptionalSpaces(currParam, end)) {
0072         goto bail_out;
0073     }
0074 
0075     if (*currParam == 'd') {
0076         /*if (!skipString(currParam, end, "defer"))
0077             goto bail_out;
0078         // FIXME: We just ignore the "defer" here.
0079         if (!skipOptionalSpaces(currParam, end))
0080             goto bail_out;*/
0081     }
0082 
0083     if (*currParam == 'n') {
0084         /*if (!skipString(currParam, end, "none"))
0085             goto bail_out;*/
0086         skipOptionalSpaces(currParam, end);
0087     } else if (*currParam == 'x') {
0088         if ((end - currParam) < 8) {
0089             goto bail_out;
0090         }
0091         if (currParam[1] != 'M' || currParam[4] != 'Y' || currParam[5] != 'M') {
0092             goto bail_out;
0093         }
0094         if (currParam[2] == 'i') {
0095             if (currParam[3] == 'n') {
0096                 if (currParam[6] == 'i') {
0097                     if (currParam[7] == 'n') {
0098                         align = SVG_PRESERVEASPECTRATIO_XMINYMIN;
0099                     } else if (currParam[7] == 'd') {
0100                         align = SVG_PRESERVEASPECTRATIO_XMINYMID;
0101                     } else {
0102                         goto bail_out;
0103                     }
0104                 } else if (currParam[6] == 'a' && currParam[7] == 'x') {
0105                     align = SVG_PRESERVEASPECTRATIO_XMINYMAX;
0106                 } else {
0107                     goto bail_out;
0108                 }
0109             } else if (currParam[3] == 'd') {
0110                 if (currParam[6] == 'i') {
0111                     if (currParam[7] == 'n') {
0112                         align = SVG_PRESERVEASPECTRATIO_XMIDYMIN;
0113                     } else if (currParam[7] == 'd') {
0114                         align = SVG_PRESERVEASPECTRATIO_XMIDYMID;
0115                     } else {
0116                         goto bail_out;
0117                     }
0118                 } else if (currParam[6] == 'a' && currParam[7] == 'x') {
0119                     align = SVG_PRESERVEASPECTRATIO_XMIDYMAX;
0120                 } else {
0121                     goto bail_out;
0122                 }
0123             } else {
0124                 goto bail_out;
0125             }
0126         } else if (currParam[2] == 'a' && currParam[3] == 'x') {
0127             if (currParam[6] == 'i') {
0128                 if (currParam[7] == 'n') {
0129                     align = SVG_PRESERVEASPECTRATIO_XMAXYMIN;
0130                 } else if (currParam[7] == 'd') {
0131                     align = SVG_PRESERVEASPECTRATIO_XMAXYMID;
0132                 } else {
0133                     goto bail_out;
0134                 }
0135             } else if (currParam[6] == 'a' && currParam[7] == 'x') {
0136                 align = SVG_PRESERVEASPECTRATIO_XMAXYMAX;
0137             } else {
0138                 goto bail_out;
0139             }
0140         } else {
0141             goto bail_out;
0142         }
0143         currParam += 8;
0144         skipOptionalSpaces(currParam, end);
0145     } else {
0146         goto bail_out;
0147     }
0148 
0149     if (currParam < end) {
0150         if (*currParam == 'm') {
0151             /*if (!skipString(currParam, end, "meet"))
0152                 goto bail_out;
0153             skipOptionalSpaces(currParam, end);*/
0154         } else if (*currParam == 's') {
0155             /*if (!skipString(currParam, end, "slice"))
0156                 goto bail_out;
0157             skipOptionalSpaces(currParam, end);
0158             if (align != SVG_PRESERVEASPECTRATIO_NONE)
0159                 meetOrSlice = SVG_MEETORSLICE_SLICE;*/
0160         }
0161     }
0162 
0163     if (end != currParam && validate) {
0164     bail_out:
0165         // FIXME: Should the two values be set to UNKNOWN instead?
0166         align = SVG_PRESERVEASPECTRATIO_NONE;
0167         meetOrSlice = SVG_MEETORSLICE_MEET;
0168     } else {
0169         ret = true;
0170     }
0171 
0172     if (m_align == align && m_meetOrSlice == meetOrSlice) {
0173         return ret;
0174     }
0175 
0176     m_align = align;
0177     m_meetOrSlice = meetOrSlice;
0178     return ret;
0179 }
0180 
0181 AffineTransform SVGPreserveAspectRatio::getCTM(double logicX, double logicY,
0182         double logicWidth, double logicHeight,
0183         double /*physX*/, double /*physY*/,
0184         double physWidth, double physHeight)
0185 {
0186     AffineTransform temp;
0187 
0188     if (align() == SVG_PRESERVEASPECTRATIO_UNKNOWN) {
0189         return temp;
0190     }
0191 
0192     double vpar = logicWidth / logicHeight;
0193     double svgar = physWidth / physHeight;
0194 
0195     if (align() == SVG_PRESERVEASPECTRATIO_NONE) {
0196         temp.scale(physWidth / logicWidth, physHeight / logicHeight);
0197         temp.translate(-logicX, -logicY);
0198     } else if ((vpar < svgar && meetOrSlice() == SVG_MEETORSLICE_MEET) || (vpar >= svgar && meetOrSlice() == SVG_MEETORSLICE_SLICE)) {
0199         temp.scale(physHeight / logicHeight, physHeight / logicHeight);
0200 
0201         if (align() == SVG_PRESERVEASPECTRATIO_XMINYMIN || align() == SVG_PRESERVEASPECTRATIO_XMINYMID || align() == SVG_PRESERVEASPECTRATIO_XMINYMAX) {
0202             temp.translate(-logicX, -logicY);
0203         } else if (align() == SVG_PRESERVEASPECTRATIO_XMIDYMIN || align() == SVG_PRESERVEASPECTRATIO_XMIDYMID || align() == SVG_PRESERVEASPECTRATIO_XMIDYMAX) {
0204             temp.translate(-logicX - (logicWidth - physWidth * logicHeight / physHeight) / 2, -logicY);
0205         } else {
0206             temp.translate(-logicX - (logicWidth - physWidth * logicHeight / physHeight), -logicY);
0207         }
0208     } else {
0209         temp.scale(physWidth / logicWidth, physWidth / logicWidth);
0210 
0211         if (align() == SVG_PRESERVEASPECTRATIO_XMINYMIN || align() == SVG_PRESERVEASPECTRATIO_XMIDYMIN || align() == SVG_PRESERVEASPECTRATIO_XMAXYMIN) {
0212             temp.translate(-logicX, -logicY);
0213         } else if (align() == SVG_PRESERVEASPECTRATIO_XMINYMID || align() == SVG_PRESERVEASPECTRATIO_XMIDYMID || align() == SVG_PRESERVEASPECTRATIO_XMAXYMID) {
0214             temp.translate(-logicX, -logicY - (logicHeight - physHeight * logicWidth / physWidth) / 2);
0215         } else {
0216             temp.translate(-logicX, -logicY - (logicHeight - physHeight * logicWidth / physWidth));
0217         }
0218     }
0219 
0220     return temp;
0221 }
0222 
0223 }
0224 
0225 #endif // ENABLE(SVG)