• Skip to content
  • Skip to link menu
KDE 4.3 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

KHTML

SVGLength.cpp

Go to the documentation of this file.
00001 /*
00002     Copyright (C) 2004, 2005, 2006 Nikolas Zimmermann <zimmermann@kde.org>
00003                   2004, 2005, 2006, 2007 Rob Buis <buis@kde.org>
00004                   2007 Apple Inc.  All rights reserved.
00005 
00006     This file is part of the KDE project
00007 
00008     This library is free software; you can redistribute it and/or
00009     modify it under the terms of the GNU Library General Public
00010     License as published by the Free Software Foundation; either
00011     version 2 of the License, or (at your option) any later version.
00012 
00013     This library is distributed in the hope that it will be useful,
00014     but WITHOUT ANY WARRANTY; without even the implied warranty of
00015     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016     Library General Public License for more details.
00017 
00018     You should have received a copy of the GNU Library General Public License
00019     along with this library; see the file COPYING.LIB.  If not, write to
00020     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00021     Boston, MA 02110-1301, USA.
00022 */
00023 
00024 #include "config.h"
00025 #include "wtf/Platform.h"
00026 
00027 #if ENABLE(SVG)
00028 #include "SVGLength.h"
00029 
00030 #include "css/csshelper.h"
00031 #include "FloatConversion.h"
00032 /*#include "FrameView.h"*/
00033 #include "RenderObject.h"
00034 #include "RenderView.h"
00035 #include "SVGParserUtilities.h"
00036 #include "SVGSVGElement.h"
00037 #include "SVGStyledElement.h"
00038 
00039 #include <math.h>
00040 #include <wtf/Assertions.h>
00041 
00042 namespace WebCore {
00043 
00044 // Helper functions
00045 static inline unsigned int storeUnit(SVGLengthMode mode, SVGLengthType type)
00046 {
00047     return (mode << 4) | type;
00048 }
00049 
00050 static inline SVGLengthMode extractMode(unsigned int unit)
00051 {
00052     unsigned int mode = unit >> 4;    
00053     return static_cast<SVGLengthMode>(mode);
00054 }
00055 
00056 static inline SVGLengthType extractType(unsigned int unit)
00057 {
00058     unsigned int mode = unit >> 4;
00059     unsigned int type = unit ^ (mode << 4);
00060     return static_cast<SVGLengthType>(type);
00061 }
00062 
00063 static inline String lengthTypeToString(SVGLengthType type)
00064 {
00065     switch (type) {
00066     case LengthTypeUnknown:
00067     case LengthTypeNumber:
00068         return "";    
00069     case LengthTypePercentage:
00070         return "%";
00071     case LengthTypeEMS:
00072         return "em";
00073     case LengthTypeEXS:
00074         return "ex";
00075     case LengthTypePX:
00076         return "px";
00077     case LengthTypeCM:
00078         return "cm";
00079     case LengthTypeMM:
00080         return "mm";
00081     case LengthTypeIN:
00082         return "in";
00083     case LengthTypePT:
00084         return "pt";
00085     case LengthTypePC:
00086         return "pc";
00087     }
00088 
00089     return String();
00090 }
00091 
00092 inline SVGLengthType stringToLengthType(const String& string)
00093 {
00094     if (string.endsWith("%"))
00095         return LengthTypePercentage;
00096     else if (string.endsWith("em"))
00097         return LengthTypeEMS;
00098     else if (string.endsWith("ex"))
00099         return LengthTypeEXS;
00100     else if (string.endsWith("px"))
00101         return LengthTypePX;
00102     else if (string.endsWith("cm"))
00103         return LengthTypeCM;
00104     else if (string.endsWith("mm"))
00105         return LengthTypeMM;
00106     else if (string.endsWith("in"))
00107         return LengthTypeIN;
00108     else if (string.endsWith("pt"))
00109         return LengthTypePT;
00110     else if (string.endsWith("pc"))
00111         return LengthTypePC;
00112     else if (!string.isEmpty())
00113         return LengthTypeNumber;
00114 
00115     return LengthTypeUnknown;
00116 }
00117 
00118 SVGLength::SVGLength(const SVGStyledElement* context, SVGLengthMode mode, const String& valueAsString)
00119     : m_valueInSpecifiedUnits(0.0f)
00120     , m_unit(storeUnit(mode, LengthTypeNumber))
00121     , m_context(context)
00122 {
00123     setValueAsString(valueAsString);
00124 }
00125 
00126 SVGLengthType SVGLength::unitType() const
00127 {
00128     return extractType(m_unit);
00129 }
00130 
00131 float SVGLength::value() const
00132 {
00133     SVGLengthType type = extractType(m_unit);
00134     if (type == LengthTypeUnknown)
00135         return 0.0f;
00136 
00137     switch (type) {
00138     case LengthTypeNumber:
00139         return m_valueInSpecifiedUnits;
00140     case LengthTypePercentage:
00141         return SVGLength::PercentageOfViewport(m_valueInSpecifiedUnits / 100.0f, m_context, extractMode(m_unit));
00142     case LengthTypeEMS:
00143     case LengthTypeEXS:
00144     {
00145         /*RenderStyle* style = 0;
00146         if (m_context && m_context->renderer())
00147             style = m_context->renderer()->style();
00148         if (style) {
00149             float useSize = style->fontSize();
00150             ASSERT(useSize > 0);
00151             if (type == LengthTypeEMS)
00152                 return m_valueInSpecifiedUnits * useSize;
00153             else {
00154                 float xHeight = style->font().xHeight();
00155                 // Use of ceil allows a pixel match to the W3Cs expected output of coords-units-03-b.svg
00156                 // if this causes problems in real world cases maybe it would be best to remove this
00157                 return m_valueInSpecifiedUnits * ceilf(xHeight);
00158             }
00159         }*/
00160         return 0.0f;
00161     }
00162     case LengthTypePX:
00163         return m_valueInSpecifiedUnits;
00164     case LengthTypeCM:
00165         return m_valueInSpecifiedUnits / 2.54f * cssPixelsPerInch;
00166     case LengthTypeMM:
00167         return m_valueInSpecifiedUnits / 25.4f * cssPixelsPerInch;
00168     case LengthTypeIN:
00169         return m_valueInSpecifiedUnits * cssPixelsPerInch;
00170     case LengthTypePT:
00171         return m_valueInSpecifiedUnits / 72.0f * cssPixelsPerInch;
00172     case LengthTypePC:
00173         return m_valueInSpecifiedUnits / 6.0f * cssPixelsPerInch;
00174     default:
00175         break;
00176     }
00177 
00178     ASSERT_NOT_REACHED();
00179     return 0.0f;
00180 }
00181 
00182 void SVGLength::setValue(float value)
00183 {
00184     SVGLengthType type = extractType(m_unit);
00185     ASSERT(type != LengthTypeUnknown);
00186 
00187     switch (type) {
00188     case LengthTypeNumber:
00189         m_valueInSpecifiedUnits = value;
00190         break;
00191     case LengthTypePercentage:
00192     case LengthTypeEMS:
00193     case LengthTypeEXS:
00194         ASSERT_NOT_REACHED();
00195         break;
00196     case LengthTypePX:
00197         m_valueInSpecifiedUnits = value;
00198         break;
00199     case LengthTypeCM:
00200         m_valueInSpecifiedUnits = value * 2.54f / cssPixelsPerInch;
00201         break;
00202     case LengthTypeMM:
00203         m_valueInSpecifiedUnits = value * 25.4f / cssPixelsPerInch;
00204         break;
00205     case LengthTypeIN:
00206         m_valueInSpecifiedUnits = value / cssPixelsPerInch;
00207         break;
00208     case LengthTypePT:
00209         m_valueInSpecifiedUnits = value * 72.0f / cssPixelsPerInch;
00210         break;
00211     case LengthTypePC:
00212         m_valueInSpecifiedUnits = value / 6.0f * cssPixelsPerInch;
00213         break;
00214     default:
00215         break;
00216     }
00217 }
00218 
00219 void SVGLength::setValueInSpecifiedUnits(float value)
00220 {
00221     m_valueInSpecifiedUnits = value;
00222 }
00223 
00224 float SVGLength::valueInSpecifiedUnits() const
00225 {
00226     return m_valueInSpecifiedUnits;
00227 }
00228 
00229 float SVGLength::valueAsPercentage() const
00230 {
00231     // 100% = 100.0 instead of 1.0 for historical reasons, this could eventually be changed
00232     if (extractType(m_unit) == LengthTypePercentage)
00233         return valueInSpecifiedUnits() / 100.0f;
00234 
00235     return valueInSpecifiedUnits();
00236 }
00237 
00238 bool SVGLength::setValueAsString(const String& s)
00239 {
00240     if (s.isEmpty())
00241         return false;
00242 
00243     float convertedNumber = 0.0f;
00244     const UChar* ptr = s.characters();
00245     const UChar* end = ptr + s.length();
00246 
00247     if (!parseNumber(ptr, end, convertedNumber, false))
00248         return false;
00249 
00250     SVGLengthType type = stringToLengthType(s);
00251     if (ptr != end && type == LengthTypeNumber)
00252         return false;
00253 
00254     kDebug() << convertedNumber << type;
00255 
00256     m_unit = storeUnit(extractMode(m_unit), type);
00257     m_valueInSpecifiedUnits = convertedNumber;
00258     return true;
00259 }
00260 
00261 String SVGLength::valueAsString() const
00262 {
00263     //return String::number(m_valueInSpecifiedUnits) + lengthTypeToString(extractType(m_unit));
00264     ASSERT(false);
00265     return "";
00266 }
00267 
00268 void SVGLength::newValueSpecifiedUnits(unsigned short type, float value)
00269 {
00270     ASSERT(type <= LengthTypePC);
00271 
00272     m_unit = storeUnit(extractMode(m_unit), (SVGLengthType) type);
00273     m_valueInSpecifiedUnits = value;
00274 }
00275 
00276 void SVGLength::convertToSpecifiedUnits(unsigned short type)
00277 {
00278     ASSERT(type <= LengthTypePC);
00279 
00280     float valueInUserUnits = value();
00281     m_unit = storeUnit(extractMode(m_unit), (SVGLengthType) type);
00282     setValue(valueInUserUnits);
00283 }
00284 
00285 float SVGLength::PercentageOfViewport(float value, const SVGStyledElement* context, SVGLengthMode mode)
00286 {
00287     ASSERT(context);
00288 
00289     float width = 0.0f, height = 0.0f;
00290     SVGElement* viewportElement = context->viewportElement();
00291 
00292     Document* doc = context->document();
00293     if (doc->documentElement() == context) {
00294         // We have to ask the canvas for the full "canvas size"...
00295         RenderView* view = static_cast<RenderView*>(doc->renderer());
00296         if (view && view->view()) {
00297             width = view->view()->visibleWidth(); // TODO: recheck!
00298             height = view->view()->visibleHeight(); // TODO: recheck!
00299          }
00300     } else if (viewportElement && viewportElement->isSVG()) {
00301         const SVGSVGElement* svg = static_cast<const SVGSVGElement*>(viewportElement);
00302         if (svg->hasAttribute(SVGNames::viewBoxAttr)) {
00303             width = svg->viewBox().width();
00304             height = svg->viewBox().height();
00305         } else {
00306             width = svg->width().value();
00307             height = svg->height().value();
00308         }
00309     } else if (context->parent() && !context->parent()->isSVGElement()) {
00310         if (RenderObject* renderer = context->renderer()) {
00311             width = renderer->width();
00312             height = renderer->height();
00313         }
00314     }
00315 
00316     if (mode == LengthModeWidth)
00317         return value * width;
00318     else if (mode == LengthModeHeight)
00319         return value * height;
00320     else if (mode == LengthModeOther)
00321         return value * sqrtf(powf(width, 2) + powf(height, 2)) / sqrtf(2.0f);
00322 
00323     return 0.0f;
00324 }
00325 
00326 }
00327 
00328 #endif // ENABLE(SVG)
00329 
00330 // vim:ts=4:noet

KHTML

Skip menu "KHTML"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.6.1
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal