• Skip to content
  • Skip to link menu
KDE 4.6 API Reference
  • KDE API Reference
  • kdelibs
  • KDE Home
  • 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     Q_UNUSED(characters);
00095     Q_UNUSED(length);
00096     Q_UNUSED(range);
00097     // FIXME khtml
00098     return 0;
00099     /*if (length < 2)
00100         return 0;
00101     if (characters[0] != 'U')
00102         return 0;
00103     if (characters[1] != '+')
00104         return 0;
00105     
00106     // Parse the starting hex number (or its prefix).
00107     unsigned start = 0;
00108     unsigned startLength = 0;
00109     for (unsigned i = 2; i < length; ++i) {
00110         if (!isASCIIHexDigit(characters[i]))
00111             break;
00112         if (++startLength > 6)
00113             return 0;
00114         start = (start << 4) | toASCIIHexValue(characters[i]);
00115     }
00116     
00117     // Handle the case of ranges separated by "-" sign.
00118     if (2 + startLength < length && characters[2 + startLength] == '-') {
00119         if (!startLength)
00120             return 0;
00121         
00122         // Parse the ending hex number (or its prefix).
00123         unsigned end = 0;
00124         unsigned endLength = 0;
00125         for (unsigned i = 2 + startLength + 1; i < length; ++i) {
00126             if (!isASCIIHexDigit(characters[i]))
00127                 break;
00128             if (++endLength > 6)
00129                 return 0;
00130             end = (end << 4) | toASCIIHexValue(characters[i]);
00131         }
00132         
00133         if (!endLength)
00134             return 0;
00135         
00136         range.first = start;
00137         range.second = end;
00138         return 2 + startLength + 1 + endLength;
00139     }
00140     
00141     // Handle the case of a number with some optional trailing question marks.
00142     unsigned end = start;
00143     for (unsigned i = 2 + startLength; i < length; ++i) {
00144         if (characters[i] != '?')
00145             break;
00146         if (++startLength > 6)
00147             return 0;
00148         start <<= 4;
00149         end = (end << 4) | 0xF;
00150     }
00151     
00152     if (!startLength)
00153         return 0;
00154     
00155     range.first = start;
00156     range.second = end;
00157     return 2 + startLength;*/
00158 }
00159     
00160 static bool parseUnicodeRangeList(const UChar* characters, unsigned length, Vector<pair<unsigned, unsigned> >& ranges)
00161 {
00162     ranges.clear();
00163     if (!length)
00164         return true;
00165     
00166     const UChar* remainingCharacters = characters;
00167     unsigned remainingLength = length;
00168     
00169     while (1) {
00170         pair<unsigned, unsigned> range;
00171         unsigned charactersConsumed = parseUnicodeRange(remainingCharacters, remainingLength, range);
00172         if (charactersConsumed) {
00173             ranges.append(range);
00174             remainingCharacters += charactersConsumed;
00175             remainingLength -= charactersConsumed;
00176         } else {
00177             if (!remainingLength)
00178                 return false;
00179             UChar character = remainingCharacters[0];
00180             if (character == ',')
00181                 return false;
00182             ranges.append(make_pair(character.unicode(), character.unicode()));
00183             ++remainingCharacters;
00184             --remainingLength;
00185         }
00186         if (!remainingLength)
00187             return true;
00188         if (remainingCharacters[0] != ',')
00189             return false;
00190         ++remainingCharacters;
00191         --remainingLength;
00192     }
00193 }
00194 
00195 static bool stringMatchesUnicodeRange(const String& unicodeString, const String& unicodeRangeSpec)
00196 {
00197     Vector<pair<unsigned, unsigned> > ranges;
00198     if (!parseUnicodeRangeList(unicodeRangeSpec.characters(), unicodeRangeSpec.length(), ranges))
00199         return false;
00200     
00201     if (unicodeString.length() != ranges.size())
00202         return false;
00203     
00204     for (size_t i = 0; i < unicodeString.length(); ++i) {
00205         UChar c = unicodeString[i];
00206         if (c < ranges[i].first || c > ranges[i].second)
00207             return false;
00208     }
00209     
00210     return true;
00211 }
00212     
00213 static bool matches(const String& u1, const String& g1, const String& u2, const String& g2, const SVGHorizontalKerningPair& kerningPair)
00214 {
00215     if (kerningPair.unicode1.length() && !stringMatchesUnicodeRange(u1, kerningPair.unicode1))
00216         return false;
00217     if (kerningPair.glyphName1.length() && kerningPair.glyphName1 != g1)
00218         return false;
00219     
00220     if (kerningPair.unicode2.length() && !stringMatchesUnicodeRange(u2, kerningPair.unicode2))
00221         return false;
00222     if (kerningPair.glyphName2.length() && kerningPair.glyphName2 != g2)
00223         return false;
00224     
00225     return true;
00226 }
00227     
00228 bool SVGFontElement::getHorizontalKerningPairForStringsAndGlyphs(const String& u1, const String& g1, const String& u2, const String& g2, SVGHorizontalKerningPair& kerningPair) const
00229 {
00230     for (size_t i = 0; i < m_kerningPairs.size(); ++i) {
00231         if (matches(u1, g1, u2, g2, m_kerningPairs[i])) {
00232             kerningPair = m_kerningPairs[i];
00233             return true;
00234         }        
00235     }
00236     
00237     return false;
00238 }
00239 
00240 void SVGFontElement::getGlyphIdentifiersForString(const String& string, Vector<SVGGlyphIdentifier>& glyphs) const
00241 {
00242     ensureGlyphCache();
00243     m_glyphMap.get(string, glyphs);
00244 }
00245 
00246 }
00247 
00248 #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
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.7.3
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