Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(287)

Side by Side Diff: Source/core/svg/SVGFontElement.cpp

Issue 181443002: Use glyph-ids for lookups of SVG font kerning-pairs (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Vector<...>::append -> Vector<...>::appendVector. Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « Source/core/svg/SVGFontElement.h ('k') | Source/core/svg/SVGGlyphMap.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2007 Eric Seidel <eric@webkit.org> 2 * Copyright (C) 2007 Eric Seidel <eric@webkit.org>
3 * Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org> 3 * Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org>
4 * Copyright (C) Research In Motion Limited 2010. All rights reserved. 4 * Copyright (C) Research In Motion Limited 2010. All rights reserved.
5 * 5 *
6 * This library is free software; you can redistribute it and/or 6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public 7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either 8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version. 9 * version 2 of the License, or (at your option) any later version.
10 * 10 *
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
52 52
53 PassRefPtr<SVGFontElement> SVGFontElement::create(Document& document) 53 PassRefPtr<SVGFontElement> SVGFontElement::create(Document& document)
54 { 54 {
55 return adoptRef(new SVGFontElement(document)); 55 return adoptRef(new SVGFontElement(document));
56 } 56 }
57 57
58 void SVGFontElement::invalidateGlyphCache() 58 void SVGFontElement::invalidateGlyphCache()
59 { 59 {
60 if (m_isGlyphCacheValid) { 60 if (m_isGlyphCacheValid) {
61 m_glyphMap.clear(); 61 m_glyphMap.clear();
62 m_horizontalKerningPairs.clear(); 62 m_horizontalKerningTable.clear();
63 m_verticalKerningPairs.clear(); 63 m_verticalKerningTable.clear();
64 } 64 }
65 m_isGlyphCacheValid = false; 65 m_isGlyphCacheValid = false;
66 } 66 }
67 67
68 SVGMissingGlyphElement* SVGFontElement::firstMissingGlyphElement() const 68 SVGMissingGlyphElement* SVGFontElement::firstMissingGlyphElement() const
69 { 69 {
70 for (Node* child = firstChild(); child; child = child->nextSibling()) { 70 for (Node* child = firstChild(); child; child = child->nextSibling()) {
71 if (child->hasTagName(SVGNames::missing_glyphTag)) 71 if (child->hasTagName(SVGNames::missing_glyphTag))
72 return toSVGMissingGlyphElement(child); 72 return toSVGMissingGlyphElement(child);
73 } 73 }
(...skipping 30 matching lines...) Expand all
104 } 104 }
105 105
106 // This glyph is never meant to be used for rendering, only as ident ifier as a part of a ligature. 106 // This glyph is never meant to be used for rendering, only as ident ifier as a part of a ligature.
107 SVGGlyph newGlyphPart; 107 SVGGlyph newGlyphPart;
108 newGlyphPart.isPartOfLigature = true; 108 newGlyphPart.isPartOfLigature = true;
109 m_glyphMap.addGlyph(String(), lookupString, newGlyphPart); 109 m_glyphMap.addGlyph(String(), lookupString, newGlyphPart);
110 } 110 }
111 } 111 }
112 } 112 }
113 113
114 static inline KerningPairKey makeKerningPairKey(Glyph glyphId1, Glyph glyphId2)
115 {
116 return glyphId1 << 16 | glyphId2;
117 }
118
119 Vector<SVGGlyph> SVGFontElement::buildGlyphList(const UnicodeRanges& unicodeRang es, const HashSet<String>& unicodeNames, const HashSet<String>& glyphNames) cons t
120 {
121 Vector<SVGGlyph> glyphs;
122 if (!unicodeRanges.isEmpty()) {
123 const UnicodeRanges::const_iterator end = unicodeRanges.end();
124 for (UnicodeRanges::const_iterator it = unicodeRanges.begin(); it != end ; ++it)
125 m_glyphMap.collectGlyphsForUnicodeRange(*it, glyphs);
126 }
127 if (!unicodeNames.isEmpty()) {
128 const HashSet<String>::const_iterator end = unicodeNames.end();
129 for (HashSet<String>::const_iterator it = unicodeNames.begin(); it != en d; ++it)
130 m_glyphMap.collectGlyphsForStringExact(*it, glyphs);
131 }
132 if (!glyphNames.isEmpty()) {
133 const HashSet<String>::const_iterator end = glyphNames.end();
134 for (HashSet<String>::const_iterator it = glyphNames.begin(); it != end; ++it) {
135 const SVGGlyph& glyph = m_glyphMap.glyphIdentifierForGlyphName(*it);
136 if (glyph.tableEntry)
137 glyphs.append(glyph);
138 }
139 }
140 return glyphs;
141 }
142
143 void SVGFontElement::addPairsToKerningTable(const SVGKerningPair& kerningPair, K erningTable& kerningTable)
144 {
145 Vector<SVGGlyph> glyphsLhs = buildGlyphList(kerningPair.unicodeRange1, kerni ngPair.unicodeName1, kerningPair.glyphName1);
146 Vector<SVGGlyph> glyphsRhs = buildGlyphList(kerningPair.unicodeRange2, kerni ngPair.unicodeName2, kerningPair.glyphName2);
147 if (glyphsLhs.isEmpty() || glyphsRhs.isEmpty())
148 return;
149 size_t glyphsLhsSize = glyphsLhs.size();
150 size_t glyphsRhsSize = glyphsRhs.size();
151 // Enumerate all the valid kerning pairs, and add them to the table.
152 for (size_t lhsIndex = 0; lhsIndex < glyphsLhsSize; ++lhsIndex) {
153 for (size_t rhsIndex = 0; rhsIndex < glyphsRhsSize; ++rhsIndex) {
154 Glyph glyph1 = glyphsLhs[lhsIndex].tableEntry;
155 Glyph glyph2 = glyphsRhs[rhsIndex].tableEntry;
156 ASSERT(glyph1 && glyph2);
157 kerningTable.add(makeKerningPairKey(glyph1, glyph2), kerningPair.ker ning);
158 }
159 }
160 }
161
162 void SVGFontElement::buildKerningTable(const KerningPairVector& kerningPairs, Ke rningTable& kerningTable)
163 {
164 size_t kerningPairsSize = kerningPairs.size();
165 for (size_t i = 0; i < kerningPairsSize; ++i)
166 addPairsToKerningTable(kerningPairs[i], kerningTable);
167 }
168
114 void SVGFontElement::ensureGlyphCache() 169 void SVGFontElement::ensureGlyphCache()
115 { 170 {
116 if (m_isGlyphCacheValid) 171 if (m_isGlyphCacheValid)
117 return; 172 return;
118 173
174 KerningPairVector horizontalKerningPairs;
175 KerningPairVector verticalKerningPairs;
176
119 SVGMissingGlyphElement* firstMissingGlyphElement = 0; 177 SVGMissingGlyphElement* firstMissingGlyphElement = 0;
120 Vector<String> ligatures; 178 Vector<String> ligatures;
121 for (Node* child = firstChild(); child; child = child->nextSibling()) { 179 for (Node* child = firstChild(); child; child = child->nextSibling()) {
122 if (child->hasTagName(SVGNames::glyphTag)) { 180 if (child->hasTagName(SVGNames::glyphTag)) {
123 SVGGlyphElement* glyph = toSVGGlyphElement(child); 181 SVGGlyphElement* glyph = toSVGGlyphElement(child);
124 AtomicString unicode = glyph->fastGetAttribute(SVGNames::unicodeAttr ); 182 AtomicString unicode = glyph->fastGetAttribute(SVGNames::unicodeAttr );
125 AtomicString glyphId = glyph->getIdAttribute(); 183 AtomicString glyphId = glyph->getIdAttribute();
126 if (glyphId.isEmpty() && unicode.isEmpty()) 184 if (glyphId.isEmpty() && unicode.isEmpty())
127 continue; 185 continue;
128 186
129 m_glyphMap.addGlyph(glyphId, unicode, glyph->buildGlyphIdentifier()) ; 187 m_glyphMap.addGlyph(glyphId, unicode, glyph->buildGlyphIdentifier()) ;
130 188
131 // Register ligatures, if needed, don't mix up with surrogate pairs though! 189 // Register ligatures, if needed, don't mix up with surrogate pairs though!
132 if (unicode.length() > 1 && !U16_IS_SURROGATE(unicode[0])) 190 if (unicode.length() > 1 && !U16_IS_SURROGATE(unicode[0]))
133 ligatures.append(unicode.string()); 191 ligatures.append(unicode.string());
134 } else if (child->hasTagName(SVGNames::hkernTag)) { 192 } else if (child->hasTagName(SVGNames::hkernTag)) {
135 toSVGHKernElement(child)->buildHorizontalKerningPair(m_horizontalKer ningPairs); 193 toSVGHKernElement(child)->buildHorizontalKerningPair(horizontalKerni ngPairs);
136 } else if (child->hasTagName(SVGNames::vkernTag)) { 194 } else if (child->hasTagName(SVGNames::vkernTag)) {
137 toSVGVKernElement(child)->buildVerticalKerningPair(m_verticalKerning Pairs); 195 toSVGVKernElement(child)->buildVerticalKerningPair(verticalKerningPa irs);
138 } else if (child->hasTagName(SVGNames::missing_glyphTag) && !firstMissin gGlyphElement) { 196 } else if (child->hasTagName(SVGNames::missing_glyphTag) && !firstMissin gGlyphElement) {
139 firstMissingGlyphElement = toSVGMissingGlyphElement(child); 197 firstMissingGlyphElement = toSVGMissingGlyphElement(child);
140 } 198 }
141 } 199 }
142 200
201 // Build the kerning tables.
202 buildKerningTable(horizontalKerningPairs, m_horizontalKerningTable);
203 buildKerningTable(verticalKerningPairs, m_verticalKerningTable);
204
205 // The glyph-name->glyph-id map won't be needed/used after having built the kerning table(s).
206 m_glyphMap.dropNamedGlyphMap();
207
143 // Register each character of each ligature, if needed. 208 // Register each character of each ligature, if needed.
144 if (!ligatures.isEmpty()) 209 if (!ligatures.isEmpty())
145 registerLigaturesInGlyphCache(ligatures); 210 registerLigaturesInGlyphCache(ligatures);
146 211
147 // Register missing-glyph element, if present. 212 // Register missing-glyph element, if present.
148 if (firstMissingGlyphElement) { 213 if (firstMissingGlyphElement) {
149 SVGGlyph svgGlyph = SVGGlyphElement::buildGenericGlyphIdentifier(firstMi ssingGlyphElement); 214 SVGGlyph svgGlyph = SVGGlyphElement::buildGenericGlyphIdentifier(firstMi ssingGlyphElement);
150 m_glyphMap.appendToGlyphTable(svgGlyph); 215 m_glyphMap.appendToGlyphTable(svgGlyph);
151 m_missingGlyph = svgGlyph.tableEntry; 216 m_missingGlyph = svgGlyph.tableEntry;
152 ASSERT(m_missingGlyph > 0); 217 ASSERT(m_missingGlyph > 0);
153 } 218 }
154 219
155 m_isGlyphCacheValid = true; 220 m_isGlyphCacheValid = true;
156 } 221 }
157 222
158 static bool stringMatchesUnicodeRange(const String& unicodeString, const Unicode Ranges& ranges, const HashSet<String>& unicodeValues) 223 static float kerningForPairOfGlyphs(const KerningTable& kerningTable, Glyph glyp hId1, Glyph glyphId2)
159 { 224 {
160 if (unicodeString.isEmpty()) 225 KerningTable::const_iterator result = kerningTable.find(makeKerningPairKey(g lyphId1, glyphId2));
161 return false; 226 if (result != kerningTable.end())
162 227 return result->value;
163 if (!ranges.isEmpty()) {
164 UChar firstChar = unicodeString[0];
165 const UnicodeRanges::const_iterator end = ranges.end();
166 for (UnicodeRanges::const_iterator it = ranges.begin(); it != end; ++it) {
167 if (firstChar >= it->first && firstChar <= it->second)
168 return true;
169 }
170 }
171
172 if (!unicodeValues.isEmpty())
173 return unicodeValues.contains(unicodeString);
174
175 return false;
176 }
177
178 static bool stringMatchesGlyphName(const String& glyphName, const HashSet<String >& glyphValues)
179 {
180 if (glyphName.isEmpty())
181 return false;
182
183 if (!glyphValues.isEmpty())
184 return glyphValues.contains(glyphName);
185
186 return false;
187 }
188
189 static bool matches(const String& u1, const String& g1, const String& u2, const String& g2, const SVGKerningPair& kerningPair)
190 {
191 if (!stringMatchesUnicodeRange(u1, kerningPair.unicodeRange1, kerningPair.un icodeName1)
192 && !stringMatchesGlyphName(g1, kerningPair.glyphName1))
193 return false;
194
195 if (!stringMatchesUnicodeRange(u2, kerningPair.unicodeRange2, kerningPair.un icodeName2)
196 && !stringMatchesGlyphName(g2, kerningPair.glyphName2))
197 return false;
198
199 return true;
200 }
201
202 static float kerningForPairOfStringsAndGlyphs(const KerningPairVector& kerningPa irs, const String& u1, const String& g1, const String& u2, const String& g2)
203 {
204 KerningPairVector::const_iterator it = kerningPairs.end() - 1;
205 const KerningPairVector::const_iterator begin = kerningPairs.begin() - 1;
206 for (; it != begin; --it) {
207 if (matches(u1, g1, u2, g2, *it))
208 return it->kerning;
209 }
210 228
211 return 0; 229 return 0;
212 } 230 }
213 231
214 float SVGFontElement::horizontalKerningForPairOfStringsAndGlyphs(const String& u 1, const String& g1, const String& u2, const String& g2) const 232 float SVGFontElement::horizontalKerningForPairOfGlyphs(Glyph glyphId1, Glyph gly phId2) const
215 { 233 {
216 if (m_horizontalKerningPairs.isEmpty()) 234 if (m_horizontalKerningTable.isEmpty())
217 return 0; 235 return 0;
218 236
219 return kerningForPairOfStringsAndGlyphs(m_horizontalKerningPairs, u1, g1, u2 , g2); 237 return kerningForPairOfGlyphs(m_horizontalKerningTable, glyphId1, glyphId2);
220 } 238 }
221 239
222 float SVGFontElement::verticalKerningForPairOfStringsAndGlyphs(const String& u1, const String& g1, const String& u2, const String& g2) const 240 float SVGFontElement::verticalKerningForPairOfGlyphs(Glyph glyphId1, Glyph glyph Id2) const
223 { 241 {
224 if (m_verticalKerningPairs.isEmpty()) 242 if (m_verticalKerningTable.isEmpty())
225 return 0; 243 return 0;
226 244
227 return kerningForPairOfStringsAndGlyphs(m_verticalKerningPairs, u1, g1, u2, g2); 245 return kerningForPairOfGlyphs(m_verticalKerningTable, glyphId1, glyphId2);
228 } 246 }
229 247
230 void SVGFontElement::collectGlyphsForString(const String& string, Vector<SVGGlyp h>& glyphs) 248 void SVGFontElement::collectGlyphsForString(const String& string, Vector<SVGGlyp h>& glyphs)
231 { 249 {
232 ensureGlyphCache(); 250 ensureGlyphCache();
233 m_glyphMap.collectGlyphsForString(string, glyphs); 251 m_glyphMap.collectGlyphsForString(string, glyphs);
234 } 252 }
235 253
236 void SVGFontElement::collectGlyphsForGlyphName(const String& glyphName, Vector<S VGGlyph>& glyphs) 254 void SVGFontElement::collectGlyphsForAltGlyphReference(const String& glyphIdenti fier, Vector<SVGGlyph>& glyphs)
237 { 255 {
238 ensureGlyphCache(); 256 ensureGlyphCache();
239 // FIXME: We only support glyphName -> single glyph mapping so far. 257 // FIXME: We only support glyphName -> single glyph mapping so far.
240 glyphs.append(m_glyphMap.glyphIdentifierForGlyphName(glyphName)); 258 glyphs.append(m_glyphMap.glyphIdentifierForAltGlyphReference(glyphIdentifier ));
241 } 259 }
242 260
243 SVGGlyph SVGFontElement::svgGlyphForGlyph(Glyph glyph) 261 SVGGlyph SVGFontElement::svgGlyphForGlyph(Glyph glyph)
244 { 262 {
245 ensureGlyphCache(); 263 ensureGlyphCache();
246 return m_glyphMap.svgGlyphForGlyph(glyph); 264 return m_glyphMap.svgGlyphForGlyph(glyph);
247 } 265 }
248 266
249 Glyph SVGFontElement::missingGlyph() 267 Glyph SVGFontElement::missingGlyph()
250 { 268 {
251 ensureGlyphCache(); 269 ensureGlyphCache();
252 return m_missingGlyph; 270 return m_missingGlyph;
253 } 271 }
254 272
255 } 273 }
256 274
257 #endif // ENABLE(SVG_FONTS) 275 #endif // ENABLE(SVG_FONTS)
OLDNEW
« no previous file with comments | « Source/core/svg/SVGFontElement.h ('k') | Source/core/svg/SVGGlyphMap.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698