• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 Eric Seidel <eric@webkit.org>
3  * Copyright (C) 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org>
4  * Copyright (C) 2008 Rob Buis <buis@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 "core/svg/SVGGlyphElement.h"
26 
27 #include "core/svg/SVGFontData.h"
28 #include "core/svg/SVGFontElement.h"
29 #include "core/svg/SVGPathUtilities.h"
30 
31 namespace WebCore {
32 
SVGGlyphElement(Document & document)33 inline SVGGlyphElement::SVGGlyphElement(Document& document)
34     : SVGElement(SVGNames::glyphTag, document)
35 {
36     ScriptWrappable::init(this);
37 }
38 
create(Document & document)39 PassRefPtr<SVGGlyphElement> SVGGlyphElement::create(Document& document)
40 {
41     return adoptRef(new SVGGlyphElement(document));
42 }
43 
invalidateGlyphCache()44 void SVGGlyphElement::invalidateGlyphCache()
45 {
46     ContainerNode* fontNode = parentNode();
47     if (fontNode && fontNode->hasTagName(SVGNames::fontTag))
48         toSVGFontElement(fontNode)->invalidateGlyphCache();
49 }
50 
parseAttribute(const QualifiedName & name,const AtomicString & value)51 void SVGGlyphElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
52 {
53     if (name == SVGNames::dAttr)
54         invalidateGlyphCache();
55     else
56         SVGElement::parseAttribute(name, value);
57 }
58 
insertedInto(ContainerNode * rootParent)59 Node::InsertionNotificationRequest SVGGlyphElement::insertedInto(ContainerNode* rootParent)
60 {
61     invalidateGlyphCache();
62     return SVGElement::insertedInto(rootParent);
63 }
64 
removedFrom(ContainerNode * rootParent)65 void SVGGlyphElement::removedFrom(ContainerNode* rootParent)
66 {
67     if (rootParent->inDocument())
68         invalidateGlyphCache();
69     SVGElement::removedFrom(rootParent);
70 }
71 
parseArabicForm(const AtomicString & value)72 static inline SVGGlyph::ArabicForm parseArabicForm(const AtomicString& value)
73 {
74     if (value == "medial")
75         return SVGGlyph::Medial;
76     if (value == "terminal")
77         return SVGGlyph::Terminal;
78     if (value == "isolated")
79         return SVGGlyph::Isolated;
80     if (value == "initial")
81         return SVGGlyph::Initial;
82 
83     return SVGGlyph::None;
84 }
85 
parseOrientation(const AtomicString & value)86 static inline SVGGlyph::Orientation parseOrientation(const AtomicString& value)
87 {
88     if (value == "h")
89         return SVGGlyph::Horizontal;
90     if (value == "v")
91         return SVGGlyph::Vertical;
92 
93     return SVGGlyph::Both;
94 }
95 
inheritUnspecifiedAttributes(SVGGlyph & identifier,const SVGFontData * svgFontData)96 void SVGGlyphElement::inheritUnspecifiedAttributes(SVGGlyph& identifier, const SVGFontData* svgFontData)
97 {
98     if (identifier.horizontalAdvanceX == SVGGlyph::inheritedValue())
99         identifier.horizontalAdvanceX = svgFontData->horizontalAdvanceX();
100 
101     if (identifier.verticalOriginX == SVGGlyph::inheritedValue())
102         identifier.verticalOriginX = svgFontData->verticalOriginX();
103 
104     if (identifier.verticalOriginY == SVGGlyph::inheritedValue())
105         identifier.verticalOriginY = svgFontData->verticalOriginY();
106 
107     if (identifier.verticalAdvanceY == SVGGlyph::inheritedValue())
108         identifier.verticalAdvanceY = svgFontData->verticalAdvanceY();
109 }
110 
parseSVGGlyphAttribute(const SVGElement * element,const WebCore::QualifiedName & name)111 static inline float parseSVGGlyphAttribute(const SVGElement* element, const WebCore::QualifiedName& name)
112 {
113     AtomicString value(element->fastGetAttribute(name));
114     if (value.isEmpty())
115         return SVGGlyph::inheritedValue();
116 
117     return value.toFloat();
118 }
119 
buildGenericGlyphIdentifier(const SVGElement * element)120 SVGGlyph SVGGlyphElement::buildGenericGlyphIdentifier(const SVGElement* element)
121 {
122     SVGGlyph identifier;
123     buildPathFromString(element->fastGetAttribute(SVGNames::dAttr), identifier.pathData);
124 
125     // Spec: The horizontal advance after rendering the glyph in horizontal orientation.
126     // If the attribute is not specified, the effect is as if the attribute were set to the
127     // value of the font's horiz-adv-x attribute. Glyph widths are required to be non-negative,
128     // even if the glyph is typically rendered right-to-left, as in Hebrew and Arabic scripts.
129     identifier.horizontalAdvanceX = parseSVGGlyphAttribute(element, SVGNames::horiz_adv_xAttr);
130 
131     // Spec: The X-coordinate in the font coordinate system of the origin of the glyph to be
132     // used when drawing vertically oriented text. If the attribute is not specified, the effect
133     // is as if the attribute were set to the value of the font's vert-origin-x attribute.
134     identifier.verticalOriginX = parseSVGGlyphAttribute(element, SVGNames::vert_origin_xAttr);
135 
136     // Spec: The Y-coordinate in the font coordinate system of the origin of a glyph to be
137     // used when drawing vertically oriented text. If the attribute is not specified, the effect
138     // is as if the attribute were set to the value of the font's vert-origin-y attribute.
139     identifier.verticalOriginY = parseSVGGlyphAttribute(element, SVGNames::vert_origin_yAttr);
140 
141     // Spec: The vertical advance after rendering a glyph in vertical orientation.
142     // If the attribute is not specified, the effect is as if the attribute were set to the
143     // value of the font's vert-adv-y attribute.
144     identifier.verticalAdvanceY = parseSVGGlyphAttribute(element, SVGNames::vert_adv_yAttr);
145 
146     return identifier;
147 }
148 
buildGlyphIdentifier() const149 SVGGlyph SVGGlyphElement::buildGlyphIdentifier() const
150 {
151     SVGGlyph identifier(buildGenericGlyphIdentifier(this));
152     identifier.glyphName = fastGetAttribute(SVGNames::glyph_nameAttr);
153     identifier.orientation = parseOrientation(fastGetAttribute(SVGNames::orientationAttr));
154     identifier.arabicForm = parseArabicForm(fastGetAttribute(SVGNames::arabic_formAttr));
155 
156     String language = fastGetAttribute(SVGNames::langAttr);
157     if (!language.isEmpty())
158         identifier.languages = parseDelimitedString(language, ',');
159 
160     return identifier;
161 }
162 
163 }
164 
165 #endif // ENABLE(SVG_FONTS)
166