Changeset 70266 in webkit
- Timestamp:
- Oct 21, 2010 2:43:16 PM (14 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r70265 r70266 1 2010-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 1 16 2010-10-21 Adam Roben <aroben@apple.com> 2 17 -
trunk/WebCore/ChangeLog
r70263 r70266 1 2010-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 1 21 2010-10-21 David Hyatt <hyatt@apple.com> 2 22 -
trunk/WebCore/platform/graphics/chromium/FontLinux.cpp
r69972 r70266 1 1 /* 2 * Copyright (c) 2007, 2008, Google Inc. All rights reserved.2 * Copyright (c) 2007, 2008, 2010 Google Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 221 221 222 222 private: 223 const TextRun& getTextRun(const TextRun&);224 const TextRun& getNormalizedTextRun(const TextRun&);225 223 void setupFontForScriptRun(); 226 224 HB_FontRec* allocHarfbuzzFont(); … … 230 228 void shapeGlyphs(); 231 229 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); 233 233 234 234 // This matches the logic in RenderBlock::findNextLineBreak … … 265 265 , m_startingX(startingX) 266 266 , m_offsetX(m_startingX) 267 , m_run(get TextRun(run))267 , m_run(getNormalizedTextRun(run, m_normalizedRun, m_normalizedBuffer)) 268 268 , m_iterateBackwards(m_run.rtl()) 269 269 , m_wordSpacingAdjustment(0) 270 270 , m_padding(0) 271 , m_padPerWordBreak(0) 271 272 , m_padError(0) 273 , m_letterSpacing(0) 272 274 { 273 275 // Do not use |run| inside this constructor. Use |m_run| instead. … … 287 289 m_item.item.bidiLevel = m_run.rtl(); 288 290 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(); 300 293 301 294 reset(); … … 307 300 deleteGlyphArrays(); 308 301 delete[] m_item.log_clusters; 309 if (m_item.item.bidiLevel)310 delete[] m_item.string;311 302 } 312 303 … … 407 398 408 399 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 marks415 // (U+0300..) are used in the run. This conversion is necessary since most OpenType416 // fonts (e.g., Arial) don't have substitution rules for the diacritical marks in417 // their GSUB tables.418 //419 // Note that we don't use the icu::Normalizer::isNormalized(UNORM_NFC) API here since420 // the API returns FALSE (= not normalized) for complex runs that don't require NFC421 // 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 glyphs424 // 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;454 400 } 455 401 … … 596 542 } 597 543 598 void TextRunWalker:: mirrorCharacters(UChar* destination, const UChar* source, int length) const544 void TextRunWalker::normalizeSpacesAndMirrorChars(const UChar* source, bool rtl, UChar* destination, int length) 599 545 { 600 546 int position = 0; … … 605 551 int nextPosition = position; 606 552 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); 608 557 U16_APPEND(destination, position, length, character, error); 609 558 ASSERT(!error); 610 559 position = nextPosition; 611 560 } 561 } 562 563 const 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; 612 613 } 613 614
Note: See TracChangeset
for help on using the changeset viewer.