Changeset 58585 in webkit


Ignore:
Timestamp:
Apr 30, 2010 10:50:39 AM (14 years ago)
Author:
mitz@apple.com
Message:

WebCore: Part of <rdar://problem/6649734> Text repainting does not account for glyphs which draw outside the typographic bounds of the font
https://bugs.webkit.org/show_bug.cgi?id=6274

Reviewed by Adele Peterson.

Account for glyph overflow of characters in the range U+1E00..U+2000, but without sending them
through the complex text code path. Instead, introduce a variant of the fast path that tracks
glyph overflow.

  • platform/graphics/Font.cpp:

(WebCore::Font::drawText): Use codePath().
(WebCore::Font::floatWidth): Use codePath(). Pass the GlyphOverflow pointer through to
floatWidthForSimpleText() if the code path is SimpleWithGlyphOverflow.
(WebCore::Font::selectionRectForText): Use codePath().
(WebCore::Font::offsetForPosition): Ditto.

  • platform/graphics/Font.h: Replaced canUseGlyphCache() with codePath(). Added a GlyphOverflow

parameter to floatWidthForSimpleText().

  • platform/graphics/FontFastPath.cpp:

Removed ROMAN_AND_GREEK_DIACRITICS_CAN_USE_GLYPH_CACHE.
(WebCore::Font::codePath): Renamed canUseGlyphCache() to this. Where it used to return false,
it now returns Complex. Where it used to return true, it now returns Simple, except for
the range U+1E00..U+2000, where it now returns SimpleWithGlyphOverflow.
(WebCore::Font::floatWidthForSimpleText): Added a GlyphOverflow parameter. If not 0, have the
width iterator account for glyph bounds, then update the GlyphOverflow accordingly.

  • platform/graphics/WidthIterator.cpp:

(WebCore::WidthIterator::WidthIterator): Added boolean parameter telling the width iterator
whether to account for glyph bounds. Initialize m_accountForGlyphBounds accordingly. Initialize
m_maxGlyphBoundingBoxY, m_minGlyphBoundingBoxY, m_firstGlyphOverflow and m_lastGlyphOverflow.
(WebCore::WidthIterator::advance): If accounting for glyph bounds, update the above member variables.

  • platform/graphics/WidthIterator.h:

(WebCore::WidthIterator::maxGlyphBoundingBoxY): Added this accessor.
(WebCore::WidthIterator::minGlyphBoundingBoxY): Ditto.
(WebCore::WidthIterator::firstGlyphOverflow): Ditto.
(WebCore::WidthIterator::lastGlyphOverflow): Ditto.

LayoutTests: Updated results for <rdar://problem/6649734> Text repainting does not account for glyphs which draw outside the typographic bounds of the font
https://bugs.webkit.org/show_bug.cgi?id=6274

Reviewed by Adele Peterson.

  • platform/mac/fast/repaint/stacked-diacritics-expected.checksum:
  • platform/mac/fast/repaint/stacked-diacritics-expected.png:
Location:
trunk
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r58584 r58585  
     12010-04-30  Dan Bernstein  <mitz@apple.com>
     2
     3        Reviewed by Adele Peterson.
     4
     5        Updated results for <rdar://problem/6649734> Text repainting does not account for glyphs which draw outside the typographic bounds of the font
     6        https://bugs.webkit.org/show_bug.cgi?id=6274
     7
     8        * platform/mac/fast/repaint/stacked-diacritics-expected.checksum:
     9        * platform/mac/fast/repaint/stacked-diacritics-expected.png:
     10
    1112010-04-30  Chris Marrin  <cmarrin@apple.com>
    212
  • trunk/LayoutTests/platform/mac/fast/repaint/stacked-diacritics-expected.checksum

    r58426 r58585  
    1 214a62226351798b782ad9c839ab900d
     161cab097914525fb7f7a07989330012e
  • trunk/WebCore/ChangeLog

    r58584 r58585  
     12010-04-30  Dan Bernstein  <mitz@apple.com>
     2
     3        Reviewed by Adele Peterson.
     4
     5        Part of <rdar://problem/6649734> Text repainting does not account for glyphs which draw outside the typographic bounds of the font
     6        https://bugs.webkit.org/show_bug.cgi?id=6274
     7
     8        Account for glyph overflow of characters in the range U+1E00..U+2000, but without sending them
     9        through the complex text code path. Instead, introduce a variant of the fast path that tracks
     10        glyph overflow.
     11
     12        * platform/graphics/Font.cpp:
     13        (WebCore::Font::drawText): Use codePath().
     14        (WebCore::Font::floatWidth): Use codePath(). Pass the GlyphOverflow pointer through to
     15        floatWidthForSimpleText() if the code path is SimpleWithGlyphOverflow.
     16        (WebCore::Font::selectionRectForText): Use codePath().
     17        (WebCore::Font::offsetForPosition): Ditto.
     18        * platform/graphics/Font.h: Replaced canUseGlyphCache() with codePath(). Added a GlyphOverflow
     19        parameter to floatWidthForSimpleText().
     20        * platform/graphics/FontFastPath.cpp:
     21        Removed ROMAN_AND_GREEK_DIACRITICS_CAN_USE_GLYPH_CACHE.
     22        (WebCore::Font::codePath): Renamed canUseGlyphCache() to this. Where it used to return false,
     23        it now returns Complex. Where it used to return true, it now returns Simple, except for
     24        the range U+1E00..U+2000, where it now returns SimpleWithGlyphOverflow.
     25        (WebCore::Font::floatWidthForSimpleText): Added a GlyphOverflow parameter. If not 0, have the
     26        width iterator account for glyph bounds, then update the GlyphOverflow accordingly.
     27        * platform/graphics/WidthIterator.cpp:
     28        (WebCore::WidthIterator::WidthIterator): Added boolean parameter telling the width iterator
     29        whether to account for glyph bounds. Initialize m_accountForGlyphBounds accordingly. Initialize
     30        m_maxGlyphBoundingBoxY, m_minGlyphBoundingBoxY, m_firstGlyphOverflow and m_lastGlyphOverflow.
     31        (WebCore::WidthIterator::advance): If accounting for glyph bounds, update the above member variables.
     32        * platform/graphics/WidthIterator.h:
     33        (WebCore::WidthIterator::maxGlyphBoundingBoxY): Added this accessor.
     34        (WebCore::WidthIterator::minGlyphBoundingBoxY): Ditto.
     35        (WebCore::WidthIterator::firstGlyphOverflow): Ditto.
     36        (WebCore::WidthIterator::lastGlyphOverflow): Ditto.
     37
    1382010-04-30  Chris Marrin  <cmarrin@apple.com>
    239
  • trunk/WebCore/platform/graphics/Font.cpp

    r57215 r58585  
    176176
    177177#if USE(FONT_FAST_PATH)
    178     if (canUseGlyphCache(run))
     178    if (codePath(run) != Complex)
    179179        return drawSimpleText(context, run, point, from, to);
    180180#endif
     
    191191
    192192#if USE(FONT_FAST_PATH)
    193     if (canUseGlyphCache(run)) {
     193    CodePath codePathToUse = codePath(run);
     194    if (codePathToUse != Complex) {
    194195        // If the complex text implementation cannot return fallback fonts, avoid
    195196        // returning them for simple text as well.
    196197        static bool returnFallbackFonts = canReturnFallbackFontsForComplexText();
    197         return floatWidthForSimpleText(run, 0, returnFallbackFonts ? fallbackFonts : 0);
     198        return floatWidthForSimpleText(run, 0, returnFallbackFonts ? fallbackFonts : 0, codePathToUse == SimpleWithGlyphOverflow ? glyphOverflow : 0);
    198199    }
    199200#endif
     
    215216
    216217#if USE(FONT_FAST_PATH)
    217     if (canUseGlyphCache(run))
     218    if (codePath(run) != Complex)
    218219        return floatWidthForSimpleText(run, 0);
    219220#endif
     
    232233
    233234#if USE(FONT_FAST_PATH)
    234     if (canUseGlyphCache(run))
     235    if (codePath(run) != Complex)
    235236        return selectionRectForSimpleText(run, point, h, from, to);
    236237#endif
     
    247248
    248249#if USE(FONT_FAST_PATH)
    249     if (canUseGlyphCache(run))
     250    if (codePath(run) != Complex)
    250251        return offsetForPositionForSimpleText(run, x, includePartialGlyphs);
    251252#endif
  • trunk/WebCore/platform/graphics/Font.h

    r58042 r58585  
    151151    static bool shouldUseSmoothing();
    152152
     153#if USE(FONT_FAST_PATH)
     154    enum CodePath { Auto, Simple, Complex, SimpleWithGlyphOverflow };
     155#endif
     156
    153157private:
    154158#if ENABLE(SVG_FONTS)
     
    161165
    162166#if USE(FONT_FAST_PATH)
    163     bool canUseGlyphCache(const TextRun&) const;
     167    CodePath codePath(const TextRun&) const;
    164168    void drawSimpleText(GraphicsContext*, const TextRun&, const FloatPoint&, int from, int to) const;
    165169    void drawGlyphs(GraphicsContext*, const SimpleFontData*, const GlyphBuffer&, int from, int to, const FloatPoint&) const;
    166170    void drawGlyphBuffer(GraphicsContext*, const GlyphBuffer&, const TextRun&, const FloatPoint&) const;
    167     float floatWidthForSimpleText(const TextRun&, GlyphBuffer*, HashSet<const SimpleFontData*>* fallbackFonts = 0) const;
     171    float floatWidthForSimpleText(const TextRun&, GlyphBuffer*, HashSet<const SimpleFontData*>* fallbackFonts = 0, GlyphOverflow* = 0) const;
    168172    int offsetForPositionForSimpleText(const TextRun&, int position, bool includePartialGlyphs) const;
    169173    FloatRect selectionRectForSimpleText(const TextRun&, const IntPoint&, int h, int from, int to) const;
     
    182186    // Useful for debugging the different font rendering code paths.
    183187#if USE(FONT_FAST_PATH)
    184     enum CodePath { Auto, Simple, Complex };
    185188    static void setCodePath(CodePath);
    186189    static CodePath codePath();
  • trunk/WebCore/platform/graphics/FontFastPath.cpp

    r58426 r58585  
    3737#include <wtf/unicode/Unicode.h>
    3838
    39 #ifndef ROMAN_AND_GREEK_DIACRITICS_CAN_USE_GLYPH_CACHE
    40 #define ROMAN_AND_GREEK_DIACRITICS_CAN_USE_GLYPH_CACHE 1
    41 #endif
    42 
    4339using namespace WTF;
    4440using namespace Unicode;
     
    195191}
    196192
    197 bool Font::canUseGlyphCache(const TextRun& run) const
    198 {
    199     switch (s_codePath) {
    200         case Auto:
    201             break;
    202         case Simple:
    203             return true;
    204         case Complex:
    205             return false;
    206     }
    207    
     193Font::CodePath Font::codePath(const TextRun& run) const
     194{
     195    if (s_codePath != Auto)
     196        return s_codePath;
     197
    208198    // Start from 0 since drawing and highlighting also measure the characters before run->from
    209199    for (int i = 0; i < run.length(); i++) {
     
    212202            continue;
    213203        if (c <= 0x36F)
    214             return false;
     204            return Complex;
    215205
    216206        if (c < 0x0591 || c == 0x05BE)     // U+0591 through U+05CF excluding U+05BE Hebrew combining marks, Hebrew punctuation Paseq, Sof Pasuq and Nun Hafukha
    217207            continue;
    218208        if (c <= 0x05CF)
    219             return false;
     209            return Complex;
    220210
    221211        if (c < 0x0600)     // U+0600 through U+1059 Arabic, Syriac, Thaana, Devanagari, Bengali, Gurmukhi, Gujarati, Oriya, Tamil, Telugu, Kannada, Malayalam, Sinhala, Thai, Lao, Tibetan, Myanmar
    222212            continue;
    223213        if (c <= 0x1059)
    224             return false;
     214            return Complex;
    225215
    226216        if (c < 0x1100)     // U+1100 through U+11FF Hangul Jamo (only Ancient Korean should be left here if you precompose; Modern Korean will be precomposed as a result of step A)
    227217            continue;
    228218        if (c <= 0x11FF)
    229             return false;
     219            return Complex;
    230220
    231221        if (c < 0x1780)     // U+1780 through U+18AF Khmer, Mongolian
    232222            continue;
    233223        if (c <= 0x18AF)
    234             return false;
     224            return Complex;
    235225
    236226        if (c < 0x1900)     // U+1900 through U+194F Limbu (Unicode 4.0)
    237227            continue;
    238228        if (c <= 0x194F)
    239             return false;
    240 
    241 #if !ROMAN_AND_GREEK_DIACRITICS_CAN_USE_GLYPH_CACHE
    242         // FIXME: we should not use complex text path for these characters.
     229            return Complex;
     230
    243231        if (c < 0x1E00)     // U+1E00 through U+2000 characters with diacritics and stacked diacritics
    244232            continue;
    245233        if (c <= 0x2000)
    246             return false;
    247 #endif
     234            return SimpleWithGlyphOverflow;
    248235
    249236        if (c < 0x20D0)     // U+20D0 through U+20FF Combining marks for symbols
    250237            continue;
    251238        if (c <= 0x20FF)
    252             return false;
     239            return Complex;
    253240
    254241        if (c < 0xFE20)     // U+FE20 through U+FE2F Combining half marks
    255242            continue;
    256243        if (c <= 0xFE2F)
    257             return false;
     244            return Complex;
    258245    }
    259246
    260247    if (typesettingFeatures())
    261         return false;
    262 
    263     return true;
    264 
     248        return Complex;
     249
     250    return Simple;
    265251}
    266252
     
    327313}
    328314
    329 float Font::floatWidthForSimpleText(const TextRun& run, GlyphBuffer* glyphBuffer, HashSet<const SimpleFontData*>* fallbackFonts) const
    330 {
    331     WidthIterator it(this, run, fallbackFonts);
     315float Font::floatWidthForSimpleText(const TextRun& run, GlyphBuffer* glyphBuffer, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
     316{
     317    WidthIterator it(this, run, fallbackFonts, glyphOverflow);
    332318    it.advance(run.length(), glyphBuffer);
     319
     320    if (glyphOverflow) {
     321        glyphOverflow->top = max<int>(glyphOverflow->top, ceilf(-it.minGlyphBoundingBoxY()) - ascent());
     322        glyphOverflow->bottom = max<int>(glyphOverflow->bottom, ceilf(it.maxGlyphBoundingBoxY()) - descent());
     323        glyphOverflow->left = ceilf(it.firstGlyphOverflow());
     324        glyphOverflow->right = ceilf(it.lastGlyphOverflow());
     325    }
     326
    333327    return it.m_runWidthSoFar;
    334328}
  • trunk/WebCore/platform/graphics/WidthIterator.cpp

    r44439 r58585  
    3434using namespace WTF;
    3535using namespace Unicode;
     36using namespace std;
    3637
    3738namespace WebCore {
     
    4041static const uint8_t hiraganaKatakanaVoicingMarksCombiningClass = 8;
    4142
    42 WidthIterator::WidthIterator(const Font* font, const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts)
     43WidthIterator::WidthIterator(const Font* font, const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts, bool accountForGlyphBounds)
    4344    : m_font(font)
    4445    , m_run(run)
     
    4849    , m_finalRoundingWidth(0)
    4950    , m_fallbackFonts(fallbackFonts)
     51    , m_accountForGlyphBounds(accountForGlyphBounds)
     52    , m_maxGlyphBoundingBoxY(numeric_limits<float>::min())
     53    , m_minGlyphBoundingBoxY(numeric_limits<float>::max())
     54    , m_firstGlyphOverflow(0)
     55    , m_lastGlyphOverflow(0)
    5056{
    5157    // If the padding is non-zero, count the number of spaces in the run
     
    8086    float runWidthSoFar = m_runWidthSoFar;
    8187    float lastRoundingWidth = m_finalRoundingWidth;
     88    FloatRect bounds;
    8289
    8390    const SimpleFontData* primaryFont = m_font->primaryFont();
     
    176183        }
    177184
     185        if (m_accountForGlyphBounds) {
     186            bounds = fontData->boundsForGlyph(glyph);
     187            if (!currentCharacter)
     188                m_firstGlyphOverflow = max<float>(0, -bounds.x());
     189        }
     190
    178191        // Advance past the character we just dealt with.
    179192        cp += clusterLength;
     
    206219
    207220        lastRoundingWidth = width - oldWidth;
     221
     222        if (m_accountForGlyphBounds) {
     223            m_maxGlyphBoundingBoxY = max(m_maxGlyphBoundingBoxY, bounds.bottom());
     224            m_minGlyphBoundingBoxY = min(m_minGlyphBoundingBoxY, bounds.y());
     225            m_lastGlyphOverflow = max<float>(0, bounds.right() - width);
     226        }
    208227    }
    209228
  • trunk/WebCore/platform/graphics/WidthIterator.h

    r42379 r58585  
    3434
    3535struct WidthIterator {
    36     WidthIterator(const Font*, const TextRun&, HashSet<const SimpleFontData*>* fallbackFonts = 0);
     36    WidthIterator(const Font*, const TextRun&, HashSet<const SimpleFontData*>* fallbackFonts = 0, bool accountForGlyphBounds = false);
    3737
    3838    void advance(int to, GlyphBuffer* = 0);
    3939    bool advanceOneCharacter(float& width, GlyphBuffer* = 0);
     40
     41    float maxGlyphBoundingBoxY() const { ASSERT(m_accountForGlyphBounds); return m_maxGlyphBoundingBoxY; }
     42    float minGlyphBoundingBoxY() const { ASSERT(m_accountForGlyphBounds); return m_minGlyphBoundingBoxY; }
     43    float firstGlyphOverflow() const { ASSERT(m_accountForGlyphBounds); return m_firstGlyphOverflow; }
     44    float lastGlyphOverflow() const { ASSERT(m_accountForGlyphBounds); return m_lastGlyphOverflow; }
    4045
    4146    const Font* m_font;
     
    5257private:
    5358    UChar32 normalizeVoicingMarks(int currentCharacter);
     59
    5460    HashSet<const SimpleFontData*>* m_fallbackFonts;
     61    bool m_accountForGlyphBounds;
     62    float m_maxGlyphBoundingBoxY;
     63    float m_minGlyphBoundingBoxY;
     64    float m_firstGlyphOverflow;
     65    float m_lastGlyphOverflow;
    5566};
    5667
Note: See TracChangeset for help on using the changeset viewer.