• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

KHTML

SVGFontElement.cpp

Go to the documentation of this file.
00001 /*
00002     Copyright (C) 2007 Eric Seidel <eric@webkit.org>
00003     Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org>
00004 
00005     This library is free software; you can redistribute it and/or
00006     modify it under the terms of the GNU Library General Public
00007     License as published by the Free Software Foundation; either
00008     version 2 of the License, or (at your option) any later version.
00009 
00010     This library is distributed in the hope that it will be useful,
00011     but WITHOUT ANY WARRANTY; without even the implied warranty of
00012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013     Library General Public License for more details.
00014 
00015     You should have received a copy of the GNU Library General Public License
00016     along with this library; see the file COPYING.LIB.  If not, write to
00017     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018     Boston, MA 02110-1301, USA.
00019 */
00020 
00021 #include "config.h"
00022 #include "wtf/Platform.h"
00023 
00024 #if ENABLE(SVG_FONTS)
00025 #include "SVGFontElement.h"
00026 
00027 //#include "Font.h"
00028 //FIXME khtml #include "GlyphPageTreeNode.h"
00029 #include "SVGGlyphElement.h"
00030 #include "SVGMissingGlyphElement.h"
00031 #include "SVGNames.h"
00032 #include "SVGParserUtilities.h"
00033 #include <wtf/ASCIICType.h>
00034 
00035 using namespace WTF;
00036 
00037 namespace WebCore {
00038 
00039 using namespace SVGNames;
00040 
00041 SVGFontElement::SVGFontElement(const QualifiedName& tagName, Document* doc)
00042     : SVGStyledElement(tagName, doc)
00043     , m_isGlyphCacheValid(false)
00044 {
00045 }
00046 
00047 SVGFontElement::~SVGFontElement()
00048 {
00049 }
00050 
00051 void SVGFontElement::invalidateGlyphCache()
00052 {
00053     if (m_isGlyphCacheValid) {
00054         m_glyphMap.clear();
00055         m_kerningPairs.clear();
00056     }
00057     m_isGlyphCacheValid = false;
00058 }
00059 
00060 SVGMissingGlyphElement* SVGFontElement::firstMissingGlyphElement() const
00061 {
00062     for (Node* child = firstChild(); child; child = child->nextSibling()) {
00063         if (child->hasTagName(missing_glyphTag))
00064             return static_cast<SVGMissingGlyphElement*>(child);
00065     }
00066 
00067     return 0;
00068 }
00069 
00070 void SVGFontElement::ensureGlyphCache() const
00071 {
00072     if (m_isGlyphCacheValid)
00073         return;
00074 
00075     for (Node* child = firstChild(); child; child = child->nextSibling()) {
00076         if (child->hasTagName(glyphTag)) {
00077             SVGGlyphElement* glyph = static_cast<SVGGlyphElement*>(child);
00078             String unicode = glyph->getAttribute(unicodeAttr);
00079             if (unicode.length())
00080                 m_glyphMap.add(unicode, glyph->buildGlyphIdentifier());
00081         } else if (child->hasTagName(hkernTag)) {
00082             SVGHKernElement* hkern = static_cast<SVGHKernElement*>(child);
00083             SVGHorizontalKerningPair kerningPair = hkern->buildHorizontalKerningPair();
00084             m_kerningPairs.append(kerningPair);
00085         }
00086     }
00087         
00088     m_isGlyphCacheValid = true;
00089 }
00090     
00091 // Returns the number of characters consumed or 0 if no range was found.
00092 static unsigned parseUnicodeRange(const UChar* characters, unsigned length, pair<unsigned, unsigned>& range)
00093 {
00094     // FIXME khtml
00095     return 0;
00096     /*if (length < 2)
00097         return 0;
00098     if (characters[0] != 'U')
00099         return 0;
00100     if (characters[1] != '+')
00101         return 0;
00102     
00103     // Parse the starting hex number (or its prefix).
00104     unsigned start = 0;
00105     unsigned startLength = 0;
00106     for (unsigned i = 2; i < length; ++i) {
00107         if (!isASCIIHexDigit(characters[i]))
00108             break;
00109         if (++startLength > 6)
00110             return 0;
00111         start = (start << 4) | toASCIIHexValue(characters[i]);
00112     }
00113     
00114     // Handle the case of ranges separated by "-" sign.
00115     if (2 + startLength < length && characters[2 + startLength] == '-') {
00116         if (!startLength)
00117             return 0;
00118         
00119         // Parse the ending hex number (or its prefix).
00120         unsigned end = 0;
00121         unsigned endLength = 0;
00122         for (unsigned i = 2 + startLength + 1; i < length; ++i) {
00123             if (!isASCIIHexDigit(characters[i]))
00124                 break;
00125             if (++endLength > 6)
00126                 return 0;
00127             end = (end << 4) | toASCIIHexValue(characters[i]);
00128         }
00129         
00130         if (!endLength)
00131             return 0;
00132         
00133         range.first = start;
00134         range.second = end;
00135         return 2 + startLength + 1 + endLength;
00136     }
00137     
00138     // Handle the case of a number with some optional trailing question marks.
00139     unsigned end = start;
00140     for (unsigned i = 2 + startLength; i < length; ++i) {
00141         if (characters[i] != '?')
00142             break;
00143         if (++startLength > 6)
00144             return 0;
00145         start <<= 4;
00146         end = (end << 4) | 0xF;
00147     }
00148     
00149     if (!startLength)
00150         return 0;
00151     
00152     range.first = start;
00153     range.second = end;
00154     return 2 + startLength;*/
00155 }
00156     
00157 static bool parseUnicodeRangeList(const UChar* characters, unsigned length, Vector<pair<unsigned, unsigned> >& ranges)
00158 {
00159     ranges.clear();
00160     if (!length)
00161         return true;
00162     
00163     const UChar* remainingCharacters = characters;
00164     unsigned remainingLength = length;
00165     
00166     while (1) {
00167         pair<unsigned, unsigned> range;
00168         unsigned charactersConsumed = parseUnicodeRange(remainingCharacters, remainingLength, range);
00169         if (charactersConsumed) {
00170             ranges.append(range);
00171             remainingCharacters += charactersConsumed;
00172             remainingLength -= charactersConsumed;
00173         } else {
00174             if (!remainingLength)
00175                 return false;
00176             UChar character = remainingCharacters[0];
00177             if (character == ',')
00178                 return false;
00179             ranges.append(make_pair(character.unicode(), character.unicode()));
00180             ++remainingCharacters;
00181             --remainingLength;
00182         }
00183         if (!remainingLength)
00184             return true;
00185         if (remainingCharacters[0] != ',')
00186             return false;
00187         ++remainingCharacters;
00188         --remainingLength;
00189     }
00190 }
00191 
00192 static bool stringMatchesUnicodeRange(const String& unicodeString, const String& unicodeRangeSpec)
00193 {
00194     Vector<pair<unsigned, unsigned> > ranges;
00195     if (!parseUnicodeRangeList(unicodeRangeSpec.characters(), unicodeRangeSpec.length(), ranges))
00196         return false;
00197     
00198     if (unicodeString.length() != ranges.size())
00199         return false;
00200     
00201     for (size_t i = 0; i < unicodeString.length(); ++i) {
00202         UChar c = unicodeString[i];
00203         if (c < ranges[i].first || c > ranges[i].second)
00204             return false;
00205     }
00206     
00207     return true;
00208 }
00209     
00210 static bool matches(const String& u1, const String& g1, const String& u2, const String& g2, const SVGHorizontalKerningPair& kerningPair)
00211 {
00212     if (kerningPair.unicode1.length() && !stringMatchesUnicodeRange(u1, kerningPair.unicode1))
00213         return false;
00214     if (kerningPair.glyphName1.length() && kerningPair.glyphName1 != g1)
00215         return false;
00216     
00217     if (kerningPair.unicode2.length() && !stringMatchesUnicodeRange(u2, kerningPair.unicode2))
00218         return false;
00219     if (kerningPair.glyphName2.length() && kerningPair.glyphName2 != g2)
00220         return false;
00221     
00222     return true;
00223 }
00224     
00225 bool SVGFontElement::getHorizontalKerningPairForStringsAndGlyphs(const String& u1, const String& g1, const String& u2, const String& g2, SVGHorizontalKerningPair& kerningPair) const
00226 {
00227     for (size_t i = 0; i < m_kerningPairs.size(); ++i) {
00228         if (matches(u1, g1, u2, g2, m_kerningPairs[i])) {
00229             kerningPair = m_kerningPairs[i];
00230             return true;
00231         }        
00232     }
00233     
00234     return false;
00235 }
00236 
00237 void SVGFontElement::getGlyphIdentifiersForString(const String& string, Vector<SVGGlyphIdentifier>& glyphs) const
00238 {
00239     ensureGlyphCache();
00240     m_glyphMap.get(string, glyphs);
00241 }
00242 
00243 }
00244 
00245 #endif // ENABLE(SVG_FONTS)

KHTML

Skip menu "KHTML"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.7
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal