Home | History | Annotate | Download | only in svg
      1 /*
      2    Copyright (C) 2007 Eric Seidel <eric (at) webkit.org>
      3    Copyright (C) 2007, 2008 Nikolas Zimmermann <zimmermann (at) kde.org>
      4    Copyright (C) 2008 Rob Buis <buis (at) kde.org>
      5 
      6    This library is free software; you can redistribute it and/or
      7    modify it under the terms of the GNU Library General Public
      8    License as published by the Free Software Foundation; either
      9    version 2 of the License, or (at your option) any later version.
     10 
     11    This library is distributed in the hope that it will be useful,
     12    but WITHOUT ANY WARRANTY; without even the implied warranty of
     13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     14    Library General Public License for more details.
     15 
     16    You should have received a copy of the GNU Library General Public License
     17    along with this library; see the file COPYING.LIB.  If not, write to
     18    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     19    Boston, MA 02110-1301, USA.
     20 */
     21 
     22 #include "config.h"
     23 
     24 #if ENABLE(SVG_FONTS)
     25 #include "SVGGlyphElement.h"
     26 
     27 #include "MappedAttribute.h"
     28 #include "SVGFontData.h"
     29 #include "SVGFontElement.h"
     30 #include "SVGFontFaceElement.h"
     31 #include "SVGNames.h"
     32 #include "SVGParserUtilities.h"
     33 #include "SimpleFontData.h"
     34 #include "XMLNames.h"
     35 
     36 namespace WebCore {
     37 
     38 using namespace SVGNames;
     39 
     40 SVGGlyphElement::SVGGlyphElement(const QualifiedName& tagName, Document* doc)
     41     : SVGStyledElement(tagName, doc)
     42 {
     43 }
     44 
     45 SVGGlyphElement::~SVGGlyphElement()
     46 {
     47 }
     48 
     49 void SVGGlyphElement::invalidateGlyphCache()
     50 {
     51     Node* fontNode = parentNode();
     52     if (fontNode && fontNode->hasTagName(SVGNames::fontTag)) {
     53         if (SVGFontElement* element = static_cast<SVGFontElement*>(fontNode))
     54             element->invalidateGlyphCache();
     55     }
     56 }
     57 
     58 void SVGGlyphElement::parseMappedAttribute(MappedAttribute* attr)
     59 {
     60     if (attr->name() == SVGNames::dAttr)
     61         invalidateGlyphCache();
     62     else
     63         SVGStyledElement::parseMappedAttribute(attr);
     64 }
     65 
     66 void SVGGlyphElement::insertedIntoDocument()
     67 {
     68     invalidateGlyphCache();
     69     SVGStyledElement::insertedIntoDocument();
     70 }
     71 
     72 void SVGGlyphElement::removedFromDocument()
     73 {
     74     invalidateGlyphCache();
     75     SVGStyledElement::removedFromDocument();
     76 }
     77 
     78 static inline SVGGlyphIdentifier::ArabicForm parseArabicForm(const AtomicString& value)
     79 {
     80     if (value == "medial")
     81         return SVGGlyphIdentifier::Medial;
     82     else if (value == "terminal")
     83         return SVGGlyphIdentifier::Terminal;
     84     else if (value == "isolated")
     85         return SVGGlyphIdentifier::Isolated;
     86     else if (value == "initial")
     87         return SVGGlyphIdentifier::Initial;
     88 
     89     return SVGGlyphIdentifier::None;
     90 }
     91 
     92 static inline SVGGlyphIdentifier::Orientation parseOrientation(const AtomicString& value)
     93 {
     94     if (value == "h")
     95         return SVGGlyphIdentifier::Horizontal;
     96     else if (value == "v")
     97         return SVGGlyphIdentifier::Vertical;
     98 
     99     return SVGGlyphIdentifier::Both;
    100 }
    101 
    102 static inline Path parsePathData(const AtomicString& value)
    103 {
    104     Path result;
    105     pathFromSVGData(result, value);
    106 
    107     return result;
    108 }
    109 
    110 void SVGGlyphElement::inheritUnspecifiedAttributes(SVGGlyphIdentifier& identifier, const SVGFontData* svgFontData)
    111 {
    112     if (identifier.horizontalAdvanceX == SVGGlyphIdentifier::inheritedValue())
    113         identifier.horizontalAdvanceX = svgFontData->horizontalAdvanceX();
    114 
    115     if (identifier.verticalOriginX == SVGGlyphIdentifier::inheritedValue())
    116         identifier.verticalOriginX = svgFontData->verticalOriginX();
    117 
    118     if (identifier.verticalOriginY == SVGGlyphIdentifier::inheritedValue())
    119         identifier.verticalOriginY = svgFontData->verticalOriginY();
    120 
    121     if (identifier.verticalAdvanceY == SVGGlyphIdentifier::inheritedValue())
    122         identifier.verticalAdvanceY = svgFontData->verticalAdvanceY();
    123 }
    124 
    125 static inline float parseSVGGlyphAttribute(const SVGElement* element, const WebCore::QualifiedName& name)
    126 {
    127     AtomicString value(element->getAttribute(name));
    128     if (value.isEmpty())
    129         return SVGGlyphIdentifier::inheritedValue();
    130 
    131     return value.toFloat();
    132 }
    133 
    134 SVGGlyphIdentifier SVGGlyphElement::buildGenericGlyphIdentifier(const SVGElement* element)
    135 {
    136     SVGGlyphIdentifier identifier;
    137     identifier.pathData = parsePathData(element->getAttribute(dAttr));
    138 
    139     // Spec: The horizontal advance after rendering the glyph in horizontal orientation.
    140     // If the attribute is not specified, the effect is as if the attribute were set to the
    141     // value of the font's horiz-adv-x attribute. Glyph widths are required to be non-negative,
    142     // even if the glyph is typically rendered right-to-left, as in Hebrew and Arabic scripts.
    143     identifier.horizontalAdvanceX = parseSVGGlyphAttribute(element, horiz_adv_xAttr);
    144 
    145     // Spec: The X-coordinate in the font coordinate system of the origin of the glyph to be
    146     // used when drawing vertically oriented text. If the attribute is not specified, the effect
    147     // is as if the attribute were set to the value of the font's vert-origin-x attribute.
    148     identifier.verticalOriginX = parseSVGGlyphAttribute(element, vert_origin_xAttr);
    149 
    150     // Spec: The Y-coordinate in the font coordinate system of the origin of a glyph to be
    151     // used when drawing vertically oriented text. If the attribute is not specified, the effect
    152     // is as if the attribute were set to the value of the font's vert-origin-y attribute.
    153     identifier.verticalOriginY = parseSVGGlyphAttribute(element, vert_origin_yAttr);
    154 
    155     // Spec: The vertical advance after rendering a glyph in vertical orientation.
    156     // If the attribute is not specified, the effect is as if the attribute were set to the
    157     // value of the font's vert-adv-y attribute.
    158     identifier.verticalAdvanceY = parseSVGGlyphAttribute(element, vert_adv_yAttr);
    159 
    160     return identifier;
    161 }
    162 
    163 SVGGlyphIdentifier SVGGlyphElement::buildGlyphIdentifier() const
    164 {
    165     SVGGlyphIdentifier identifier(buildGenericGlyphIdentifier(this));
    166     identifier.glyphName = getAttribute(glyph_nameAttr);
    167     identifier.orientation = parseOrientation(getAttribute(orientationAttr));
    168     identifier.arabicForm = parseArabicForm(getAttribute(arabic_formAttr));
    169 
    170     String language = getAttribute(SVGNames::langAttr);
    171     if (!language.isEmpty())
    172         identifier.languages = parseDelimitedString(language, ',');
    173 
    174     return identifier;
    175 }
    176 
    177 }
    178 
    179 #endif // ENABLE(SVG_FONTS)
    180