Changeset 181492 in webkit
- Timestamp:
- Mar 13, 2015 6:10:53 PM (9 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 12 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r181491 r181492 1 2015-03-13 Antti Koivisto <antti@apple.com> 2 3 Cache glyph widths to GlyphPages 4 https://bugs.webkit.org/show_bug.cgi?id=142028 5 6 Reviewed by Andreas Kling. 7 8 Currently we have a separate cache in Font for glyph widths. In practice we always need 9 the widths so we can just cache them in GlyphPages. This simplifies the code and removes 10 a per-character hash lookup from WidthIterator. 11 12 * platform/graphics/Font.cpp: 13 (WebCore::Font::Font): 14 (WebCore::Font::initCharWidths): 15 (WebCore::Font::platformGlyphInit): 16 (WebCore::createAndFillGlyphPage): 17 (WebCore::Font::computeWidthForGlyph): 18 19 Rename to make it clear this doesn't cache. 20 21 (WebCore::GlyphPage::setGlyphDataForIndex): 22 23 Initialize the width. 24 This could go to GlyphPage.cpp if we had one. 25 26 * platform/graphics/Font.h: 27 (WebCore::Font::glyphZeroWidth): 28 (WebCore::Font::isZeroWidthSpaceGlyph): 29 (WebCore::Font::zeroGlyph): Deleted. 30 (WebCore::Font::setZeroGlyph): Deleted. 31 (WebCore::Font::widthForGlyph): Deleted. 32 * platform/graphics/FontCascade.cpp: 33 (WebCore::offsetToMiddleOfGlyph): 34 * platform/graphics/FontCascadeFonts.cpp: 35 (WebCore::FontCascadeFonts::glyphDataForCharacter): 36 * platform/graphics/GlyphPage.h: 37 (WebCore::GlyphData::GlyphData): 38 39 Return width too as part of GlyphData. 40 41 (WebCore::GlyphPage::glyphDataForIndex): 42 (WebCore::GlyphPage::setGlyphDataForCharacter): 43 (WebCore::GlyphPage::setGlyphDataForIndex): 44 (WebCore::GlyphPage::GlyphPage): 45 * platform/graphics/WidthIterator.cpp: 46 (WebCore::WidthIterator::advanceInternal): 47 48 No need to lookup width separately now. 49 50 * platform/graphics/mac/ComplexTextController.cpp: 51 (WebCore::ComplexTextController::adjustGlyphsAndAdvances): 52 * platform/graphics/mac/ComplexTextControllerCoreText.mm: 53 (WebCore::ComplexTextController::ComplexTextRun::ComplexTextRun): 54 * rendering/mathml/RenderMathMLOperator.cpp: 55 (WebCore::RenderMathMLOperator::advanceForGlyph): 56 * rendering/svg/SVGTextRunRenderingContext.cpp: 57 (WebCore::missingGlyphForFont): 58 * svg/SVGFontData.cpp: 59 (WebCore::SVGFontData::initializeFont): 60 1 61 2015-03-13 Eric Carlson <eric.carlson@apple.com> 2 62 -
trunk/Source/WebCore/platform/graphics/Font.cpp
r181348 r181492 55 55 , m_avgCharWidth(-1) 56 56 , m_platformData(platformData) 57 , m_treatAsFixedPitch(false)58 57 , m_isCustomFont(isCustomFont) 59 58 , m_isLoading(isLoading) 60 59 , m_isTextOrientationFallback(isTextOrientationFallback) 61 , m_isBrokenIdeographFallback(false)62 , m_mathData(nullptr)63 #if ENABLE(OPENTYPE_VERTICAL)64 , m_verticalData(0)65 #endif66 , m_hasVerticalGlyphs(false)67 60 { 68 61 platformInit(); … … 80 73 : m_platformData(FontPlatformData(fontSize, syntheticBold, syntheticItalic)) 81 74 , m_svgData(WTF::move(svgData)) 82 , m_treatAsFixedPitch(false)83 75 , m_isCustomFont(true) 84 , m_isLoading(false)85 , m_isTextOrientationFallback(false)86 , m_isBrokenIdeographFallback(false)87 , m_mathData(nullptr)88 #if ENABLE(OPENTYPE_VERTICAL)89 , m_verticalData(0)90 #endif91 , m_hasVerticalGlyphs(false)92 #if PLATFORM(IOS)93 , m_shouldNotBeUsedForArabic(false)94 #endif95 76 { 96 77 m_svgData->initializeFont(this, fontSize); 78 if (m_glyphPageZero) 79 m_glyphPageZero->setImmutable(); 97 80 } 98 81 … … 107 90 Glyph digitZeroGlyph = glyphPageZero->glyphDataForCharacter(digitZeroChar).glyph; 108 91 if (digitZeroGlyph) 109 m_avgCharWidth = widthForGlyph(digitZeroGlyph);92 m_avgCharWidth = computeWidthForGlyph(digitZeroGlyph); 110 93 } 111 94 … … 122 105 auto* glyphPageZero = glyphPage(0); 123 106 if (!glyphPageZero) { 124 m_spaceGlyph = 0;125 m_spaceWidth = 0;126 m_zeroGlyph = 0;127 m_adjustedSpaceWidth = 0;128 107 determinePitch(); 129 m_zeroWidthSpaceGlyph = 0;130 108 return; 131 109 } 132 133 110 // Ask for the glyph for 0 to avoid paging in ZERO WIDTH SPACE. Control characters, including 0, 134 111 // are mapped to the ZERO WIDTH SPACE glyph. 135 112 m_zeroWidthSpaceGlyph = glyphPageZero->glyphDataForCharacter(0).glyph; 136 137 113 // Nasty hack to determine if we should round or ceil space widths. 138 114 // If the font is monospace or fake monospace we ceil to ensure that 139 115 // every character and the space are the same width. Otherwise we round. 140 m_spaceGlyph = glyphPageZero->glyphDataForCharacter(' ').glyph; 141 float width = widthForGlyph(m_spaceGlyph); 142 m_spaceWidth = width; 143 m_zeroGlyph = glyphPageZero->glyphDataForCharacter('0').glyph; 144 m_fontMetrics.setZeroWidth(widthForGlyph(m_zeroGlyph)); 116 auto spaceGlyphData = glyphPageZero->glyphDataForCharacter(' '); 117 m_spaceGlyph = spaceGlyphData.glyph; 118 m_spaceWidth = spaceGlyphData.width; 119 m_fontMetrics.setZeroWidth(glyphPageZero->glyphDataForCharacter('0').width); 145 120 determinePitch(); 146 m_adjustedSpaceWidth = m_treatAsFixedPitch ? ceilf(width) : roundf(width); 121 m_adjustedSpaceWidth = m_treatAsFixedPitch ? ceilf(m_spaceWidth) : roundf(m_spaceWidth); 122 m_glyphZeroWidth = computeWidthForGlyph(0); 147 123 148 124 // Force the glyph for ZERO WIDTH SPACE to have zero width, unless it is shared with SPACE. … … 151 127 if (m_zeroWidthSpaceGlyph == m_spaceGlyph) 152 128 m_zeroWidthSpaceGlyph = 0; 129 else { 130 // Fixup the page zero now that we know the zero width glyph. 131 for (unsigned i = 0; i < GlyphPage::size; ++i) { 132 auto glyphData = m_glyphPageZero->glyphDataForIndex(i); 133 if (glyphData.glyph == m_zeroWidthSpaceGlyph) 134 m_glyphPageZero->setGlyphDataForIndex(i, { glyphData.glyph, 0, glyphData.font }); 135 } 136 } 137 m_glyphPageZero->setImmutable(); 153 138 } 154 139 … … 172 157 } 173 158 174 staticRefPtr<GlyphPage> createAndFillGlyphPage(unsigned pageNumber, const Font* font)159 RefPtr<GlyphPage> createAndFillGlyphPage(unsigned pageNumber, const Font* font) 175 160 { 176 161 #if PLATFORM(IOS) … … 245 230 return nullptr; 246 231 247 glyphPage->setImmutable();248 232 return glyphPage; 233 } 234 235 float Font::computeWidthForGlyph(Glyph glyph) const 236 { 237 if (isZeroWidthSpaceGlyph(glyph)) 238 return 0; 239 float width; 240 if (isSVGFont()) 241 width = m_svgData->widthForSVGGlyph(glyph, m_platformData.size()); 242 #if ENABLE(OPENTYPE_VERTICAL) 243 else if (m_verticalData) 244 #if USE(CG) || USE(CAIRO) 245 width = m_verticalData->advanceHeight(this, glyph) + m_syntheticBoldOffset; 246 #else 247 width = m_verticalData->advanceHeight(this, glyph); 248 #endif 249 #endif 250 else 251 width = platformWidthForGlyph(glyph); 252 return width; 249 253 } 250 254 … … 254 258 if (!m_glyphPageZero) 255 259 m_glyphPageZero = createAndFillGlyphPage(0, this); 260 // Zero page is marked immutable in platformGlyphInit. 256 261 return m_glyphPageZero.get(); 257 262 } 258 263 auto addResult = m_glyphPages.add(pageNumber, nullptr); 259 if (addResult.isNewEntry) 260 addResult.iterator->value = createAndFillGlyphPage(pageNumber, this); 261 262 return addResult.iterator->value.get(); 264 auto& page = addResult.iterator->value; 265 if (addResult.isNewEntry) { 266 page = createAndFillGlyphPage(pageNumber, this); 267 if (page) 268 page->setImmutable(); 269 } 270 return page.get(); 263 271 } 264 272 … … 459 467 } 460 468 469 void GlyphPage::setGlyphDataForIndex(unsigned index, Glyph glyph, const Font* font) 470 { 471 setGlyphDataForIndex(index, { glyph, font ? font->computeWidthForGlyph(glyph) : 0, font }); 472 } 473 474 461 475 } // namespace WebCore -
trunk/Source/WebCore/platform/graphics/Font.h
r180779 r181492 141 141 142 142 FloatRect boundsForGlyph(Glyph) const; 143 float widthForGlyph(Glyph) const; 144 FloatRect platformBoundsForGlyph(Glyph) const; 145 float platformWidthForGlyph(Glyph) const; 143 144 float computeWidthForGlyph(Glyph) const; 146 145 147 146 float spaceWidth() const { return m_spaceWidth; } … … 152 151 m_adjustedSpaceWidth = spaceWidth; 153 152 } 153 float glyphZeroWidth() const { return m_glyphZeroWidth; } 154 154 155 155 #if USE(CG) || USE(CAIRO) … … 162 162 void setZeroWidthSpaceGlyph(Glyph spaceGlyph) { m_zeroWidthSpaceGlyph = spaceGlyph; } 163 163 bool isZeroWidthSpaceGlyph(Glyph glyph) const { return glyph == m_zeroWidthSpaceGlyph && glyph; } 164 Glyph zeroGlyph() const { return m_zeroGlyph; }165 void setZeroGlyph(Glyph zeroGlyph) { m_zeroGlyph = zeroGlyph; }166 164 167 165 GlyphData glyphDataForCharacter(UChar32) const; … … 228 226 PassRefPtr<Font> platformCreateScaledFont(const FontDescription&, float scaleFactor) const; 229 227 228 float platformWidthForGlyph(Glyph) const; 229 FloatRect platformBoundsForGlyph(Glyph) const; 230 230 231 void removeFromSystemFallbackCache(); 232 233 friend RefPtr<GlyphPage> createAndFillGlyphPage(unsigned pageNumber, const Font*); 231 234 232 235 #if PLATFORM(WIN) … … 247 250 mutable HashMap<unsigned, RefPtr<GlyphPage>> m_glyphPages; 248 251 mutable std::unique_ptr<GlyphMetricsMap<FloatRect>> m_glyphToBoundsMap; 249 mutable GlyphMetricsMap<float> m_glyphToWidthMap; 250 251 bool m_treatAsFixedPitch; 252 bool m_isCustomFont; // Whether or not we are custom font loaded via @font-face 253 bool m_isLoading; // Whether or not this custom font is still in the act of loading. 254 255 bool m_isTextOrientationFallback; 256 bool m_isBrokenIdeographFallback; 252 253 bool m_treatAsFixedPitch { false }; 254 bool m_isCustomFont { false }; // Whether or not we are custom font loaded via @font-face 255 bool m_isLoading { false }; // Whether or not this custom font is still in the act of loading. 256 257 bool m_isTextOrientationFallback { false }; 258 bool m_isBrokenIdeographFallback { false }; 257 259 258 260 bool m_isUsedInSystemFallbackCache { false }; … … 262 264 RefPtr<OpenTypeVerticalData> m_verticalData; 263 265 #endif 264 bool m_hasVerticalGlyphs; 265 266 Glyph m_spaceGlyph; 267 float m_spaceWidth; 268 Glyph m_zeroGlyph; 269 float m_adjustedSpaceWidth; 270 271 Glyph m_zeroWidthSpaceGlyph; 266 bool m_hasVerticalGlyphs { false }; 267 268 Glyph m_spaceGlyph { 0 }; 269 float m_spaceWidth { 0 }; 270 float m_adjustedSpaceWidth { 0 }; 271 272 Glyph m_zeroWidthSpaceGlyph { 0 }; 273 274 float m_glyphZeroWidth { 0 }; 272 275 273 276 struct DerivedFontData { … … 310 313 #endif 311 314 #if PLATFORM(IOS) 312 bool m_shouldNotBeUsedForArabic ;315 bool m_shouldNotBeUsedForArabic { false }; 313 316 #endif 314 317 }; … … 333 336 } 334 337 335 ALWAYS_INLINE float Font::widthForGlyph(Glyph glyph) const336 {337 if (isZeroWidthSpaceGlyph(glyph))338 return 0;339 340 float width = m_glyphToWidthMap.metricsForGlyph(glyph);341 if (width != cGlyphSizeUnknown)342 return width;343 344 if (isSVGFont())345 width = m_svgData->widthForSVGGlyph(glyph, m_platformData.size());346 #if ENABLE(OPENTYPE_VERTICAL)347 else if (m_verticalData)348 #if USE(CG) || USE(CAIRO)349 width = m_verticalData->advanceHeight(this, glyph) + m_syntheticBoldOffset;350 #else351 width = m_verticalData->advanceHeight(this, glyph);352 #endif353 #endif354 else355 width = platformWidthForGlyph(glyph);356 357 m_glyphToWidthMap.setMetricsForGlyph(glyph, width);358 return width;359 }360 361 338 } // namespace WebCore 362 339 -
trunk/Source/WebCore/platform/graphics/FontCascade.cpp
r181172 r181492 1340 1340 } 1341 1341 // FIXME: Use glyph bounds once they make sense for vertical fonts. 1342 return fontData-> widthForGlyph(glyph) / 2;1342 return fontData->computeWidthForGlyph(glyph) / 2; 1343 1343 } 1344 1344 -
trunk/Source/WebCore/platform/graphics/FontCascadeFonts.cpp
r180779 r181492 388 388 389 389 glyphData = glyphDataForNormalVariant(c, description); 390 cachedPage->setGlyphDataForCharacter(c, glyphData .glyph, glyphData.font);390 cachedPage->setGlyphDataForCharacter(c, glyphData); 391 391 } 392 392 return glyphData; -
trunk/Source/WebCore/platform/graphics/GlyphPage.h
r180779 r181492 45 45 // character. 46 46 struct GlyphData { 47 GlyphData(Glyph g = 0, const Font* f = 0) 48 : glyph(g) 49 , font(f) 50 { 51 } 52 Glyph glyph; 53 const Font* font; 47 GlyphData() { } 48 GlyphData(Glyph glyph, float width, const Font* font) 49 : glyph(glyph) 50 , width(width) 51 , font(font) 52 { } 53 54 Glyph glyph { 0 }; 55 float width { 0 }; 56 const Font* font { nullptr }; 54 57 }; 55 58 … … 110 113 ASSERT_WITH_SECURITY_IMPLICATION(index < size); 111 114 Glyph glyph = m_glyphs[index]; 115 float width = m_widths[index]; 112 116 if (hasPerGlyphFontData()) 113 return GlyphData(glyph, m_perGlyphFontData[index]);114 return GlyphData(glyph, glyph ? m_fontForAllGlyphs : 0);117 return { glyph, width, m_perGlyphFontData[index] }; 118 return { glyph, width, glyph ? m_fontForAllGlyphs : nullptr }; 115 119 } 116 120 … … 129 133 } 130 134 131 void setGlyphDataForCharacter(UChar32 c, Glyph g, const Font* f)135 void setGlyphDataForCharacter(UChar32 c, const GlyphData& glyphData) 132 136 { 133 setGlyphDataForIndex(indexForCharacter(c), g , f);137 setGlyphDataForIndex(indexForCharacter(c), glyphData); 134 138 } 135 139 136 void setGlyphDataForIndex(unsigned index, Glyph glyph, const Font* font) 140 void setGlyphDataForIndex(unsigned index, Glyph, const Font*); 141 142 void setGlyphDataForIndex(unsigned index, const GlyphData& glyphData) 137 143 { 138 144 ASSERT_WITH_SECURITY_IMPLICATION(index < size); 139 145 ASSERT(!m_isImmutable); 140 141 m_glyphs[index] = glyph; 146 147 m_glyphs[index] = glyphData.glyph; 148 m_widths[index] = glyphData.width; 142 149 143 150 // GlyphPage getters will always return a null Font* for glyph #0 if there's no per-glyph font array. 144 151 if (hasPerGlyphFontData()) { 145 m_perGlyphFontData[index] = glyph ?font : 0;152 m_perGlyphFontData[index] = glyphData.glyph ? glyphData.font : 0; 146 153 return; 147 154 } 148 155 149 156 // A single-font GlyphPage already assigned m_fontForAllGlyphs in the constructor. 150 ASSERT(!glyph || font == m_fontForAllGlyphs); 151 } 152 153 void setGlyphDataForIndex(unsigned index, const GlyphData& glyphData) 154 { 155 setGlyphDataForIndex(index, glyphData.glyph, glyphData.font); 157 ASSERT(!glyphData.glyph || glyphData.font == m_fontForAllGlyphs); 156 158 } 157 159 … … 169 171 { 170 172 memset(m_glyphs, 0, sizeof(m_glyphs)); 173 memset(m_widths, 0, sizeof(m_widths)); 171 174 if (hasPerGlyphFontData()) 172 175 memset(m_perGlyphFontData, 0, sizeof(Font*) * GlyphPage::size); … … 176 179 bool hasPerGlyphFontData() const { return !m_fontForAllGlyphs; } 177 180 178 const Font* m_fontForAllGlyphs ;181 const Font* m_fontForAllGlyphs { nullptr }; 179 182 Glyph m_glyphs[size]; 183 float m_widths[size]; 180 184 181 185 bool m_isImmutable { false }; -
trunk/Source/WebCore/platform/graphics/WidthIterator.cpp
r180779 r181492 192 192 width = m_font->tabWidth(*font, m_run.tabSize(), m_run.xPos() + m_runWidthSoFar + widthSinceLastRounding); 193 193 else { 194 width = font->widthForGlyph(glyph);194 width = glyphData.width; 195 195 196 196 // SVG uses horizontalGlyphStretch(), when textLength is used to stretch/squeeze text. -
trunk/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp
r181090 r181492 639 639 #if PLATFORM(IOS) 640 640 if (isEmoji && advance.width) 641 advance.width = font. widthForGlyph(glyph);641 advance.width = font.computeWidthForGlyph(glyph); 642 642 #endif 643 643 -
trunk/Source/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.mm
r181172 r181492 169 169 m_glyphsVector.fill(0, m_glyphCount); 170 170 m_glyphs = m_glyphsVector.data(); 171 m_advancesVector.fill(CGSizeMake(m_font. widthForGlyph(0), 0), m_glyphCount);171 m_advancesVector.fill(CGSizeMake(m_font.glyphZeroWidth(), 0), m_glyphCount); 172 172 m_advances = m_advancesVector.data(); 173 173 } -
trunk/Source/WebCore/rendering/mathml/RenderMathMLOperator.cpp
r181398 r181492 1344 1344 float RenderMathMLOperator::advanceForGlyph(const GlyphData& data) const 1345 1345 { 1346 return data.font && data.glyph ? data.font->widthForGlyph(data.glyph) : 0; 1346 // FIXME: MathML code synthesizes bad GlyphDatas. 1347 if (!data.font) 1348 return 0; 1349 return data.width ? data.width : data.font->computeWidthForGlyph(data.glyph); 1347 1350 } 1348 1351 -
trunk/Source/WebCore/rendering/svg/SVGTextRunRenderingContext.cpp
r180779 r181492 299 299 SVGFontFaceElement* fontFaceElement; 300 300 svgFontAndFontFaceElementForFontData(&primaryFont, fontFaceElement, fontElement); 301 return GlyphData(fontElement->missingGlyph(), &primaryFont); 301 auto missingGlyph = fontElement->missingGlyph(); 302 return { missingGlyph, primaryFont.computeWidthForGlyph(missingGlyph), &primaryFont }; 302 303 } 303 304 -
trunk/Source/WebCore/svg/SVGFontData.cpp
r180779 r181492 80 80 // Fallback if x_heightAttr is not specified for the font element. 81 81 Glyph letterXGlyph = glyphPageZero->glyphDataForCharacter('x').glyph; 82 xHeight = letterXGlyph ? font-> widthForGlyph(letterXGlyph) : 2 * ascent / 3;82 xHeight = letterXGlyph ? font->computeWidthForGlyph(letterXGlyph) : 2 * ascent / 3; 83 83 } 84 84 … … 100 100 101 101 // Calculate space width. 102 Glyph spaceGlyph = glyphPageZero->glyphDataForCharacter(' ').glyph;103 font->setSpaceGlyph(spaceGlyph );104 font->setSpaceWidths( font->widthForGlyph(spaceGlyph));102 auto spaceGlyphData = glyphPageZero->glyphDataForCharacter(' '); 103 font->setSpaceGlyph(spaceGlyphData.glyph); 104 font->setSpaceWidths(spaceGlyphData.width); 105 105 106 106 // Estimate average character width. 107 Glyph numeralZeroGlyph = glyphPageZero->glyphDataForCharacter('0').glyph;108 font->setAvgCharWidth(numeralZeroGlyph ? font->widthForGlyph(numeralZeroGlyph): font->spaceWidth());107 auto numeralZeroGlyphData = glyphPageZero->glyphDataForCharacter('0'); 108 font->setAvgCharWidth(numeralZeroGlyphData.glyph ? numeralZeroGlyphData.width : font->spaceWidth()); 109 109 110 110 // Estimate maximum character width. 111 Glyph letterWGlyph = glyphPageZero->glyphDataForCharacter('W').glyph;112 font->setMaxCharWidth(letterWGlyph ? font->widthForGlyph(letterWGlyph): ascent);111 auto letterWGlyphData = glyphPageZero->glyphDataForCharacter('W'); 112 font->setMaxCharWidth(letterWGlyphData.glyph ? letterWGlyphData.width : ascent); 113 113 } 114 114 … … 178 178 iterator.setLastGlyphName(svgGlyph.glyphName); 179 179 glyphData.glyph = svgGlyph.tableEntry; 180 glyphData.width = glyphData.font->computeWidthForGlyph(glyphData.glyph); 180 181 advanceLength = svgGlyph.unicodeStringLength; 181 182 return true; … … 201 202 iterator.setLastGlyphName(svgGlyph.glyphName); 202 203 glyphData.glyph = svgGlyph.tableEntry; 204 glyphData.width = glyphData.font->computeWidthForGlyph(glyphData.glyph); 203 205 advanceLength = svgGlyph.unicodeStringLength; 204 206 return true;
Note: See TracChangeset
for help on using the changeset viewer.