Changeset 180752 in webkit
- Timestamp:
- Feb 27, 2015 8:12:13 AM (9 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 12 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r180727 r180752 1 2015-02-27 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-02-26 Alexey Proskuryakov <ap@apple.com> 2 62 -
trunk/Source/WebCore/platform/graphics/Font.cpp
r180561 r180752 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); … … 107 88 Glyph digitZeroGlyph = glyphPageZero->glyphDataForCharacter(digitZeroChar).glyph; 108 89 if (digitZeroGlyph) 109 m_avgCharWidth = widthForGlyph(digitZeroGlyph);90 m_avgCharWidth = computeWidthForGlyph(digitZeroGlyph); 110 91 } 111 92 … … 122 103 auto* glyphPageZero = glyphPage(0); 123 104 if (!glyphPageZero) { 124 m_spaceGlyph = 0;125 m_spaceWidth = 0;126 m_zeroGlyph = 0;127 m_adjustedSpaceWidth = 0;128 105 determinePitch(); 129 m_zeroWidthSpaceGlyph = 0;130 106 return; 131 107 } 132 133 108 // Ask for the glyph for 0 to avoid paging in ZERO WIDTH SPACE. Control characters, including 0, 134 109 // are mapped to the ZERO WIDTH SPACE glyph. 135 110 m_zeroWidthSpaceGlyph = glyphPageZero->glyphDataForCharacter(0).glyph; 136 137 111 // Nasty hack to determine if we should round or ceil space widths. 138 112 // If the font is monospace or fake monospace we ceil to ensure that 139 113 // 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)); 114 auto spaceGlyphData = glyphPageZero->glyphDataForCharacter(' '); 115 m_spaceGlyph = spaceGlyphData.glyph; 116 m_spaceWidth = spaceGlyphData.width; 117 m_fontMetrics.setZeroWidth(glyphPageZero->glyphDataForCharacter('0').width); 145 118 determinePitch(); 146 m_adjustedSpaceWidth = m_treatAsFixedPitch ? ceilf(width) : roundf(width); 119 m_adjustedSpaceWidth = m_treatAsFixedPitch ? ceilf(m_spaceWidth) : roundf(m_spaceWidth); 120 m_glyphZeroWidth = computeWidthForGlyph(0); 147 121 148 122 // Force the glyph for ZERO WIDTH SPACE to have zero width, unless it is shared with SPACE. … … 151 125 if (m_zeroWidthSpaceGlyph == m_spaceGlyph) 152 126 m_zeroWidthSpaceGlyph = 0; 127 else { 128 // Fixup the page zero now that we know the zero width glyph. 129 for (unsigned i = 0; i < GlyphPage::size; ++i) { 130 auto glyphData = m_glyphPageZero->glyphDataForIndex(i); 131 if (glyphData.glyph == m_zeroWidthSpaceGlyph) 132 m_glyphPageZero->setGlyphDataForIndex(i, { glyphData.glyph, 0, glyphData.font }); 133 } 134 } 135 m_glyphPageZero->setImmutable(); 153 136 } 154 137 … … 172 155 } 173 156 174 staticRefPtr<GlyphPage> createAndFillGlyphPage(unsigned pageNumber, const Font* font)157 RefPtr<GlyphPage> createAndFillGlyphPage(unsigned pageNumber, const Font* font) 175 158 { 176 159 #if PLATFORM(IOS) … … 245 228 return nullptr; 246 229 247 glyphPage->setImmutable();248 230 return glyphPage; 231 } 232 233 float Font::computeWidthForGlyph(Glyph glyph) const 234 { 235 if (isZeroWidthSpaceGlyph(glyph)) 236 return 0; 237 float width; 238 if (isSVGFont()) 239 width = m_svgData->widthForSVGGlyph(glyph, m_platformData.size()); 240 #if ENABLE(OPENTYPE_VERTICAL) 241 else if (m_verticalData) 242 #if USE(CG) || USE(CAIRO) 243 width = m_verticalData->advanceHeight(this, glyph) + m_syntheticBoldOffset; 244 #else 245 width = m_verticalData->advanceHeight(this, glyph); 246 #endif 247 #endif 248 else 249 width = platformWidthForGlyph(glyph); 250 return width; 249 251 } 250 252 … … 254 256 if (!m_glyphPageZero) 255 257 m_glyphPageZero = createAndFillGlyphPage(0, this); 258 // Zero page is marked immutable in platformGlyphInit. 256 259 return m_glyphPageZero.get(); 257 260 } 258 261 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(); 262 auto& page = addResult.iterator->value; 263 if (addResult.isNewEntry) { 264 page = createAndFillGlyphPage(pageNumber, this); 265 if (page) 266 page->setImmutable(); 267 } 268 return page.get(); 263 269 } 264 270 … … 459 465 } 460 466 467 void GlyphPage::setGlyphDataForIndex(unsigned index, Glyph glyph, const Font* font) 468 { 469 setGlyphDataForIndex(index, { glyph, font ? font->computeWidthForGlyph(glyph) : 0, font }); 470 } 471 472 461 473 } // namespace WebCore -
trunk/Source/WebCore/platform/graphics/Font.h
r179861 r180752 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
r180294 r180752 1335 1335 } 1336 1336 // FIXME: Use glyph bounds once they make sense for vertical fonts. 1337 return fontData-> widthForGlyph(glyph) / 2;1337 return fontData->computeWidthForGlyph(glyph) / 2; 1338 1338 } 1339 1339 -
trunk/Source/WebCore/platform/graphics/FontCascadeFonts.cpp
r180294 r180752 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
r179861 r180752 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
r178940 r180752 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
r180191 r180752 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
r180281 r180752 164 164 m_glyphsVector.fill(0, m_glyphCount); 165 165 m_glyphs = m_glyphsVector.data(); 166 m_advancesVector.fill(CGSizeMake(m_font. widthForGlyph(0), 0), m_glyphCount);166 m_advancesVector.fill(CGSizeMake(m_font.glyphZeroWidth(), 0), m_glyphCount); 167 167 m_advances = m_advancesVector.data(); 168 168 } -
trunk/Source/WebCore/rendering/mathml/RenderMathMLOperator.cpp
r178940 r180752 1344 1344 float RenderMathMLOperator::advanceForGlyph(const GlyphData& data) const 1345 1345 { 1346 return data.font->widthForGlyph(data.glyph); 1346 // FIXME: MathML code synthesizes bad GlyphDatas. 1347 return data.width ? data.width : data.font->computeWidthForGlyph(data.glyph); 1347 1348 } 1348 1349 -
trunk/Source/WebCore/rendering/svg/SVGTextRunRenderingContext.cpp
r178940 r180752 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
r178940 r180752 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
Note: See TracChangeset
for help on using the changeset viewer.