| Differences between
and this patch
- a/Source/WebCore/ChangeLog +27 lines
Lines 1-3 a/Source/WebCore/ChangeLog_sec1
1
2016-09-04  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
1
2016-09-03  Michael Catanzaro  <mcatanzaro@igalia.com>
28
2016-09-03  Michael Catanzaro  <mcatanzaro@igalia.com>
2
29
3
        Silence -Wparentheses warning triggered by r205266
30
        Silence -Wparentheses warning triggered by r205266
- a/Source/WebCore/platform/graphics/Font.cpp -18 / +30 lines
Lines 81-92 Font::Font(const FontPlatformData& platformData, bool isCustomFont, bool isLoadi a/Source/WebCore/platform/graphics/Font.cpp_sec1
81
// Estimates of avgCharWidth and maxCharWidth for platforms that don't support accessing these values from the font.
81
// Estimates of avgCharWidth and maxCharWidth for platforms that don't support accessing these values from the font.
82
void Font::initCharWidths()
82
void Font::initCharWidths()
83
{
83
{
84
    auto* glyphPageZero = glyphPage(0);
84
    auto* glyphPageZero = glyphPage('0' / GlyphPage::size);
85
85
86
    // Treat the width of a '0' as the avgCharWidth.
86
    // Treat the width of a '0' as the avgCharWidth.
87
    if (m_avgCharWidth <= 0.f && glyphPageZero) {
87
    if (m_avgCharWidth <= 0.f && glyphPageZero) {
88
        static const UChar32 digitZeroChar = '0';
88
        Glyph digitZeroGlyph = glyphPageZero->glyphDataForCharacter('0').glyph;
89
        Glyph digitZeroGlyph = glyphPageZero->glyphDataForCharacter(digitZeroChar).glyph;
90
        if (digitZeroGlyph)
89
        if (digitZeroGlyph)
91
            m_avgCharWidth = widthForGlyph(digitZeroGlyph);
90
            m_avgCharWidth = widthForGlyph(digitZeroGlyph);
92
    }
91
    }
Lines 102-108 void Font::initCharWidths() a/Source/WebCore/platform/graphics/Font.cpp_sec2
102
void Font::platformGlyphInit()
101
void Font::platformGlyphInit()
103
{
102
{
104
    auto* glyphPageZero = glyphPage(0);
103
    auto* glyphPageZero = glyphPage(0);
105
    if (!glyphPageZero) {
104
    auto* glyphPageCharacterZero = glyphPage('0' / GlyphPage::size);
105
    auto* glyphPageSpace = glyphPage(space / GlyphPage::size);
106
    if (!glyphPageZero || !glyphPageCharacterZero || !glyphPageSpace) {
106
        determinePitch();
107
        determinePitch();
107
        return;
108
        return;
108
    }
109
    }
Lines 114-123 void Font::platformGlyphInit() a/Source/WebCore/platform/graphics/Font.cpp_sec3
114
    // Nasty hack to determine if we should round or ceil space widths.
115
    // Nasty hack to determine if we should round or ceil space widths.
115
    // If the font is monospace or fake monospace we ceil to ensure that 
116
    // If the font is monospace or fake monospace we ceil to ensure that 
116
    // every character and the space are the same width. Otherwise we round.
117
    // every character and the space are the same width. Otherwise we round.
117
    m_spaceGlyph = glyphPageZero->glyphDataForCharacter(' ').glyph;
118
    m_spaceGlyph = glyphPageSpace->glyphDataForCharacter(space).glyph;
118
    float width = widthForGlyph(m_spaceGlyph);
119
    float width = widthForGlyph(m_spaceGlyph);
119
    m_spaceWidth = width;
120
    m_spaceWidth = width;
120
    m_zeroGlyph = glyphPageZero->glyphDataForCharacter('0').glyph;
121
    m_zeroGlyph = glyphPageCharacterZero->glyphDataForCharacter('0').glyph;
121
    m_fontMetrics.setZeroWidth(widthForGlyph(m_zeroGlyph));
122
    m_fontMetrics.setZeroWidth(widthForGlyph(m_zeroGlyph));
122
    determinePitch();
123
    determinePitch();
123
    m_adjustedSpaceWidth = m_treatAsFixedPitch ? ceilf(width) : roundf(width);
124
    m_adjustedSpaceWidth = m_treatAsFixedPitch ? ceilf(width) : roundf(width);
Lines 152-158 static RefPtr<GlyphPage> createAndFillGlyphPage(unsigned pageNumber, const Font& a/Source/WebCore/platform/graphics/Font.cpp_sec4
152
    // FIXME: Times New Roman contains Arabic glyphs, but Core Text doesn't know how to shape them. See <rdar://problem/9823975>.
153
    // FIXME: Times New Roman contains Arabic glyphs, but Core Text doesn't know how to shape them. See <rdar://problem/9823975>.
153
    // Once we have the fix for <rdar://problem/9823975> then remove this code together with Font::shouldNotBeUsedForArabic()
154
    // Once we have the fix for <rdar://problem/9823975> then remove this code together with Font::shouldNotBeUsedForArabic()
154
    // in <rdar://problem/12096835>.
155
    // in <rdar://problem/12096835>.
155
    if (pageNumber == 6 && font.shouldNotBeUsedForArabic())
156
    if (pageNumber >= 0x60 && pageNumber < 0x70 && && font.shouldNotBeUsedForArabic())
156
        return nullptr;
157
        return nullptr;
157
#endif
158
#endif
158
159
Lines 165-197 static RefPtr<GlyphPage> createAndFillGlyphPage(unsigned pageNumber, const Font& a/Source/WebCore/platform/graphics/Font.cpp_sec5
165
        for (unsigned i = 0; i < GlyphPage::size; i++)
166
        for (unsigned i = 0; i < GlyphPage::size; i++)
166
            buffer[i] = start + i;
167
            buffer[i] = start + i;
167
168
169
        static_assert(GlyphPage::size == 16 && !(GlyphPage::size & (GlyphPage::size - 1)), "createAndFillGlyphPage() assumes GlyphPage::size is 16.");
168
        if (!start) {
170
        if (!start) {
169
            // Control characters must not render at all.
171
            // Control characters must not render at all.
170
            for (unsigned i = 0; i < 0x20; ++i)
172
            for (unsigned i = 0; i < 0x10; ++i)
171
                buffer[i] = zeroWidthSpace;
172
            for (unsigned i = 0x7F; i < 0xA0; i++)
173
                buffer[i] = zeroWidthSpace;
173
                buffer[i] = zeroWidthSpace;
174
            buffer[softHyphen] = zeroWidthSpace;
175
176
            // \n, \t, and nonbreaking space must render as a space.
174
            // \n, \t, and nonbreaking space must render as a space.
177
            buffer[(int)'\n'] = ' ';
175
            buffer[static_cast<int>('\t')] = space;
178
            buffer[(int)'\t'] = ' ';
176
            buffer[static_cast<int>('\n')] = space;
179
            buffer[noBreakSpace] = ' ';
177
        } else if (start == 1) {
178
            // Control characters must not render at all.
179
            for (unsigned i = 0; i < 0x10; ++i)
180
                buffer[i] = zeroWidthSpace;
181
        } else if (start == (0x7F & ~(GlyphPage::size - 1))) {
182
            buffer[0x7F - start] = zeroWidthSpace;
183
        } else if (pageNumber >= 8 && pageNumber < 10) {
184
            for (unsigned i = 0; i < GlyphPage::size; ++i)
185
                buffer[i] = zeroWidthSpace;
186
        } else if (pageNumber == 10) {
187
            buffer[softHyphen - start] = zeroWidthSpace;
188
            buffer[noBreakSpace - start] = space;
180
        } else if (start == (leftToRightMark & ~(GlyphPage::size - 1))) {
189
        } else if (start == (leftToRightMark & ~(GlyphPage::size - 1))) {
181
            // LRM, RLM, LRE, RLE, ZWNJ, ZWJ, and PDF must not render at all.
190
            // LRM, RLM, LRE, RLE, ZWNJ, ZWJ, and PDF must not render at all.
182
            buffer[leftToRightMark - start] = zeroWidthSpace;
191
            buffer[leftToRightMark - start] = zeroWidthSpace;
183
            buffer[rightToLeftMark - start] = zeroWidthSpace;
192
            buffer[rightToLeftMark - start] = zeroWidthSpace;
193
        } else if (start == (leftToRightEmbed & ~(GlyphPage::size - 1))) {
184
            buffer[leftToRightEmbed - start] = zeroWidthSpace;
194
            buffer[leftToRightEmbed - start] = zeroWidthSpace;
185
            buffer[rightToLeftEmbed - start] = zeroWidthSpace;
195
            buffer[rightToLeftEmbed - start] = zeroWidthSpace;
186
            buffer[leftToRightOverride - start] = zeroWidthSpace;
196
            buffer[leftToRightOverride - start] = zeroWidthSpace;
187
            buffer[rightToLeftOverride - start] = zeroWidthSpace;
197
            buffer[rightToLeftOverride - start] = zeroWidthSpace;
198
            buffer[popDirectionalFormatting - start] = zeroWidthSpace;
199
        } else if (start == (leftToRightIsolate & ~(GlyphPage::size - 1))) {
188
            buffer[leftToRightIsolate - start] = zeroWidthSpace;
200
            buffer[leftToRightIsolate - start] = zeroWidthSpace;
189
            buffer[rightToLeftIsolate - start] = zeroWidthSpace;
201
            buffer[rightToLeftIsolate - start] = zeroWidthSpace;
190
            buffer[zeroWidthNonJoiner - start] = zeroWidthSpace;
191
            buffer[zeroWidthJoiner - start] = zeroWidthSpace;
192
            buffer[popDirectionalFormatting - start] = zeroWidthSpace;
193
            buffer[popDirectionalIsolate - start] = zeroWidthSpace;
202
            buffer[popDirectionalIsolate - start] = zeroWidthSpace;
194
            buffer[firstStrongIsolate - start] = zeroWidthSpace;
203
            buffer[firstStrongIsolate - start] = zeroWidthSpace;
204
        } else if (start == (zeroWidthNonJoiner & ~(GlyphPage::size - 1))) {
205
            buffer[zeroWidthNonJoiner - start] = zeroWidthSpace;
206
            buffer[zeroWidthJoiner - start] = zeroWidthSpace;
195
        } else if (start == (objectReplacementCharacter & ~(GlyphPage::size - 1))) {
207
        } else if (start == (objectReplacementCharacter & ~(GlyphPage::size - 1))) {
196
            // Object replacement character must not render at all.
208
            // Object replacement character must not render at all.
197
            buffer[objectReplacementCharacter - start] = zeroWidthSpace;
209
            buffer[objectReplacementCharacter - start] = zeroWidthSpace;
- a/Source/WebCore/platform/graphics/Font.h -2 / +2 lines
Lines 337-349 ALWAYS_INLINE float Font::widthForGlyph(Glyph glyph) const a/Source/WebCore/platform/graphics/Font.h_sec1
337
        return width;
337
        return width;
338
338
339
#if ENABLE(OPENTYPE_VERTICAL)
339
#if ENABLE(OPENTYPE_VERTICAL)
340
    if (m_verticalData)
340
    if (m_verticalData) {
341
#if USE(CG) || USE(CAIRO)
341
#if USE(CG) || USE(CAIRO)
342
        width = m_verticalData->advanceHeight(this, glyph) + m_syntheticBoldOffset;
342
        width = m_verticalData->advanceHeight(this, glyph) + m_syntheticBoldOffset;
343
#else
343
#else
344
        width = m_verticalData->advanceHeight(this, glyph);
344
        width = m_verticalData->advanceHeight(this, glyph);
345
#endif
345
#endif
346
    else
346
    } else
347
#endif
347
#endif
348
        width = platformWidthForGlyph(glyph);
348
        width = platformWidthForGlyph(glyph);
349
349
- a/Source/WebCore/platform/graphics/GlyphMetricsMap.h -1 / +1 lines
Lines 54-60 private: a/Source/WebCore/platform/graphics/GlyphMetricsMap.h_sec1
54
    class GlyphMetricsPage {
54
    class GlyphMetricsPage {
55
        WTF_MAKE_FAST_ALLOCATED;
55
        WTF_MAKE_FAST_ALLOCATED;
56
    public:
56
    public:
57
        static const size_t size = 256; // Usually covers Latin-1 in a single page.
57
        static const size_t size = 16;
58
58
59
        GlyphMetricsPage() = default;
59
        GlyphMetricsPage() = default;
60
        explicit GlyphMetricsPage(const T& initialValue)
60
        explicit GlyphMetricsPage(const T& initialValue)
- a/Source/WebCore/platform/graphics/GlyphPage.h -5 / +29 lines
Lines 31-40 a/Source/WebCore/platform/graphics/GlyphPage.h_sec1
31
#define GlyphPage_h
31
#define GlyphPage_h
32
32
33
#include "Glyph.h"
33
#include "Glyph.h"
34
#include <array>
34
#include <string.h>
35
#include <string.h>
35
#include <unicode/utypes.h>
36
#include <unicode/utypes.h>
37
#include <wtf/Optional.h>
36
#include <wtf/RefCounted.h>
38
#include <wtf/RefCounted.h>
37
#include <wtf/Ref.h>
39
#include <wtf/Ref.h>
40
#include <wtf/Vector.h>
38
41
39
namespace WebCore {
42
namespace WebCore {
40
43
Lines 43-51 class Font; a/Source/WebCore/platform/graphics/GlyphPage.h_sec2
43
// Holds the glyph index and the corresponding Font information for a given
46
// Holds the glyph index and the corresponding Font information for a given
44
// character.
47
// character.
45
struct GlyphData {
48
struct GlyphData {
46
    GlyphData(Glyph g = 0, const Font* f = 0)
49
    GlyphData(Glyph g = 0, const Font* f = nullptr, Optional<float> advance = Nullopt)
47
        : glyph(g)
50
        : glyph(g)
48
        , font(f)
51
        , font(f)
52
        , advance(advance)
49
    {
53
    {
50
    }
54
    }
51
55
Lines 53-58 struct GlyphData { a/Source/WebCore/platform/graphics/GlyphPage.h_sec3
53
57
54
    Glyph glyph;
58
    Glyph glyph;
55
    const Font* font;
59
    const Font* font;
60
    Optional<float> advance;
56
};
61
};
57
62
58
// A GlyphPage contains a fixed-size set of GlyphData mappings for a contiguous
63
// A GlyphPage contains a fixed-size set of GlyphData mappings for a contiguous
Lines 72-78 public: a/Source/WebCore/platform/graphics/GlyphPage.h_sec4
72
77
73
    static unsigned count() { return s_count; }
78
    static unsigned count() { return s_count; }
74
79
75
    static const size_t size = 256; // Covers Latin-1 in a single page.
80
    static constexpr size_t size = 16;
76
    static unsigned indexForCharacter(UChar32 c) { return c % GlyphPage::size; }
81
    static unsigned indexForCharacter(UChar32 c) { return c % GlyphPage::size; }
77
82
78
    GlyphData glyphDataForCharacter(UChar32 c) const
83
    GlyphData glyphDataForCharacter(UChar32 c) const
Lines 85-94 public: a/Source/WebCore/platform/graphics/GlyphPage.h_sec5
85
        return glyphForIndex(indexForCharacter(c));
90
        return glyphForIndex(indexForCharacter(c));
86
    }
91
    }
87
92
93
    Optional<float> advanceForCharacter(UChar32 c) const
94
    {
95
        return advanceForIndex(indexForCharacter(c));
96
    }
97
88
    GlyphData glyphDataForIndex(unsigned index) const
98
    GlyphData glyphDataForIndex(unsigned index) const
89
    {
99
    {
90
        Glyph glyph = glyphForIndex(index);
100
        Glyph glyph = glyphForIndex(index);
91
        return GlyphData(glyph, glyph ? &m_font : nullptr);
101
        return GlyphData(glyph, glyph ? &m_font : nullptr, advanceForIndex(index));
92
    }
102
    }
93
103
94
    Glyph glyphForIndex(unsigned index) const
104
    Glyph glyphForIndex(unsigned index) const
Lines 97-107 public: a/Source/WebCore/platform/graphics/GlyphPage.h_sec6
97
        return m_glyphs[index];
107
        return m_glyphs[index];
98
    }
108
    }
99
109
110
    Optional<float> advanceForIndex(unsigned index) const
111
    {
112
        ASSERT_WITH_SECURITY_IMPLICATION(index < size);
113
        if (m_advances.isEmpty())
114
            return Nullopt;
115
        return m_advances[index];
116
    }
117
100
    // FIXME: Pages are immutable after initialization. This should be private.
118
    // FIXME: Pages are immutable after initialization. This should be private.
101
    void setGlyphForIndex(unsigned index, Glyph glyph)
119
    void setGlyphForIndex(unsigned index, Glyph glyph, Optional<float> advance = Nullopt)
102
    {
120
    {
103
        ASSERT_WITH_SECURITY_IMPLICATION(index < size);
121
        ASSERT_WITH_SECURITY_IMPLICATION(index < size);
104
        m_glyphs[index] = glyph;
122
        m_glyphs[index] = glyph;
123
        if (advance) {
124
            if (m_advances.isEmpty())
125
                m_advances.fill(0, size);
126
            m_advances[index] = advance.value();
127
        }
105
    }
128
    }
106
129
107
    const Font& font() const
130
    const Font& font() const
Lines 120-126 private: a/Source/WebCore/platform/graphics/GlyphPage.h_sec7
120
    }
143
    }
121
144
122
    const Font& m_font;
145
    const Font& m_font;
123
    Glyph m_glyphs[size] { };
146
    std::array<Glyph, size> m_glyphs;
147
    Vector<float> m_advances;
124
148
125
    WEBCORE_EXPORT static unsigned s_count;
149
    WEBCORE_EXPORT static unsigned s_count;
126
};
150
};
- a/Source/WebCore/platform/graphics/WidthIterator.cpp -1 / +3 lines
Lines 207-213 inline unsigned WidthIterator::advanceInternal(TextIterator& textIterator, Glyph a/Source/WebCore/platform/graphics/WidthIterator.cpp_sec1
207
        if (character == '\t' && m_run.allowTabs())
207
        if (character == '\t' && m_run.allowTabs())
208
            width = m_font->tabWidth(*font, m_run.tabSize(), m_run.xPos() + m_runWidthSoFar + widthSinceLastRounding);
208
            width = m_font->tabWidth(*font, m_run.tabSize(), m_run.xPos() + m_runWidthSoFar + widthSinceLastRounding);
209
        else {
209
        else {
210
            width = font->widthForGlyph(glyph);
210
            width = glyphData.advance.valueOrCompute([&] {
211
                return font->widthForGlyph(glyph);
212
            });
211
213
212
            // SVG uses horizontalGlyphStretch(), when textLength is used to stretch/squeeze text.
214
            // SVG uses horizontalGlyphStretch(), when textLength is used to stretch/squeeze text.
213
            width *= m_run.horizontalGlyphStretch();
215
            width *= m_run.horizontalGlyphStretch();
- a/Source/WebCore/platform/graphics/cocoa/FontCocoa.mm -35 / +7 lines
Lines 596-639 FloatRect Font::platformBoundsForGlyph(Glyph glyph) const a/Source/WebCore/platform/graphics/cocoa/FontCocoa.mm_sec1
596
    return boundingBox;
596
    return boundingBox;
597
}
597
}
598
598
599
static inline Optional<CGSize> advanceForColorBitmapFont(const FontPlatformData& platformData, Glyph glyph)
600
{
601
    CTFontRef font = platformData.font();
602
    if (!font || !platformData.isColorBitmapFont())
603
        return Nullopt;
604
    CGSize advance;
605
    CTFontGetAdvancesForGlyphs(font, kCTFontOrientationDefault, &glyph, &advance, 1);
606
    return advance;
607
}
608
609
static inline bool canUseFastGlyphAdvanceGetter(const FontPlatformData& platformData, Glyph glyph, CGSize& advance, bool& populatedAdvance)
610
{
611
    if (platformData.isEmoji() || platformData.hasCustomTracking() || platformData.textRenderingMode() == OptimizeLegibility)
612
        return false;
613
    if (auto size = advanceForColorBitmapFont(platformData, glyph)) {
614
        populatedAdvance = true;
615
        advance = size.value();
616
        return false;
617
    }
618
    return true;
619
}
620
621
float Font::platformWidthForGlyph(Glyph glyph) const
599
float Font::platformWidthForGlyph(Glyph glyph) const
622
{
600
{
623
    CGSize advance = CGSizeZero;
601
    CGSize advance = CGSizeZero;
624
    bool horizontal = platformData().orientation() == Horizontal;
602
    auto orientation = platformData().orientation() == Horizontal ? kCTFontOrientationHorizontal : kCTFontOrientationVertical;
625
    bool populatedAdvance = false;
603
#if (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200) || (PLATFORM(IOS) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 100000)
626
    if ((horizontal || m_isBrokenIdeographFallback) && canUseFastGlyphAdvanceGetter(this->platformData(), glyph, advance, populatedAdvance)) {
604
    CGFontRenderingStyle style = kCGFontRenderingStyleAntialiasing | kCGFontRenderingStyleSubpixelPositioning | kCGFontRenderingStyleSubpixelQuantization | kCGFontAntialiasingStyleUnfiltered;
627
        float pointSize = platformData().size();
605
    CTFontGetUnsummedAdvancesForGlyphsAndStyle(m_platformData.ctFont(), orientation, style, &glyph, &advance, 1);
628
        CGAffineTransform m = CGAffineTransformMakeScale(pointSize, pointSize);
606
#else
629
        CGFontRenderingStyle style = kCGFontRenderingStyleAntialiasing | kCGFontRenderingStyleSubpixelPositioning | kCGFontRenderingStyleSubpixelQuantization | kCGFontAntialiasingStyleUnfiltered;
607
    CTFontGetAdvancesForGlyphs(m_platformData.ctFont(), orientation, &glyph, &advance, 1);
630
        if (!CGFontGetGlyphAdvancesForStyle(platformData().cgFont(), &m, style, &glyph, 1, &advance)) {
608
#endif
631
            RetainPtr<CFStringRef> fullName = adoptCF(CGFontCopyFullName(platformData().cgFont()));
632
            LOG_ERROR("Unable to cache glyph widths for %@ %f", fullName.get(), pointSize);
633
            advance.width = 0;
634
        }
635
    } else if (!populatedAdvance && platformData().size())
636
        CTFontGetAdvancesForGlyphs(m_platformData.ctFont(), horizontal ? kCTFontOrientationHorizontal : kCTFontOrientationVertical, &glyph, &advance, 1);
637
609
638
    return advance.width + m_syntheticBoldOffset;
610
    return advance.width + m_syntheticBoldOffset;
639
}
611
}
- a/Source/WebCore/platform/graphics/mac/GlyphPageMac.cpp -12 / +20 lines
Lines 63-78 bool GlyphPage::fill(UChar* buffer, unsigned bufferLength) a/Source/WebCore/platform/graphics/mac/GlyphPageMac.cpp_sec1
63
    ASSERT(bufferLength == GlyphPage::size || bufferLength == 2 * GlyphPage::size);
63
    ASSERT(bufferLength == GlyphPage::size || bufferLength == 2 * GlyphPage::size);
64
64
65
    const Font& font = this->font();
65
    const Font& font = this->font();
66
    Vector<CGGlyph, 512> glyphs(bufferLength);
66
    Vector<CGGlyph> glyphs(bufferLength);
67
    unsigned glyphStep;
67
    memset(glyphs.data(), 0, sizeof(CGGlyph) * bufferLength);
68
    if (!shouldUseCoreText(buffer, bufferLength, font)) {
68
    if (!shouldUseCoreText(buffer, bufferLength, font))
69
        // We pass in either 256 or 512 UTF-16 characters: 256 for U+FFFF and less, 512 (double character surrogates)
70
        // for U+10000 and above. It is indeed possible to get back 512 glyphs back from the API, so the glyph buffer
71
        // we pass in must be 512. If we get back more than 256 glyphs though we'll ignore all the ones after 256,
72
        // this should not happen as the only time we pass in 512 characters is when they are surrogates.
73
        CGFontGetGlyphsForUnichars(font.platformData().cgFont(), buffer, glyphs.data(), bufferLength);
69
        CGFontGetGlyphsForUnichars(font.platformData().cgFont(), buffer, glyphs.data(), bufferLength);
74
        glyphStep = 1;
70
    else {
75
    } else {
76
        // Because we know the implementation of shouldUseCoreText(), if the font isn't for text combine and it isn't a system font,
71
        // Because we know the implementation of shouldUseCoreText(), if the font isn't for text combine and it isn't a system font,
77
        // we know it must have vertical glyphs.
72
        // we know it must have vertical glyphs.
78
        if (font.platformData().isForTextCombine() || font.platformData().isSystemFont())
73
        if (font.platformData().isForTextCombine() || font.platformData().isSystemFont())
Lines 82-94 bool GlyphPage::fill(UChar* buffer, unsigned bufferLength) a/Source/WebCore/platform/graphics/mac/GlyphPageMac.cpp_sec2
82
77
83
        // When buffer consists of surrogate pairs, CTFontGetVerticalGlyphsForCharacters and CTFontGetGlyphsForCharacters
78
        // When buffer consists of surrogate pairs, CTFontGetVerticalGlyphsForCharacters and CTFontGetGlyphsForCharacters
84
        // place the glyphs at indices corresponding to the first character of each pair.
79
        // place the glyphs at indices corresponding to the first character of each pair.
85
        glyphStep = bufferLength / GlyphPage::size;
80
        unsigned glyphStep = bufferLength / GlyphPage::size;
81
        if (glyphStep != 1) {
82
            for (unsigned i = 0; i < GlyphPage::size; ++i)
83
                glyphs[i] = glyphs[i * glyphStep];
84
        }
86
    }
85
    }
87
86
87
    Vector<CGSize> advances(GlyphPage::size);
88
    CTFontOrientation orientation = font.platformData().orientation() == Horizontal ? kCTFontOrientationHorizontal : kCTFontOrientationVertical;
89
#if (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200) || (PLATFORM(IOS) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 100000)
90
    CGFontRenderingStyle style = kCGFontRenderingStyleAntialiasing | kCGFontRenderingStyleSubpixelPositioning | kCGFontRenderingStyleSubpixelQuantization | kCGFontAntialiasingStyleUnfiltered;
91
    CTFontGetUnsummedAdvancesForGlyphsAndStyle(font.platformData().ctFont(), orientation, style, glyphs.data(), advances.data(), GlyphPage::size);
92
#else
93
    CTFontGetAdvancesForGlyphs(font.platformData().ctFont(), orientation, glyphs.data(), advances.data(), GlyphPage::size);
94
#endif
95
88
    bool haveGlyphs = false;
96
    bool haveGlyphs = false;
89
    for (unsigned i = 0; i < GlyphPage::size; ++i) {
97
    for (unsigned i = 0; i < GlyphPage::size; ++i) {
90
        if (glyphs[i * glyphStep]) {
98
        if (glyphs[i]) {
91
            setGlyphForIndex(i, glyphs[i * glyphStep]);
99
            setGlyphForIndex(i, glyphs[i], advances[i].width);
92
            haveGlyphs = true;
100
            haveGlyphs = true;
93
        }
101
        }
94
    }
102
    }

Return to Bug 161119