File indexing completed on 2024-04-28 15:24:34

0001 /*
0002    Copyright (C) 2007 Eric Seidel <eric@webkit.org>
0003    Copyright (C) 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org>
0004 
0005    This library is free software; you can redistribute it and/or
0006    modify it under the terms of the GNU Library General Public
0007    License as published by the Free Software Foundation; either
0008    version 2 of the License, or (at your option) any later version.
0009 
0010    This library is distributed in the hope that it will be useful,
0011    but WITHOUT ANY WARRANTY; without even the implied warranty of
0012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0013    Library General Public License for more details.
0014 
0015    You should have received a copy of the GNU Library General Public License
0016    along with this library; see the file COPYING.LIB.  If not, write to
0017    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0018    Boston, MA 02110-1301, USA.
0019 */
0020 
0021 #include "wtf/Platform.h"
0022 
0023 #if ENABLE(SVG_FONTS)
0024 #include "SVGGlyphElement.h"
0025 
0026 #include "SVGFontElement.h"
0027 //FIXME khtml #include "SVGFontFaceElement.h"
0028 #include "SVGFontData.h"
0029 #include "SVGNames.h"
0030 #include "SVGParserUtilities.h"
0031 //FIXME khtml #include "SimpleFontData.h"
0032 
0033 namespace WebCore
0034 {
0035 
0036 using namespace SVGNames;
0037 
0038 SVGGlyphElement::SVGGlyphElement(const QualifiedName &tagName, Document *doc)
0039     : SVGStyledElement(tagName, doc)
0040 {
0041 }
0042 
0043 SVGGlyphElement::~SVGGlyphElement()
0044 {
0045 }
0046 
0047 void SVGGlyphElement::insertedIntoDocument()
0048 {
0049     Node *fontNode = parentNode();
0050     if (fontNode && fontNode->hasTagName(fontTag)) {
0051         if (SVGFontElement *element = static_cast<SVGFontElement *>(fontNode)) {
0052             element->invalidateGlyphCache();
0053         }
0054     }
0055     SVGStyledElement::insertedIntoDocument();
0056 }
0057 
0058 void SVGGlyphElement::removedFromDocument()
0059 {
0060     Node *fontNode = parentNode();
0061     if (fontNode && fontNode->hasTagName(fontTag)) {
0062         if (SVGFontElement *element = static_cast<SVGFontElement *>(fontNode)) {
0063             element->invalidateGlyphCache();
0064         }
0065     }
0066     SVGStyledElement::removedFromDocument();
0067 }
0068 
0069 static inline SVGGlyphIdentifier::ArabicForm parseArabicForm(const AtomicString &value)
0070 {
0071     if (value == "medial") {
0072         return SVGGlyphIdentifier::Medial;
0073     } else if (value == "terminal") {
0074         return SVGGlyphIdentifier::Terminal;
0075     } else if (value == "isolated") {
0076         return SVGGlyphIdentifier::Isolated;
0077     } else if (value == "initial") {
0078         return SVGGlyphIdentifier::Initial;
0079     }
0080 
0081     return SVGGlyphIdentifier::None;
0082 }
0083 
0084 static inline SVGGlyphIdentifier::Orientation parseOrientation(const AtomicString &value)
0085 {
0086     if (value == "h") {
0087         return SVGGlyphIdentifier::Horizontal;
0088     } else if (value == "v") {
0089         return SVGGlyphIdentifier::Vertical;
0090     }
0091 
0092     return SVGGlyphIdentifier::Both;
0093 }
0094 
0095 static inline Path parsePathData(const AtomicString &value)
0096 {
0097     Path result;
0098     pathFromSVGData(result, value);
0099 
0100     return result;
0101 }
0102 
0103 void SVGGlyphElement::inheritUnspecifiedAttributes(SVGGlyphIdentifier &identifier, const SVGFontData *svgFontData)
0104 {
0105     if (identifier.horizontalAdvanceX == SVGGlyphIdentifier::inheritedValue()) {
0106         identifier.horizontalAdvanceX = svgFontData->horizontalAdvanceX();
0107     }
0108 
0109     if (identifier.verticalOriginX == SVGGlyphIdentifier::inheritedValue()) {
0110         identifier.verticalOriginX = svgFontData->verticalOriginX();
0111     }
0112 
0113     if (identifier.verticalOriginY == SVGGlyphIdentifier::inheritedValue()) {
0114         identifier.verticalOriginY = svgFontData->verticalOriginY();
0115     }
0116 
0117     if (identifier.verticalAdvanceY == SVGGlyphIdentifier::inheritedValue()) {
0118         identifier.verticalAdvanceY = svgFontData->verticalAdvanceY();
0119     }
0120 }
0121 
0122 static inline float parseSVGGlyphAttribute(const SVGElement *element, const WebCore::QualifiedName &name)
0123 {
0124     AtomicString value(element->getAttribute(name));
0125     if (value.isEmpty()) {
0126         return SVGGlyphIdentifier::inheritedValue();
0127     }
0128 
0129     return value.string().string().toFloat();
0130 }
0131 
0132 SVGGlyphIdentifier SVGGlyphElement::buildGenericGlyphIdentifier(const SVGElement *element)
0133 {
0134     SVGGlyphIdentifier identifier;
0135     identifier.pathData = parsePathData(element->getAttribute(dAttr));
0136 
0137     // Spec: The horizontal advance after rendering the glyph in horizontal orientation.
0138     // If the attribute is not specified, the effect is as if the attribute were set to the
0139     // value of the font's horiz-adv-x attribute. Glyph widths are required to be non-negative,
0140     // even if the glyph is typically rendered right-to-left, as in Hebrew and Arabic scripts.
0141     identifier.horizontalAdvanceX = parseSVGGlyphAttribute(element, horiz_adv_xAttr);
0142 
0143     // Spec: The X-coordinate in the font coordinate system of the origin of the glyph to be
0144     // used when drawing vertically oriented text. If the attribute is not specified, the effect
0145     // is as if the attribute were set to the value of the font's vert-origin-x attribute.
0146     identifier.verticalOriginX = parseSVGGlyphAttribute(element, vert_origin_xAttr);
0147 
0148     // Spec: The Y-coordinate in the font coordinate system of the origin of a glyph to be
0149     // used when drawing vertically oriented text. If the attribute is not specified, the effect
0150     // is as if the attribute were set to the value of the font's vert-origin-y attribute.
0151     identifier.verticalOriginY = parseSVGGlyphAttribute(element, vert_origin_yAttr);
0152 
0153     // Spec: The vertical advance after rendering a glyph in vertical orientation.
0154     // If the attribute is not specified, the effect is as if the attribute were set to the
0155     // value of the font's vert-adv-y attribute.
0156     identifier.verticalAdvanceY = parseSVGGlyphAttribute(element, vert_adv_yAttr);
0157 
0158     return identifier;
0159 }
0160 
0161 SVGGlyphIdentifier SVGGlyphElement::buildGlyphIdentifier() const
0162 {
0163     SVGGlyphIdentifier identifier(buildGenericGlyphIdentifier(this));
0164     identifier.glyphName = getAttribute(glyph_nameAttr);
0165     identifier.orientation = parseOrientation(getAttribute(orientationAttr));
0166     identifier.arabicForm = parseArabicForm(getAttribute(arabic_formAttr));
0167 
0168     String language = getAttribute(langAttr);
0169     if (!language.isEmpty()) {
0170         identifier.languages = parseDelimitedString(language, ',');
0171     }
0172 
0173     return identifier;
0174 }
0175 
0176 }
0177 
0178 #endif // ENABLE(SVG_FONTS)