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 "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 36namespace WebCore { 37 38using namespace SVGNames; 39 40SVGGlyphElement::SVGGlyphElement(const QualifiedName& tagName, Document* doc) 41 : SVGStyledElement(tagName, doc) 42{ 43} 44 45SVGGlyphElement::~SVGGlyphElement() 46{ 47} 48 49void 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 58void SVGGlyphElement::parseMappedAttribute(MappedAttribute* attr) 59{ 60 if (attr->name() == SVGNames::dAttr) 61 invalidateGlyphCache(); 62 else 63 SVGStyledElement::parseMappedAttribute(attr); 64} 65 66void SVGGlyphElement::insertedIntoDocument() 67{ 68 invalidateGlyphCache(); 69 SVGStyledElement::insertedIntoDocument(); 70} 71 72void SVGGlyphElement::removedFromDocument() 73{ 74 invalidateGlyphCache(); 75 SVGStyledElement::removedFromDocument(); 76} 77 78static 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 92static 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 102static inline Path parsePathData(const AtomicString& value) 103{ 104 Path result; 105 pathFromSVGData(result, value); 106 107 return result; 108} 109 110void 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 125static 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 134SVGGlyphIdentifier 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 163SVGGlyphIdentifier 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