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