• Skip to content
  • Skip to link menu
KDE 4.2 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     m_unit = storeUnit(extractMode(m_unit), type);
00255     m_valueInSpecifiedUnits = convertedNumber;
00256     return true;
00257 }
00258 
00259 String SVGLength::valueAsString() const
00260 {
00261     //return String::number(m_valueInSpecifiedUnits) + lengthTypeToString(extractType(m_unit));
00262     ASSERT(false);
00263     return "";
00264 }
00265 
00266 void SVGLength::newValueSpecifiedUnits(unsigned short type, float value)
00267 {
00268     ASSERT(type <= LengthTypePC);
00269 
00270     m_unit = storeUnit(extractMode(m_unit), (SVGLengthType) type);
00271     m_valueInSpecifiedUnits = value;
00272 }
00273 
00274 void SVGLength::convertToSpecifiedUnits(unsigned short type)
00275 {
00276     ASSERT(type <= LengthTypePC);
00277 
00278     float valueInUserUnits = value();
00279     m_unit = storeUnit(extractMode(m_unit), (SVGLengthType) type);
00280     setValue(valueInUserUnits);
00281 }
00282 
00283 float SVGLength::PercentageOfViewport(float value, const SVGStyledElement* context, SVGLengthMode mode)
00284 {
00285     ASSERT(context);
00286 
00287     float width = 0.0f, height = 0.0f;
00288     SVGElement* viewportElement = context->viewportElement();
00289 
00290     Document* doc = context->document();
00291     if (doc->documentElement() == context) {
00292         // We have to ask the canvas for the full "canvas size"...
00293         RenderView* view = static_cast<RenderView*>(doc->renderer());
00294         if (view && view->view()) {
00295             width = view->view()->visibleWidth(); // TODO: recheck!
00296             height = view->view()->visibleHeight(); // TODO: recheck!
00297          }
00298     } else if (viewportElement && viewportElement->isSVG()) {
00299         const SVGSVGElement* svg = static_cast<const SVGSVGElement*>(viewportElement);
00300         if (svg->hasAttribute(SVGNames::viewBoxAttr)) {
00301             width = svg->viewBox().width();
00302             height = svg->viewBox().height();
00303         } else {
00304             width = svg->width().value();
00305             height = svg->height().value();
00306         }
00307     } else if (context->parent() && !context->parent()->isSVGElement()) {
00308         if (RenderObject* renderer = context->renderer()) {
00309             width = renderer->width();
00310             height = renderer->height();
00311         }
00312     }
00313 
00314     if (mode == LengthModeWidth)
00315         return value * width;
00316     else if (mode == LengthModeHeight)
00317         return value * height;
00318     else if (mode == LengthModeOther)
00319         return value * sqrtf(powf(width, 2) + powf(height, 2)) / sqrtf(2.0f);
00320 
00321     return 0.0f;
00322 }
00323 
00324 }
00325 
00326 #endif // ENABLE(SVG)
00327 
00328 // 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
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.7
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