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