Changeset 121102 in webkit


Ignore:
Timestamp:
Jun 23, 2012 2:23:12 PM (12 years ago)
Author:
mitz@apple.com
Message:

RenderText’s minimum preferred width is incorrect automatic hyphenation is used
https://bugs.webkit.org/show_bug.cgi?id=89814

Reviewed by Sam Weinig.

Source/WebCore:

Test: fast/text/hyphen-min-preferred-width.html

  • rendering/RenderText.cpp:

(WebCore::maxWordFragmentWidth): Added this helper function. It returns the width of the
widest hyphenated fragment of the word (except for the suffix after the last hyphen) and
the offset of the last hyphenation opportunity.
(WebCore::RenderText::computePreferredLogicalWidths): Changed this function to consider the
widths of hyphenated word fragments rather than entire words when computing the minimum
width. Because hyphenating and measuring all fragments is expensive, hyphenation is only
attempted if the unhyphenated word is wider than the current minimum width.

LayoutTests:

  • fast/text/hyphen-min-preferred-width-expected.html: Added.
  • fast/text/hyphen-min-preferred-width.html: Added.
Location:
trunk
Files:
2 added
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r121101 r121102  
     12012-06-23  Dan Bernstein  <mitz@apple.com>
     2
     3        RenderText’s minimum preferred width is incorrect automatic hyphenation is used
     4        https://bugs.webkit.org/show_bug.cgi?id=89814
     5
     6        Reviewed by Sam Weinig.
     7
     8        * fast/text/hyphen-min-preferred-width-expected.html: Added.
     9        * fast/text/hyphen-min-preferred-width.html: Added.
     10
    1112012-06-23  Kenneth Russell  <kbr@google.com>
    212
  • trunk/Source/WebCore/ChangeLog

    r121098 r121102  
     12012-06-23  Dan Bernstein  <mitz@apple.com>
     2
     3        RenderText’s minimum preferred width is incorrect automatic hyphenation is used
     4        https://bugs.webkit.org/show_bug.cgi?id=89814
     5
     6        Reviewed by Sam Weinig.
     7
     8        Test: fast/text/hyphen-min-preferred-width.html
     9
     10        * rendering/RenderText.cpp:
     11        (WebCore::maxWordFragmentWidth): Added this helper function. It returns the width of the
     12        widest hyphenated fragment of the word (except for the suffix after the last hyphen) and
     13        the offset of the last hyphenation opportunity.
     14        (WebCore::RenderText::computePreferredLogicalWidths): Changed this function to consider the
     15        widths of hyphenated word fragments rather than entire words when computing the minimum
     16        width. Because hyphenating and measuring all fragments is expensive, hyphenation is only
     17        attempted if the unhyphenated word is wider than the current minimum width.
     18
    1192012-06-23  Sheriff Bot  <webkit.review.bot@gmail.com>
    220
  • trunk/Source/WebCore/rendering/RenderText.cpp

    r121050 r121102  
    3131#include "FontTranscoder.h"
    3232#include "FrameView.h"
     33#include "Hyphenation.h"
    3334#include "InlineTextBox.h"
    3435#include "Range.h"
     
    889890}
    890891
     892static float maxWordFragmentWidth(RenderText* renderer, RenderStyle* style, const Font& font, const UChar* word, int wordLength, int minimumPrefixLength, int minimumSuffixLength, int& suffixStart)
     893{
     894    suffixStart = 0;
     895    if (wordLength <= minimumSuffixLength)
     896        return 0;
     897
     898    Vector<int, 8> hyphenLocations;
     899    int hyphenLocation = wordLength - minimumSuffixLength;
     900    while ((hyphenLocation = lastHyphenLocation(word, wordLength, hyphenLocation, style->locale())) >= minimumPrefixLength)
     901        hyphenLocations.append(hyphenLocation);
     902
     903    if (hyphenLocations.isEmpty())
     904        return 0;
     905
     906    hyphenLocations.reverse();
     907
     908    float minimumFragmentWidthToConsider = font.pixelSize() * 5 / 4 + hyphenWidth(renderer, font);
     909    float maxFragmentWidth = 0;
     910    for (size_t k = 0; k < hyphenLocations.size(); ++k) {
     911        int fragmentLength = hyphenLocations[k] - suffixStart;
     912        StringBuilder fragmentWithHyphen;
     913        fragmentWithHyphen.append(word + suffixStart, fragmentLength);
     914        fragmentWithHyphen.append(style->hyphenString());
     915
     916        TextRun run = RenderBlock::constructTextRun(renderer, font, fragmentWithHyphen.characters(), fragmentWithHyphen.length(), style);
     917        run.setCharactersLength(fragmentWithHyphen.length());
     918        run.setCharacterScanForCodePath(!renderer->canUseSimpleFontCodePath());
     919        float fragmentWidth = font.width(run);
     920
     921        // Narrow prefixes are ignored. See tryHyphenating in RenderBlockLineLayout.cpp.
     922        if (fragmentWidth <= minimumFragmentWidthToConsider)
     923            continue;
     924
     925        suffixStart += fragmentLength;
     926        maxFragmentWidth = max(maxFragmentWidth, fragmentWidth);
     927    }
     928
     929    return maxFragmentWidth;
     930}
     931
    891932void RenderText::computePreferredLogicalWidths(float leadWidth, HashSet<const SimpleFontData*>& fallbackFonts, GlyphOverflow& glyphOverflow)
    892933{
     
    926967    // space, then subtract its width.
    927968    float wordTrailingSpaceWidth = f.typesettingFeatures() & Kerning ? f.width(RenderBlock::constructTextRun(this, f, &space, 1, styleToUse)) : 0;
     969
     970    // If automatic hyphenation is allowed, we keep track of the width of the widest word (or word
     971    // fragment) encountered so far, and only try hyphenating words that are wider.
     972    float maxWordWidth = numeric_limits<float>::max();
     973    int minimumPrefixLength = 0;
     974    int minimumSuffixLength = 0;
     975    if (styleToUse->hyphens() == HyphensAuto && canHyphenate(styleToUse->locale())) {
     976        maxWordWidth = 0;
     977
     978        // Map 'hyphenate-limit-{before,after}: auto;' to 2.
     979        minimumPrefixLength = styleToUse->hyphenationLimitBefore();
     980        if (minimumPrefixLength < 0)
     981            minimumPrefixLength = 2;
     982
     983        minimumSuffixLength = styleToUse->hyphenationLimitAfter();
     984        if (minimumSuffixLength < 0)
     985            minimumSuffixLength = 2;
     986    }
    928987
    929988    int firstGlyphLeftOverflow = -1;
     
    10061065            }
    10071066
     1067            if (w > maxWordWidth) {
     1068                int suffixStart;
     1069                float maxFragmentWidth = maxWordFragmentWidth(this, styleToUse, f, txt + i, wordLen, minimumPrefixLength, minimumSuffixLength, suffixStart);
     1070
     1071                if (suffixStart) {
     1072                    float suffixWidth;
     1073                    if (wordTrailingSpaceWidth && isSpace)
     1074                        suffixWidth = widthFromCache(f, i + suffixStart, wordLen - suffixStart + 1, leadWidth + currMaxWidth, 0, 0) - wordTrailingSpaceWidth;
     1075                    else
     1076                        suffixWidth = widthFromCache(f, i + suffixStart, wordLen - suffixStart, leadWidth + currMaxWidth, 0, 0);
     1077
     1078                    maxFragmentWidth = max(maxFragmentWidth, suffixWidth);
     1079
     1080                    currMinWidth += maxFragmentWidth - w;
     1081                    maxWordWidth = max(maxWordWidth, maxFragmentWidth);
     1082                } else
     1083                    maxWordWidth = w;
     1084            }
     1085
    10081086            if (firstGlyphLeftOverflow < 0)
    10091087                firstGlyphLeftOverflow = glyphOverflow.left;
     
    10331111                if (hasBreak)
    10341112                    m_hasBreakableChar = true;
    1035                 m_beginMinWidth = hasBreak ? 0 : w;
     1113                m_beginMinWidth = hasBreak ? 0 : currMinWidth;
    10361114            }
    1037             m_endMinWidth = w;
     1115            m_endMinWidth = currMinWidth;
    10381116
    10391117            if (currMinWidth > m_minWidth)
Note: See TracChangeset for help on using the changeset viewer.