Source/WebCore/ChangeLog

 12016-09-08 Myles C. Maxfield <mmaxfield@apple.com>
 2
 3 [Cocoa] Improve performance of glyph advance metrics gathering
 4 https://bugs.webkit.org/show_bug.cgi?id=161119
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 No new tests (OOPS!).
 9
 10 * platform/graphics/Font.cpp:
 11 (WebCore::Font::platformGlyphInit):
 12 * platform/graphics/Font.h:
 13 (WebCore::Font::widthForGlyph):
 14 * platform/graphics/GlyphPage.h:
 15 (WebCore::GlyphData::GlyphData):
 16 (WebCore::GlyphPage::advanceForCharacter):
 17 (WebCore::GlyphPage::glyphDataForIndex):
 18 (WebCore::GlyphPage::advanceForIndex):
 19 (WebCore::GlyphPage::setGlyphForIndex):
 20 * platform/graphics/WidthIterator.cpp:
 21 (WebCore::WidthIterator::advanceInternal):
 22 * platform/graphics/cocoa/FontCocoa.mm:
 23 (WebCore::Font::platformWidthForGlyph):
 24 * platform/graphics/mac/GlyphPageMac.cpp:
 25 (WebCore::GlyphPage::fill):
 26 * platform/spi/cocoa/CoreTextSPI.h:
 27
1282016-09-08 Yusuke Suzuki <utatane.tea@gmail.com>
229
330 ScriptRunner should be driven by PendingScript rather than ScriptElement

Source/WebCore/platform/graphics/Font.cpp

@@Font::Font(const FontPlatformData& platformData, bool isCustomFont, bool isLoadi
8181// Estimates of avgCharWidth and maxCharWidth for platforms that don't support accessing these values from the font.
8282void Font::initCharWidths()
8383{
84  auto* glyphPageZero = glyphPage(0);
 84 auto* glyphPageZero = glyphPage('0' / GlyphPage::size);
8585
8686 // Treat the width of a '0' as the avgCharWidth.
8787 if (m_avgCharWidth <= 0.f && glyphPageZero) {
88  static const UChar32 digitZeroChar = '0';
89  Glyph digitZeroGlyph = glyphPageZero->glyphDataForCharacter(digitZeroChar).glyph;
 88 Glyph digitZeroGlyph = glyphPageZero->glyphDataForCharacter('0').glyph;
9089 if (digitZeroGlyph)
9190 m_avgCharWidth = widthForGlyph(digitZeroGlyph);
9291 }

@@void Font::initCharWidths()
102101void Font::platformGlyphInit()
103102{
104103 auto* glyphPageZero = glyphPage(0);
105  if (!glyphPageZero) {
106  determinePitch();
107  return;
108  }
 104 auto* glyphPageCharacterZero = glyphPage('0' / GlyphPage::size);
 105 auto* glyphPageSpace = glyphPage(space / GlyphPage::size);
109106
110107 // Ask for the glyph for 0 to avoid paging in ZERO WIDTH SPACE. Control characters, including 0,
111108 // are mapped to the ZERO WIDTH SPACE glyph.
112  m_zeroWidthSpaceGlyph = glyphPageZero->glyphDataForCharacter(0).glyph;
 109 if (glyphPageZero)
 110 m_zeroWidthSpaceGlyph = glyphPageZero->glyphDataForCharacter(0).glyph;
113111
114112 // Nasty hack to determine if we should round or ceil space widths.
115113 // If the font is monospace or fake monospace we ceil to ensure that
116114 // every character and the space are the same width. Otherwise we round.
117  m_spaceGlyph = glyphPageZero->glyphDataForCharacter(' ').glyph;
 115 if (glyphPageSpace)
 116 m_spaceGlyph = glyphPageSpace->glyphDataForCharacter(space).glyph;
118117 float width = widthForGlyph(m_spaceGlyph);
119118 m_spaceWidth = width;
120  m_zeroGlyph = glyphPageZero->glyphDataForCharacter('0').glyph;
 119 if (glyphPageCharacterZero)
 120 m_zeroGlyph = glyphPageCharacterZero->glyphDataForCharacter('0').glyph;
121121 m_fontMetrics.setZeroWidth(widthForGlyph(m_zeroGlyph));
122122 determinePitch();
123123 m_adjustedSpaceWidth = m_treatAsFixedPitch ? ceilf(width) : roundf(width);

@@static RefPtr<GlyphPage> createAndFillGlyphPage(unsigned pageNumber, const Font&
152152 // FIXME: Times New Roman contains Arabic glyphs, but Core Text doesn't know how to shape them. See <rdar://problem/9823975>.
153153 // Once we have the fix for <rdar://problem/9823975> then remove this code together with Font::shouldNotBeUsedForArabic()
154154 // in <rdar://problem/12096835>.
155  if (pageNumber == 6 && font.shouldNotBeUsedForArabic())
 155 if (pageNumber >= 0x60 && pageNumber < 0x70 && font.shouldNotBeUsedForArabic())
156156 return nullptr;
157157#endif
158158

@@static RefPtr<GlyphPage> createAndFillGlyphPage(unsigned pageNumber, const Font&
165165 for (unsigned i = 0; i < GlyphPage::size; i++)
166166 buffer[i] = start + i;
167167
 168 static_assert(GlyphPage::size == 16 && !(GlyphPage::size & (GlyphPage::size - 1)), "createAndFillGlyphPage() assumes GlyphPage::size is 16.");
168169 if (!start) {
169170 // Control characters must not render at all.
170  for (unsigned i = 0; i < 0x20; ++i)
171  buffer[i] = zeroWidthSpace;
172  for (unsigned i = 0x7F; i < 0xA0; i++)
 171 for (unsigned i = 0; i < 0x10; ++i)
173172 buffer[i] = zeroWidthSpace;
174  buffer[softHyphen] = zeroWidthSpace;
175 
176173 // \n, \t, and nonbreaking space must render as a space.
177  buffer[(int)'\n'] = ' ';
178  buffer[(int)'\t'] = ' ';
179  buffer[noBreakSpace] = ' ';
 174 buffer[static_cast<int>('\t')] = space;
 175 buffer[static_cast<int>('\n')] = space;
 176 } else if (pageNumber == 1) {
 177 // Control characters must not render at all.
 178 for (unsigned i = 0; i < 0x10; ++i)
 179 buffer[i] = zeroWidthSpace;
 180 } else if (start == (0x7F & ~(GlyphPage::size - 1))) {
 181 buffer[0x7F - start] = zeroWidthSpace;
 182 } else if (pageNumber >= 8 && pageNumber < 10) {
 183 for (unsigned i = 0; i < GlyphPage::size; ++i)
 184 buffer[i] = zeroWidthSpace;
 185 } else if (pageNumber == 10) {
 186 buffer[softHyphen - start] = zeroWidthSpace;
 187 buffer[noBreakSpace - start] = space;
180188 } else if (start == (leftToRightMark & ~(GlyphPage::size - 1))) {
181189 // LRM, RLM, LRE, RLE, ZWNJ, ZWJ, and PDF must not render at all.
182190 buffer[leftToRightMark - start] = zeroWidthSpace;
183191 buffer[rightToLeftMark - start] = zeroWidthSpace;
 192 buffer[zeroWidthNonJoiner - start] = zeroWidthSpace;
 193 buffer[zeroWidthJoiner - start] = zeroWidthSpace;
 194 } else if (start == (leftToRightEmbed & ~(GlyphPage::size - 1))) {
184195 buffer[leftToRightEmbed - start] = zeroWidthSpace;
185196 buffer[rightToLeftEmbed - start] = zeroWidthSpace;
186197 buffer[leftToRightOverride - start] = zeroWidthSpace;
187198 buffer[rightToLeftOverride - start] = zeroWidthSpace;
 199 buffer[popDirectionalFormatting - start] = zeroWidthSpace;
 200 } else if (start == (leftToRightIsolate & ~(GlyphPage::size - 1))) {
188201 buffer[leftToRightIsolate - start] = zeroWidthSpace;
189202 buffer[rightToLeftIsolate - start] = zeroWidthSpace;
190  buffer[zeroWidthNonJoiner - start] = zeroWidthSpace;
191  buffer[zeroWidthJoiner - start] = zeroWidthSpace;
192  buffer[popDirectionalFormatting - start] = zeroWidthSpace;
193203 buffer[popDirectionalIsolate - start] = zeroWidthSpace;
194204 buffer[firstStrongIsolate - start] = zeroWidthSpace;
195205 } else if (start == (objectReplacementCharacter & ~(GlyphPage::size - 1))) {

Source/WebCore/platform/graphics/Font.h

@@ALWAYS_INLINE float Font::widthForGlyph(Glyph glyph) const
337337 return width;
338338
339339#if ENABLE(OPENTYPE_VERTICAL)
340  if (m_verticalData)
 340 if (m_verticalData) {
341341#if USE(CG) || USE(CAIRO)
342342 width = m_verticalData->advanceHeight(this, glyph) + m_syntheticBoldOffset;
343343#else
344344 width = m_verticalData->advanceHeight(this, glyph);
345345#endif
346  else
 346 } else
347347#endif
348348 width = platformWidthForGlyph(glyph);
349349

Source/WebCore/platform/graphics/GlyphMetricsMap.h

@@private:
5454 class GlyphMetricsPage {
5555 WTF_MAKE_FAST_ALLOCATED;
5656 public:
57  static const size_t size = 256; // Usually covers Latin-1 in a single page.
 57 static const size_t size = 16;
5858
5959 GlyphMetricsPage() = default;
6060 explicit GlyphMetricsPage(const T& initialValue)

Source/WebCore/platform/graphics/GlyphPage.h

@@struct GlyphData {
5757
5858// A GlyphPage contains a fixed-size set of GlyphData mappings for a contiguous
5959// range of characters in the Unicode code space. GlyphPages are indexed
60 // starting from 0 and incrementing for each 256 glyphs.
 60// starting from 0 and incrementing for each "size" number of glyphs.
6161class GlyphPage : public RefCounted<GlyphPage> {
6262public:
6363 static Ref<GlyphPage> create(const Font& font)

@@public:
7272
7373 static unsigned count() { return s_count; }
7474
75  static const size_t size = 256; // Covers Latin-1 in a single page.
 75 static const size_t size = 16;
7676 static unsigned indexForCharacter(UChar32 c) { return c % GlyphPage::size; }
7777
7878 GlyphData glyphDataForCharacter(UChar32 c) const