Changeset 70266 in webkit


Ignore:
Timestamp:
Oct 21, 2010 2:43:16 PM (13 years ago)
Author:
xji@chromium.org
Message:

2010-10-21 Xiaomei Ji <xji@chromium.org>

Reviewed by David Levin.

Performance improvement for FontLinux.
https://bugs.webkit.org/show_bug.cgi?id=47019


Reduce the number of calls for the normalization function because converting
to NFC form is very expensive.


Combine space normalization and character mirroring into one text scan.

Test: platform/chromium/fast/text/font-linux-normalize.html

  • platform/graphics/chromium/FontLinux.cpp: (WebCore::TextRunWalker::TextRunWalker): (WebCore::TextRunWalker::~TextRunWalker): (WebCore::TextRunWalker::getNormalizedTextRun): (WebCore::TextRunWalker::normalizeSpacesAndMirrorChars):

2010-10-21 Xiaomei Ji <xji@chromium.org>

Reviewed by David Levin.

Performance improvement for FontLinux.
https://bugs.webkit.org/show_bug.cgi?id=47019


Reduce the number of calls for the normalization function because converting
to NFC form is very expensive.


Combine space normalization and character mirroring into one text scan.

  • platform/chromium/fast/text/font-linux-normalize-expected.txt: Added.
  • platform/chromium/fast/text/font-linux-normalize.html: Added.
Location:
trunk
Files:
2 added
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r70265 r70266  
     12010-10-21  Xiaomei Ji  <xji@chromium.org>
     2
     3        Reviewed by David Levin.
     4
     5        Performance improvement for FontLinux.
     6        https://bugs.webkit.org/show_bug.cgi?id=47019
     7       
     8        Reduce the number of calls for the normalization function because converting
     9        to NFC form is very expensive.
     10   
     11        Combine space normalization and character mirroring into one text scan.
     12
     13        * platform/chromium/fast/text/font-linux-normalize-expected.txt: Added.
     14        * platform/chromium/fast/text/font-linux-normalize.html: Added.
     15
    1162010-10-21  Adam Roben  <aroben@apple.com>
    217
  • trunk/WebCore/ChangeLog

    r70263 r70266  
     12010-10-21  Xiaomei Ji  <xji@chromium.org>
     2
     3        Reviewed by David Levin.
     4
     5        Performance improvement for FontLinux.
     6        https://bugs.webkit.org/show_bug.cgi?id=47019
     7       
     8        Reduce the number of calls for the normalization function because converting
     9        to NFC form is very expensive.
     10   
     11        Combine space normalization and character mirroring into one text scan.
     12
     13        Test: platform/chromium/fast/text/font-linux-normalize.html
     14
     15        * platform/graphics/chromium/FontLinux.cpp:
     16        (WebCore::TextRunWalker::TextRunWalker):
     17        (WebCore::TextRunWalker::~TextRunWalker):
     18        (WebCore::TextRunWalker::getNormalizedTextRun):
     19        (WebCore::TextRunWalker::normalizeSpacesAndMirrorChars):
     20
    1212010-10-21  David Hyatt  <hyatt@apple.com>
    222
  • trunk/WebCore/platform/graphics/chromium/FontLinux.cpp

    r69972 r70266  
    11/*
    2  * Copyright (c) 2007, 2008, Google Inc. All rights reserved.
     2 * Copyright (c) 2007, 2008, 2010 Google Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    221221
    222222private:
    223     const TextRun& getTextRun(const TextRun&);
    224     const TextRun& getNormalizedTextRun(const TextRun&);
    225223    void setupFontForScriptRun();
    226224    HB_FontRec* allocHarfbuzzFont();
     
    230228    void shapeGlyphs();
    231229    void setGlyphXPositions(bool);
    232     void mirrorCharacters(UChar*, const UChar*, int) const;
     230
     231    static void normalizeSpacesAndMirrorChars(const UChar* source, bool rtl, UChar* destination, int length);
     232    static const TextRun& getNormalizedTextRun(const TextRun& originalRun, OwnPtr<TextRun>& normalizedRun, OwnArrayPtr<UChar>& normalizedBuffer);
    233233
    234234    // This matches the logic in RenderBlock::findNextLineBreak
     
    265265    , m_startingX(startingX)
    266266    , m_offsetX(m_startingX)
    267     , m_run(getTextRun(run))
     267    , m_run(getNormalizedTextRun(run, m_normalizedRun, m_normalizedBuffer))
    268268    , m_iterateBackwards(m_run.rtl())
    269269    , m_wordSpacingAdjustment(0)
    270270    , m_padding(0)
     271    , m_padPerWordBreak(0)
    271272    , m_padError(0)
     273    , m_letterSpacing(0)
    272274{
    273275    // Do not use |run| inside this constructor. Use |m_run| instead.
     
    287289    m_item.item.bidiLevel = m_run.rtl();
    288290
    289     int length = m_run.length();
    290     m_item.stringLength = length;
    291 
    292     if (!m_item.item.bidiLevel)
    293         m_item.string = m_run.characters();
    294     else {
    295         // Assume mirrored character is in the same Unicode multilingual plane as the original one.
    296         UChar* string = new UChar[length];
    297         mirrorCharacters(string, m_run.characters(), length);
    298         m_item.string = string;
    299     }
     291    m_item.string = m_run.characters();
     292    m_item.stringLength = m_run.length();
    300293
    301294    reset();
     
    307300    deleteGlyphArrays();
    308301    delete[] m_item.log_clusters;
    309     if (m_item.item.bidiLevel)
    310         delete[] m_item.string;
    311302}
    312303
     
    407398
    408399    return widthSum;
    409 }
    410 
    411 const TextRun& TextRunWalker::getTextRun(const TextRun& originalRun)
    412 {
    413     // Normalize the text run in two ways:
    414     // 1) Convert the |originalRun| to NFC normalized form if combining diacritical marks
    415     // (U+0300..) are used in the run. This conversion is necessary since most OpenType
    416     // fonts (e.g., Arial) don't have substitution rules for the diacritical marks in
    417     // their GSUB tables.
    418     //
    419     // Note that we don't use the icu::Normalizer::isNormalized(UNORM_NFC) API here since
    420     // the API returns FALSE (= not normalized) for complex runs that don't require NFC
    421     // normalization (e.g., Arabic text). Unless the run contains the diacritical marks,
    422     // Harfbuzz will do the same thing for us using the GSUB table.
    423     // 2) Convert spacing characters into plain spaces, as some fonts will provide glyphs
    424     // for characters like '\n' otherwise.
    425     for (int i = 0; i < originalRun.length(); ++i) {
    426         UChar ch = originalRun[i];
    427         UBlockCode block = ::ublock_getCode(ch);
    428         if (block == UBLOCK_COMBINING_DIACRITICAL_MARKS || (Font::treatAsSpace(ch) && ch != ' '))
    429             return getNormalizedTextRun(originalRun);
    430     }
    431     return originalRun;
    432 }
    433 
    434 const TextRun& TextRunWalker::getNormalizedTextRun(const TextRun& originalRun)
    435 {
    436     icu::UnicodeString normalizedString;
    437     UErrorCode error = U_ZERO_ERROR;
    438     icu::Normalizer::normalize(icu::UnicodeString(originalRun.characters(), originalRun.length()), UNORM_NFC, 0 /* no options */, normalizedString, error);
    439     if (U_FAILURE(error))
    440         return originalRun;
    441 
    442     m_normalizedBuffer.set(new UChar[normalizedString.length() + 1]);
    443     normalizedString.extract(m_normalizedBuffer.get(), normalizedString.length() + 1, error);
    444     ASSERT(U_SUCCESS(error));
    445 
    446     for (int i = 0; i < normalizedString.length(); ++i) {
    447         if (Font::treatAsSpace(m_normalizedBuffer[i]))
    448             m_normalizedBuffer[i] = ' ';
    449     }
    450 
    451     m_normalizedRun.set(new TextRun(originalRun));
    452     m_normalizedRun->setText(m_normalizedBuffer.get(), normalizedString.length());
    453     return *m_normalizedRun;
    454400}
    455401
     
    596542}
    597543
    598 void TextRunWalker::mirrorCharacters(UChar* destination, const UChar* source, int length) const
     544void TextRunWalker::normalizeSpacesAndMirrorChars(const UChar* source, bool rtl, UChar* destination, int length)
    599545{
    600546    int position = 0;
     
    605551        int nextPosition = position;
    606552        U16_NEXT(source, nextPosition, length, character);
    607         character = u_charMirror(character);
     553        if (Font::treatAsSpace(character))
     554            character = ' ';
     555        else if (rtl)
     556            character = u_charMirror(character);
    608557        U16_APPEND(destination, position, length, character, error);
    609558        ASSERT(!error);
    610559        position = nextPosition;
    611560    }
     561}
     562
     563const TextRun& TextRunWalker::getNormalizedTextRun(const TextRun& originalRun, OwnPtr<TextRun>& normalizedRun, OwnArrayPtr<UChar>& normalizedBuffer)
     564{
     565    // Normalize the text run in three ways:
     566    // 1) Convert the |originalRun| to NFC normalized form if combining diacritical marks
     567    // (U+0300..) are used in the run. This conversion is necessary since most OpenType
     568    // fonts (e.g., Arial) don't have substitution rules for the diacritical marks in
     569    // their GSUB tables.
     570    //
     571    // Note that we don't use the icu::Normalizer::isNormalized(UNORM_NFC) API here since
     572    // the API returns FALSE (= not normalized) for complex runs that don't require NFC
     573    // normalization (e.g., Arabic text). Unless the run contains the diacritical marks,
     574    // Harfbuzz will do the same thing for us using the GSUB table.
     575    // 2) Convert spacing characters into plain spaces, as some fonts will provide glyphs
     576    // for characters like '\n' otherwise.
     577    // 3) Convert mirrored characters such as parenthesis for rtl text.
     578 
     579    // Convert to NFC form if the text has diacritical marks.
     580    icu::UnicodeString normalizedString;
     581    UErrorCode error = U_ZERO_ERROR;
     582
     583    for (int16_t i = 0; i < originalRun.length(); ++i) {
     584        UChar ch = originalRun[i];
     585        if (::ublock_getCode(ch) == UBLOCK_COMBINING_DIACRITICAL_MARKS) {
     586            icu::Normalizer::normalize(icu::UnicodeString(originalRun.characters(),
     587                                       originalRun.length()), UNORM_NFC, 0 /* no options */,
     588                                       normalizedString, error);
     589            if (U_FAILURE(error))
     590                return originalRun;
     591            break;
     592        }
     593    }
     594
     595    // Normalize space and mirror parenthesis for rtl text.
     596    int normalizedBufferLength;
     597    const UChar* sourceText;
     598    if (normalizedString.isEmpty()) {
     599        normalizedBufferLength = originalRun.length();
     600        sourceText = originalRun.characters();
     601    } else {
     602        normalizedBufferLength = normalizedString.length();
     603        sourceText = normalizedString.getBuffer();
     604    }
     605
     606    normalizedBuffer.set(new UChar[normalizedBufferLength + 1]);
     607
     608    normalizeSpacesAndMirrorChars(sourceText, originalRun.rtl(), normalizedBuffer.get(), normalizedBufferLength);
     609
     610    normalizedRun.set(new TextRun(originalRun));
     611    normalizedRun->setText(normalizedBuffer.get(), normalizedBufferLength);
     612    return *normalizedRun;
    612613}
    613614
Note: See TracChangeset for help on using the changeset viewer.