diff options
Diffstat (limited to 'Source/WebCore/svg/SVGFontElement.cpp')
-rw-r--r-- | Source/WebCore/svg/SVGFontElement.cpp | 184 |
1 files changed, 184 insertions, 0 deletions
diff --git a/Source/WebCore/svg/SVGFontElement.cpp b/Source/WebCore/svg/SVGFontElement.cpp new file mode 100644 index 0000000..d70d46a --- /dev/null +++ b/Source/WebCore/svg/SVGFontElement.cpp @@ -0,0 +1,184 @@ +/* + * Copyright (C) 2007 Eric Seidel <eric@webkit.org> + * Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) Research In Motion Limited 2010. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" + +#if ENABLE(SVG_FONTS) +#include "SVGFontElement.h" + +#include "Document.h" +#include "Font.h" +#include "GlyphPageTreeNode.h" +#include "SVGGlyphElement.h" +#include "SVGHKernElement.h" +#include "SVGMissingGlyphElement.h" +#include "SVGNames.h" +#include "SVGVKernElement.h" +#include <wtf/ASCIICType.h> + +namespace WebCore { + +// Animated property declarations +DEFINE_ANIMATED_BOOLEAN(SVGFontElement, SVGNames::externalResourcesRequiredAttr, ExternalResourcesRequired, externalResourcesRequired) + +inline SVGFontElement::SVGFontElement(const QualifiedName& tagName, Document* document) + : SVGStyledElement(tagName, document) + , m_isGlyphCacheValid(false) +{ +} + +PassRefPtr<SVGFontElement> SVGFontElement::create(const QualifiedName& tagName, Document* document) +{ + return adoptRef(new SVGFontElement(tagName, document)); +} + +void SVGFontElement::synchronizeProperty(const QualifiedName& attrName) +{ + SVGStyledElement::synchronizeProperty(attrName); + + if (attrName == anyQName() || SVGExternalResourcesRequired::isKnownAttribute(attrName)) + synchronizeExternalResourcesRequired(); +} + +void SVGFontElement::invalidateGlyphCache() +{ + if (m_isGlyphCacheValid) { + m_glyphMap.clear(); + m_horizontalKerningPairs.clear(); + m_verticalKerningPairs.clear(); + } + m_isGlyphCacheValid = false; +} + +SVGMissingGlyphElement* SVGFontElement::firstMissingGlyphElement() const +{ + for (Node* child = firstChild(); child; child = child->nextSibling()) { + if (child->hasTagName(SVGNames::missing_glyphTag)) + return static_cast<SVGMissingGlyphElement*>(child); + } + + return 0; +} + +void SVGFontElement::ensureGlyphCache() const +{ + if (m_isGlyphCacheValid) + return; + + for (Node* child = firstChild(); child; child = child->nextSibling()) { + if (child->hasTagName(SVGNames::glyphTag)) { + SVGGlyphElement* glyph = static_cast<SVGGlyphElement*>(child); + String unicode = glyph->getAttribute(SVGNames::unicodeAttr); + if (unicode.length()) + m_glyphMap.add(unicode, glyph->buildGlyphIdentifier()); + } else if (child->hasTagName(SVGNames::hkernTag)) { + SVGHKernElement* hkern = static_cast<SVGHKernElement*>(child); + hkern->buildHorizontalKerningPair(m_horizontalKerningPairs); + } else if (child->hasTagName(SVGNames::vkernTag)) { + SVGVKernElement* vkern = static_cast<SVGVKernElement*>(child); + vkern->buildVerticalKerningPair(m_verticalKerningPairs); + } + } + + m_isGlyphCacheValid = true; +} + +static bool stringMatchesUnicodeRange(const String& unicodeString, const UnicodeRanges& ranges, const HashSet<String>& unicodeValues) +{ + if (unicodeString.isEmpty()) + return false; + + if (!ranges.isEmpty()) { + UChar firstChar = unicodeString[0]; + const UnicodeRanges::const_iterator end = ranges.end(); + for (UnicodeRanges::const_iterator it = ranges.begin(); it != end; ++it) { + if (firstChar >= it->first && firstChar <= it->second) + return true; + } + } + + if (!unicodeValues.isEmpty()) + return unicodeValues.contains(unicodeString); + + return false; +} + +static bool stringMatchesGlyphName(const String& glyphName, const HashSet<String>& glyphValues) +{ + if (glyphName.isEmpty()) + return false; + + if (!glyphValues.isEmpty()) + return glyphValues.contains(glyphName); + + return false; +} + +static bool matches(const String& u1, const String& g1, const String& u2, const String& g2, const SVGKerningPair& kerningPair) +{ + if (!stringMatchesUnicodeRange(u1, kerningPair.unicodeRange1, kerningPair.unicodeName1) + && !stringMatchesGlyphName(g1, kerningPair.glyphName1)) + return false; + + if (!stringMatchesUnicodeRange(u2, kerningPair.unicodeRange2, kerningPair.unicodeName2) + && !stringMatchesGlyphName(g2, kerningPair.glyphName2)) + return false; + + return true; +} + +static float kerningForPairOfStringsAndGlyphs(KerningPairVector& kerningPairs, const String& u1, const String& g1, const String& u2, const String& g2) +{ + KerningPairVector::const_iterator it = kerningPairs.end() - 1; + const KerningPairVector::const_iterator begin = kerningPairs.begin() - 1; + for (; it != begin; --it) { + if (matches(u1, g1, u2, g2, *it)) + return it->kerning; + } + + return 0.0f; +} + +float SVGFontElement::horizontalKerningForPairOfStringsAndGlyphs(const String& u1, const String& g1, const String& u2, const String& g2) const +{ + if (m_horizontalKerningPairs.isEmpty()) + return 0.0f; + + return kerningForPairOfStringsAndGlyphs(m_horizontalKerningPairs, u1, g1, u2, g2); +} + +float SVGFontElement::verticalKerningForPairOfStringsAndGlyphs(const String& u1, const String& g1, const String& u2, const String& g2) const +{ + if (m_verticalKerningPairs.isEmpty()) + return 0.0f; + + return kerningForPairOfStringsAndGlyphs(m_verticalKerningPairs, u1, g1, u2, g2); +} + +void SVGFontElement::getGlyphIdentifiersForString(const String& string, Vector<SVGGlyphIdentifier>& glyphs) const +{ + ensureGlyphCache(); + m_glyphMap.get(string, glyphs); +} + +} + +#endif // ENABLE(SVG_FONTS) |