Changeset 151327 in webkit
- Timestamp:
- Jun 7, 2013, 10:59:01 AM (12 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r151325 r151327 1 2013-06-07 Ryosuke Niwa <rniwa@webkit.org> 2 3 REGRESSION: Lines jump up and down while typing Chinese or Japanese 4 https://bugs.webkit.org/show_bug.cgi?id=115931 5 6 Reviewed by Darin Adler. 7 8 The bug was caused by Font::width caching the width of text even when the font fallbacks existed when fallbackFonts 9 argument was null; because of this, a later call to Font::width was returning the width without filling up 10 fallbackFonts even if it was not null this time. 11 12 Fixed the bug by adding a local fallback fonts hash set, and checking the emptiness of this variable in Font::width. 13 Also added pass fallbackFonts around in various places to make use of the cached font fallbacks. 14 15 No new tests. Unfortunately I haven't been able to make a reliable reduction for this bug. 16 17 * platform/graphics/Font.cpp: 18 (WebCore::Font::width): 19 * rendering/RenderBlockLineLayout.cpp: 20 (WebCore::measureHyphenWidth): 21 (WebCore::setLogicalWidthForTextRun): 22 (WebCore::textWidth): 23 (WebCore::tryHyphenating): 24 (WebCore::RenderBlock::LineBreaker::nextSegmentBreak): 25 * rendering/RenderText.cpp: 26 (WebCore::maxWordFragmentWidth): 27 (WebCore::RenderText::computePreferredLogicalWidths): 28 1 29 2013-06-07 Zan Dobersek <zdobersek@igalia.com> 2 30 -
trunk/Source/WebCore/platform/graphics/Font.cpp
r150897 r151327 313 313 return *cacheEntry; 314 314 315 HashSet<const SimpleFontData*> localFallbackFonts; 316 if (!fallbackFonts) 317 fallbackFonts = &localFallbackFonts; 318 315 319 float result; 316 320 if (codePathToUse == Complex) … … 319 323 result = floatWidthForSimpleText(run, fallbackFonts, glyphOverflow); 320 324 321 if (cacheEntry && (!fallbackFonts || fallbackFonts->isEmpty()))325 if (cacheEntry && fallbackFonts->isEmpty()) 322 326 *cacheEntry = result; 323 327 return result; -
trunk/Source/WebCore/rendering/RenderBlockLineLayout.cpp
r151295 r151327 807 807 } 808 808 809 static inline float measureHyphenWidth(RenderText* renderer, const Font& font )809 static inline float measureHyphenWidth(RenderText* renderer, const Font& font, HashSet<const SimpleFontData*>* fallbackFonts = 0) 810 810 { 811 811 RenderStyle* style = renderer->style(); 812 return font.width(RenderBlock::constructTextRun(renderer, font, style->hyphenString().string(), style) );812 return font.width(RenderBlock::constructTextRun(renderer, font, style->hyphenString().string(), style), fallbackFonts); 813 813 } 814 814 … … 831 831 832 832 static inline void setLogicalWidthForTextRun(RootInlineBox* lineBox, BidiRun* run, RenderText* renderer, float xPos, const LineInfo& lineInfo, 833 833 GlyphOverflowAndFallbackFontsMap& textBoxDataMap, VerticalPositionCache& verticalPositionCache, WordMeasurements& wordMeasurements) 834 834 { 835 835 HashSet<const SimpleFontData*> fallbackFonts; … … 854 854 if (toInlineTextBox(run->m_box)->hasHyphen()) { 855 855 const Font& font = renderer->style(lineInfo.isFirstLine())->font(); 856 hyphenWidth = measureHyphenWidth(renderer, font );856 hyphenWidth = measureHyphenWidth(renderer, font, &fallbackFonts); 857 857 } 858 858 float measuredWidth = 0; … … 867 867 int lastEndOffset = run->m_start; 868 868 for (size_t i = 0, size = wordMeasurements.size(); i < size && lastEndOffset < run->m_stop; ++i) { 869 constWordMeasurement& wordMeasurement = wordMeasurements[i];870 if (wordMeasurement.width <= 0 || wordMeasurement.startOffset == wordMeasurement.endOffset)869 WordMeasurement& wordMeasurement = wordMeasurements[i]; 870 if (wordMeasurement.width <= 0 || wordMeasurement.startOffset == wordMeasurement.endOffset) 871 871 continue; 872 872 if (wordMeasurement.renderer != renderer || wordMeasurement.startOffset != lastEndOffset || wordMeasurement.endOffset > run->m_stop) … … 876 876 if (kerningIsEnabled && lastEndOffset == run->m_stop) { 877 877 int wordLength = lastEndOffset - wordMeasurement.startOffset; 878 measuredWidth += renderer->width(wordMeasurement.startOffset, wordLength, xPos + measuredWidth, lineInfo.isFirstLine()); 878 GlyphOverflow overflow; 879 measuredWidth += renderer->width(wordMeasurement.startOffset, wordLength, xPos + measuredWidth, lineInfo.isFirstLine(), 880 &wordMeasurement.fallbackFonts, &overflow); 879 881 UChar c = renderer->characterAt(wordMeasurement.startOffset); 880 882 if (i > 0 && wordLength == 1 && (c == ' ' || c == '\t')) … … 2561 2563 } 2562 2564 2563 static ALWAYS_INLINE float textWidth(RenderText* text, unsigned from, unsigned len, const Font& font, float xPos, bool isFixedPitch, bool collapseWhiteSpace, HashSet<const SimpleFontData*> * fallbackFonts = 0, TextLayout* layout = 0)2565 static ALWAYS_INLINE float textWidth(RenderText* text, unsigned from, unsigned len, const Font& font, float xPos, bool isFixedPitch, bool collapseWhiteSpace, HashSet<const SimpleFontData*>& fallbackFonts, TextLayout* layout = 0) 2564 2566 { 2565 2567 GlyphOverflow glyphOverflow; 2566 2568 if (isFixedPitch || (!from && len == text->textLength()) || text->style()->hasTextCombine()) 2567 return text->width(from, len, font, xPos, fallbackFonts, &glyphOverflow);2569 return text->width(from, len, font, xPos, &fallbackFonts, &glyphOverflow); 2568 2570 2569 2571 if (layout) 2570 return Font::width(*layout, from, len, fallbackFonts);2572 return Font::width(*layout, from, len, &fallbackFonts); 2571 2573 2572 2574 TextRun run = RenderBlock::constructTextRun(text, font, text, from, len, text->style()); … … 2577 2579 run.setTabSize(!collapseWhiteSpace, text->style()->tabSize()); 2578 2580 run.setXPos(xPos); 2579 return font.width(run, fallbackFonts, &glyphOverflow);2581 return font.width(run, &fallbackFonts, &glyphOverflow); 2580 2582 } 2581 2583 … … 2636 2638 2637 2639 #if !ASSERT_DISABLED 2638 float prefixWidth = hyphenWidth + textWidth(text, lastSpace, prefixLength, font, xPos, isFixedPitch, collapseWhiteSpace) + lastSpaceWordSpacing; 2640 HashSet<const SimpleFontData*> fallbackFonts; 2641 float prefixWidth = hyphenWidth + textWidth(text, lastSpace, prefixLength, font, xPos, isFixedPitch, collapseWhiteSpace, fallbackFonts) + lastSpaceWordSpacing; 2639 2642 ASSERT(xPos + prefixWidth <= availableWidth); 2640 2643 #else … … 3079 3082 // Non-zero only when kerning is enabled and TextLayout isn't used, in which case we measure 3080 3083 // words with their trailing space, then subtract its width. 3081 float wordTrailingSpaceWidth = (f.typesettingFeatures() & Kerning) && !textLayout ? f.width(constructTextRun(t, f, &space, 1, style)) + wordSpacing : 0; 3084 HashSet<const SimpleFontData*> fallbackFonts; 3085 float wordTrailingSpaceWidth = (f.typesettingFeatures() & Kerning) && !textLayout ? f.width(constructTextRun(t, f, &space, 1, style), &fallbackFonts) + wordSpacing : 0; 3082 3086 3083 3087 UChar lastCharacter = renderTextInfo.m_lineBreakIterator.lastCharacter(); … … 3093 3097 3094 3098 if (c == softHyphen && autoWrap && !hyphenWidth && style->hyphens() != HyphensNone) { 3095 hyphenWidth = measureHyphenWidth(t, f );3099 hyphenWidth = measureHyphenWidth(t, f, &fallbackFonts); 3096 3100 width.addUncommittedWidth(hyphenWidth); 3097 3101 } … … 3104 3108 wrapW += charWidth; 3105 3109 bool midWordBreakIsBeforeSurrogatePair = U16_IS_LEAD(c) && current.m_pos + 1 < t->textLength() && U16_IS_TRAIL(t->characters()[current.m_pos + 1]); 3106 charWidth = textWidth(t, current.m_pos, midWordBreakIsBeforeSurrogatePair ? 2 : 1, f, width.committedWidth() + wrapW, isFixedPitch, collapseWhiteSpace, 0, textLayout);3110 charWidth = textWidth(t, current.m_pos, midWordBreakIsBeforeSurrogatePair ? 2 : 1, f, width.committedWidth() + wrapW, isFixedPitch, collapseWhiteSpace, fallbackFonts, textLayout); 3107 3111 midWordBreak = width.committedWidth() + wrapW + charWidth > width.availableWidth(); 3108 3112 } … … 3138 3142 float additionalTempWidth; 3139 3143 if (wordTrailingSpaceWidth && c == ' ') 3140 additionalTempWidth = textWidth(t, lastSpace, current.m_pos + 1 - lastSpace, f, width.currentWidth(), isFixedPitch, collapseWhiteSpace, &wordMeasurement.fallbackFonts, textLayout) - wordTrailingSpaceWidth;3144 additionalTempWidth = textWidth(t, lastSpace, current.m_pos + 1 - lastSpace, f, width.currentWidth(), isFixedPitch, collapseWhiteSpace, wordMeasurement.fallbackFonts, textLayout) - wordTrailingSpaceWidth; 3141 3145 else 3142 additionalTempWidth = textWidth(t, lastSpace, current.m_pos - lastSpace, f, width.currentWidth(), isFixedPitch, collapseWhiteSpace, &wordMeasurement.fallbackFonts, textLayout); 3146 additionalTempWidth = textWidth(t, lastSpace, current.m_pos - lastSpace, f, width.currentWidth(), isFixedPitch, collapseWhiteSpace, wordMeasurement.fallbackFonts, textLayout); 3147 3148 if (wordMeasurement.fallbackFonts.isEmpty() && !fallbackFonts.isEmpty()) 3149 wordMeasurement.fallbackFonts.swap(fallbackFonts); 3150 fallbackFonts.clear(); 3143 3151 3144 3152 wordMeasurement.width = additionalTempWidth + wordSpacingForWordMeasurement; … … 3164 3172 bool lineWasTooWide = false; 3165 3173 if (width.fitsOnLine() && currentCharacterIsWS && currentStyle->breakOnlyAfterWhiteSpace() && !midWordBreak) { 3166 float charWidth = textWidth(t, current.m_pos, 1, f, width.currentWidth(), isFixedPitch, collapseWhiteSpace, &wordMeasurement.fallbackFonts, textLayout) + (applyWordSpacing ? wordSpacing : 0);3174 float charWidth = textWidth(t, current.m_pos, 1, f, width.currentWidth(), isFixedPitch, collapseWhiteSpace, wordMeasurement.fallbackFonts, textLayout) + (applyWordSpacing ? wordSpacing : 0); 3167 3175 // Check if line is too big even without the extra space 3168 3176 // at the end of the line. If it is not, do nothing. … … 3302 3310 3303 3311 // IMPORTANT: current.m_pos is > length here! 3304 float additionalTempWidth = ignoringSpaces ? 0 : textWidth(t, lastSpace, current.m_pos - lastSpace, f, width.currentWidth(), isFixedPitch, collapseWhiteSpace, &wordMeasurement.fallbackFonts, textLayout);3312 float additionalTempWidth = ignoringSpaces ? 0 : textWidth(t, lastSpace, current.m_pos - lastSpace, f, width.currentWidth(), isFixedPitch, collapseWhiteSpace, wordMeasurement.fallbackFonts, textLayout); 3305 3313 wordMeasurement.startOffset = lastSpace; 3306 3314 wordMeasurement.endOffset = current.m_pos; … … 3310 3318 float inlineLogicalTempWidth = inlineLogicalWidth(current.m_obj, !appliedStartWidth, includeEndWidth); 3311 3319 width.addUncommittedWidth(additionalTempWidth + inlineLogicalTempWidth); 3320 3321 if (wordMeasurement.fallbackFonts.isEmpty() && !fallbackFonts.isEmpty()) 3322 wordMeasurement.fallbackFonts.swap(fallbackFonts); 3323 fallbackFonts.clear(); 3312 3324 3313 3325 if (collapseWhiteSpace && currentCharacterIsSpace && additionalTempWidth) -
trunk/Source/WebCore/rendering/RenderText.cpp
r150922 r151327 894 894 } 895 895 896 static float maxWordFragmentWidth(RenderText* renderer, RenderStyle* style, const Font& font, const UChar* word, int wordLength, int minimumPrefixLength, int minimumSuffixLength, int& suffixStart )896 static float maxWordFragmentWidth(RenderText* renderer, RenderStyle* style, const Font& font, const UChar* word, int wordLength, int minimumPrefixLength, int minimumSuffixLength, int& suffixStart, HashSet<const SimpleFontData*>& fallbackFonts, GlyphOverflow& glyphOverflow) 897 897 { 898 898 suffixStart = 0; … … 921 921 run.setCharactersLength(fragmentWithHyphen.length()); 922 922 run.setCharacterScanForCodePath(!renderer->canUseSimpleFontCodePath()); 923 float fragmentWidth = font.width(run );923 float fragmentWidth = font.width(run, &fallbackFonts, &glyphOverflow); 924 924 925 925 // Narrow prefixes are ignored. See tryHyphenating in RenderBlockLineLayout.cpp. … … 969 969 // Non-zero only when kerning is enabled, in which case we measure words with their trailing 970 970 // space, then subtract its width. 971 float wordTrailingSpaceWidth = f.typesettingFeatures() & Kerning ? f.width(RenderBlock::constructTextRun(this, f, &space, 1, styleToUse) ) + wordSpacing : 0;971 float wordTrailingSpaceWidth = f.typesettingFeatures() & Kerning ? f.width(RenderBlock::constructTextRun(this, f, &space, 1, styleToUse), &fallbackFonts) + wordSpacing : 0; 972 972 973 973 // If automatic hyphenation is allowed, we keep track of the width of the widest word (or word … … 1070 1070 if (w > maxWordWidth) { 1071 1071 int suffixStart; 1072 float maxFragmentWidth = maxWordFragmentWidth(this, styleToUse, f, characters() + i, wordLen, minimumPrefixLength, minimumSuffixLength, suffixStart );1072 float maxFragmentWidth = maxWordFragmentWidth(this, styleToUse, f, characters() + i, wordLen, minimumPrefixLength, minimumSuffixLength, suffixStart, fallbackFonts, glyphOverflow); 1073 1073 1074 1074 if (suffixStart) { … … 1151 1151 run.setXPos(leadWidth + currMaxWidth); 1152 1152 1153 currMaxWidth += f.width(run );1153 currMaxWidth += f.width(run, &fallbackFonts); 1154 1154 glyphOverflow.right = 0; 1155 1155 needsWordSpacing = isSpace && !previousCharacterIsSpace && i == len - 1;
Note:
See TracChangeset
for help on using the changeset viewer.