Changeset 211108 in webkit


Ignore:
Timestamp:
Jan 24, 2017 1:38:20 PM (7 years ago)
Author:
Alan Bujtas
Message:

Simple line layout: Add support for hyphen: auto.
https://bugs.webkit.org/show_bug.cgi?id=167297
<rdar://problem/30119463>

Reviewed by Antti Koivisto.

Source/WebCore:

Implement hyphen: auto for simple line layout.

Tests: fast/text/simple-line-hyphens-with-text-align.html

fast/text/simple-line-hyphens-with-word-letter-spacing.html

  • platform/text/Hyphenation.h:

(WebCore::enoughWidthForHyphenation):

  • rendering/RenderTreeAsText.cpp:

(WebCore::writeSimpleLine):
(WebCore::write):

  • rendering/SimpleLineLayout.cpp:

(WebCore::SimpleLineLayout::canUseForStyle):
(WebCore::SimpleLineLayout::LineState::appendFragmentAndCreateRunIfNeeded): Inherit the hyphen attribute from the
run-to-be-appended. Ensure that we don't append additional runs when the last run has hyphen.
(WebCore::SimpleLineLayout::splitFragmentToFitLine): Before calling into the lastHyphenPosition() we need to
ensure that the hyphen would surely fit (even on the splitting position).
(WebCore::SimpleLineLayout::createLineRuns): Probe hypenation for overhanging non-whitespace runs.
(WebCore::SimpleLineLayout::printReason):

  • rendering/SimpleLineLayout.h:

(WebCore::SimpleLineLayout::Run::Run):

  • rendering/SimpleLineLayoutFlowContents.h:

(WebCore::SimpleLineLayout::FlowContents::Segment::toSegmentPosition):
(WebCore::SimpleLineLayout::FlowContents::Segment::toRenderPosition):

  • rendering/SimpleLineLayoutResolver.cpp:

(WebCore::SimpleLineLayout::RunResolver::Run::Run):
(WebCore::SimpleLineLayout::RunResolver::Run::constructStringForHyphenIfNeeded):
(WebCore::SimpleLineLayout::RunResolver::Run::text):

  • rendering/SimpleLineLayoutResolver.h:

(WebCore::SimpleLineLayout::RunResolver::Run::hasHyphen):

  • rendering/SimpleLineLayoutTextFragmentIterator.cpp:

(WebCore::SimpleLineLayout::TextFragmentIterator::Style::Style):
(WebCore::SimpleLineLayout::TextFragmentIterator::nextBreakablePosition):
(WebCore::SimpleLineLayout::TextFragmentIterator::nextNonWhitespacePosition):
(WebCore::SimpleLineLayout::TextFragmentIterator::textWidth):
(WebCore::SimpleLineLayout::TextFragmentIterator::lastHyphenPosition): We only check the actual run for hyphenation ignoring
the neighboring runs. This might need to be changed in the future.
(WebCore::SimpleLineLayout::TextFragmentIterator::runWidth):

  • rendering/SimpleLineLayoutTextFragmentIterator.h:

(WebCore::SimpleLineLayout::TextFragmentIterator::TextFragment::TextFragment):
(WebCore::SimpleLineLayout::TextFragmentIterator::TextFragment::hasHyphen):
(WebCore::SimpleLineLayout::TextFragmentIterator::TextFragment::operator==):
(WebCore::SimpleLineLayout::TextFragmentIterator::TextFragment::split):
(WebCore::SimpleLineLayout::TextFragmentIterator::TextFragment::splitWithHyphen):

  • rendering/line/BreakingContext.h:

(WebCore::tryHyphenating):

LayoutTests:

  • fast/text/simple-line-hyphens-with-text-align-expected.html: Added.
  • fast/text/simple-line-hyphens-with-text-align.html: Added.
  • fast/text/simple-line-hyphens-with-word-letter-spacing-expected.html: Added.
  • fast/text/simple-line-hyphens-with-word-letter-spacing.html: Added.
Location:
trunk
Files:
4 added
12 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r211096 r211108  
     12017-01-24  Zalan Bujtas  <zalan@apple.com>
     2
     3        Simple line layout: Add support for hyphen: auto.
     4        https://bugs.webkit.org/show_bug.cgi?id=167297
     5        <rdar://problem/30119463>
     6
     7        Reviewed by Antti Koivisto.
     8
     9        * fast/text/simple-line-hyphens-with-text-align-expected.html: Added.
     10        * fast/text/simple-line-hyphens-with-text-align.html: Added.
     11        * fast/text/simple-line-hyphens-with-word-letter-spacing-expected.html: Added.
     12        * fast/text/simple-line-hyphens-with-word-letter-spacing.html: Added.
     13
    1142017-01-24  Ryan Haddad  <ryanhaddad@apple.com>
    215
  • trunk/Source/WebCore/ChangeLog

    r211097 r211108  
     12017-01-24  Zalan Bujtas  <zalan@apple.com>
     2
     3        Simple line layout: Add support for hyphen: auto.
     4        https://bugs.webkit.org/show_bug.cgi?id=167297
     5        <rdar://problem/30119463>
     6
     7        Reviewed by Antti Koivisto.
     8
     9        Implement hyphen: auto for simple line layout.
     10
     11        Tests: fast/text/simple-line-hyphens-with-text-align.html
     12               fast/text/simple-line-hyphens-with-word-letter-spacing.html
     13
     14        * platform/text/Hyphenation.h:
     15        (WebCore::enoughWidthForHyphenation):
     16        * rendering/RenderTreeAsText.cpp:
     17        (WebCore::writeSimpleLine):
     18        (WebCore::write):
     19        * rendering/SimpleLineLayout.cpp:
     20        (WebCore::SimpleLineLayout::canUseForStyle):
     21        (WebCore::SimpleLineLayout::LineState::appendFragmentAndCreateRunIfNeeded): Inherit the hyphen attribute from the
     22        run-to-be-appended. Ensure that we don't append additional runs when the last run has hyphen.
     23        (WebCore::SimpleLineLayout::splitFragmentToFitLine): Before calling into the lastHyphenPosition() we need to
     24        ensure that the hyphen would surely fit (even on the splitting position).
     25        (WebCore::SimpleLineLayout::createLineRuns): Probe hypenation for overhanging non-whitespace runs.
     26        (WebCore::SimpleLineLayout::printReason):
     27        * rendering/SimpleLineLayout.h:
     28        (WebCore::SimpleLineLayout::Run::Run):
     29        * rendering/SimpleLineLayoutFlowContents.h:
     30        (WebCore::SimpleLineLayout::FlowContents::Segment::toSegmentPosition):
     31        (WebCore::SimpleLineLayout::FlowContents::Segment::toRenderPosition):
     32        * rendering/SimpleLineLayoutResolver.cpp:
     33        (WebCore::SimpleLineLayout::RunResolver::Run::Run):
     34        (WebCore::SimpleLineLayout::RunResolver::Run::constructStringForHyphenIfNeeded):
     35        (WebCore::SimpleLineLayout::RunResolver::Run::text):
     36        * rendering/SimpleLineLayoutResolver.h:
     37        (WebCore::SimpleLineLayout::RunResolver::Run::hasHyphen):
     38        * rendering/SimpleLineLayoutTextFragmentIterator.cpp:
     39        (WebCore::SimpleLineLayout::TextFragmentIterator::Style::Style):
     40        (WebCore::SimpleLineLayout::TextFragmentIterator::nextBreakablePosition):
     41        (WebCore::SimpleLineLayout::TextFragmentIterator::nextNonWhitespacePosition):
     42        (WebCore::SimpleLineLayout::TextFragmentIterator::textWidth):
     43        (WebCore::SimpleLineLayout::TextFragmentIterator::lastHyphenPosition): We only check the actual run for hyphenation ignoring
     44        the neighboring runs. This might need to be changed in the future.
     45        (WebCore::SimpleLineLayout::TextFragmentIterator::runWidth):
     46        * rendering/SimpleLineLayoutTextFragmentIterator.h:
     47        (WebCore::SimpleLineLayout::TextFragmentIterator::TextFragment::TextFragment):
     48        (WebCore::SimpleLineLayout::TextFragmentIterator::TextFragment::hasHyphen):
     49        (WebCore::SimpleLineLayout::TextFragmentIterator::TextFragment::operator==):
     50        (WebCore::SimpleLineLayout::TextFragmentIterator::TextFragment::split):
     51        (WebCore::SimpleLineLayout::TextFragmentIterator::TextFragment::splitWithHyphen):
     52        * rendering/line/BreakingContext.h:
     53        (WebCore::tryHyphenating):
     54
    1552017-01-24  Matt Rajca  <mrajca@apple.com>
    256
  • trunk/Source/WebCore/platform/text/Hyphenation.h

    r165848 r211108  
    3232namespace WebCore {
    3333
     34inline static bool enoughWidthForHyphenation(float availableWidth, float fontPixelSize)
     35{
     36    // If the maximum width available for the prefix before the hyphen is small, then it is very unlikely
     37    // that an hyphenation opportunity exists, so do not bother to look for it.
     38    return availableWidth > fontPixelSize * 5 / 4;
     39
     40}
    3441bool canHyphenate(const AtomicString& localeIdentifier);
    3542size_t lastHyphenLocation(StringView, size_t beforeIndex, const AtomicString& localeIdentifier);
  • trunk/Source/WebCore/rendering/RenderTreeAsText.cpp

    r210763 r211108  
    494494}
    495495
    496 static void writeSimpleLine(TextStream& ts, const RenderText& o, const FloatRect& rect, StringView text)
    497 {
     496static void writeSimpleLine(TextStream& ts, const RenderText& renderText, const SimpleLineLayout::RunResolver::Run& run)
     497{
     498    auto rect = run.rect();
    498499    int x = rect.x();
    499500    int y = rect.y();
    500501    int logicalWidth = ceilf(rect.x() + rect.width()) - x;
    501502
    502     if (is<RenderTableCell>(*o.containingBlock()))
    503         y -= floorToInt(downcast<RenderTableCell>(*o.containingBlock()).intrinsicPaddingBefore());
    504        
     503    if (is<RenderTableCell>(*renderText.containingBlock()))
     504        y -= floorToInt(downcast<RenderTableCell>(*renderText.containingBlock()).intrinsicPaddingBefore());
     505
    505506    ts << "text run at (" << x << "," << y << ") width " << logicalWidth;
    506     ts << ": "
    507         << quoteAndEscapeNonPrintables(text);
     507    if (run.hasHyphen()) {
     508        ts << ": " << quoteAndEscapeNonPrintables(run.text().substring(0, run.text().length() - 1));
     509        ts << " + hyphen string " << quoteAndEscapeNonPrintables(renderText.style().hyphenString().string());
     510    } else
     511        ts << ": " << quoteAndEscapeNonPrintables(run.text());
     512
    508513    ts << "\n";
    509514}
     
    556561            for (const auto& run : resolver.rangeForRenderer(text)) {
    557562                writeIndent(ts, indent + 1);
    558                 writeSimpleLine(ts, text, run.rect(), run.text());
     563                writeSimpleLine(ts, text, run);
    559564            }
    560565        } else {
  • trunk/Source/WebCore/rendering/SimpleLineLayout.cpp

    r210985 r211108  
    3434#include "HitTestRequest.h"
    3535#include "HitTestResult.h"
     36#include "Hyphenation.h"
    3637#include "InlineTextBox.h"
    3738#include "LineWidth.h"
     
    8687    FlowHasLineAlignEdges                 = 1LLU  << 21,
    8788    FlowHasLineSnap                       = 1LLU  << 22,
    88     FlowHasHypensAuto                     = 1LLU  << 23,
     89    FlowHasHypensLimit                    = 1LLU  << 23,
    8990    FlowHasTextEmphasisFillOrMark         = 1LLU  << 24,
    9091    FlowHasTextShadow                     = 1LLU  << 25,
     
    237238    if (style.lineSnap() != LineSnapNone)
    238239        SET_REASON_AND_RETURN_IF_NEEDED(FlowHasLineSnap, reasons, includeReasons);
    239     if (style.hyphens() == HyphensAuto)
    240         SET_REASON_AND_RETURN_IF_NEEDED(FlowHasHypensAuto, reasons, includeReasons);
     240    if (style.hyphenationLimitBefore() != RenderStyle::initialHyphenationLimitBefore()
     241        || style.hyphenationLimitAfter() != RenderStyle::initialHyphenationLimitAfter()
     242        || style.hyphenationLimitLines() != RenderStyle::initialHyphenationLimitLines())
     243        SET_REASON_AND_RETURN_IF_NEEDED(FlowHasHypensLimit, reasons, includeReasons);
    241244    if (style.textEmphasisFill() != TextEmphasisFillFilled || style.textEmphasisMark() != TextEmphasisMarkNone)
    242245        SET_REASON_AND_RETURN_IF_NEEDED(FlowHasTextEmphasisFillOrMark, reasons, includeReasons);
     
    454457        // New line needs new run.
    455458        if (!m_runsWidth)
    456             runs.append(Run(fragment.start(), endPosition, m_runsWidth, m_runsWidth + fragment.width(), false));
     459            runs.append(Run(fragment.start(), endPosition, m_runsWidth, m_runsWidth + fragment.width(), false, fragment.hasHyphen()));
    457460        else {
    458461            const auto& lastFragment = m_fragments.last();
     
    471474            }
    472475            if (lastFragment.isLastInRenderer() || lastFragment.isCollapsed())
    473                 runs.append(Run(fragment.start(), endPosition, m_runsWidth, m_runsWidth + fragment.width(), false));
     476                runs.append(Run(fragment.start(), endPosition, m_runsWidth, m_runsWidth + fragment.width(), false, fragment.hasHyphen()));
    474477            else {
    475478                Run& lastRun = runs.last();
    476479                lastRun.end = endPosition;
    477480                lastRun.logicalRight += fragment.width();
     481                ASSERT(!lastRun.hasHyphen);
     482                lastRun.hasHyphen = fragment.hasHyphen();
    478483            }
    479484        }
     
    624629    });
    625630    unsigned splitPosition = (*it);
    626     if (keepAtLeastOneCharacter && splitPosition == fragmentToSplit.start())
    627         ++splitPosition;
     631    auto& style = textFragmentIterator.style();
     632    // Does first character fit this line?
     633    if (splitPosition == fragmentToSplit.start()) {
     634        if (keepAtLeastOneCharacter)
     635            ++splitPosition;
     636    } else if (style.shouldHyphenate && enoughWidthForHyphenation(availableWidth, style.font.pixelSize())) {
     637        // We might be able to fit the hyphen at the split position.
     638        auto splitPositionWithHyphen = splitPosition;
     639        // Find a splitting position where hyphen surely fits.
     640        auto leftSideWidth = textFragmentIterator.textWidth(start, splitPosition, 0);
     641        while (leftSideWidth + style.hyphenStringWidth > availableWidth) {
     642            if (--splitPositionWithHyphen <= start)
     643                break; // No space for hyphen.
     644            leftSideWidth -= textFragmentIterator.textWidth(splitPositionWithHyphen, splitPositionWithHyphen + 1, 0);
     645        }
     646        if (splitPositionWithHyphen > start) {
     647            if (auto hyphenPosition = textFragmentIterator.lastHyphenPosition(fragmentToSplit, splitPositionWithHyphen + 1))
     648                return fragmentToSplit.splitWithHyphen(*hyphenPosition, textFragmentIterator);
     649        }
     650    }
    628651    return fragmentToSplit.split(splitPosition, textFragmentIterator);
    629652}
     
    737760                break;
    738761            }
     762            ASSERT(fragment.type() == TextFragmentIterator::TextFragment::NonWhitespace);
     763            // Find out if this non-whitespace fragment has a hyphen where we can break.
     764            if (style.shouldHyphenate) {
     765                auto fragmentToSplit = fragment;
     766                // Split and check if we actually ended up with a hyphen.
     767                auto overflowFragment = splitFragmentToFitLine(fragmentToSplit, line.availableWidth() - line.width(), emptyLine, textFragmentIterator);
     768                if (fragmentToSplit.hasHyphen()) {
     769                    line.setOverflowedFragment(overflowFragment);
     770                    line.appendFragmentAndCreateRunIfNeeded(fragmentToSplit, runs);
     771                    break;
     772                }
     773                // No hyphen, no split.
     774            }
    739775            // Non-breakable non-whitespace first fragment. Add it to the current line. -it overflows though.
    740             ASSERT(fragment.type() == TextFragmentIterator::TextFragment::NonWhitespace);
    741776            if (emptyLine) {
    742777                forceFragmentToLine(line, textFragmentIterator, runs, fragment);
     
    957992        stream << "-webkit-line-snap property";
    958993        break;
    959     case FlowHasHypensAuto:
    960         stream << "hyphen: auto";
     994    case FlowHasHypensLimit:
     995        stream << "hyphen-limit-* property";
    961996        break;
    962997    case FlowHasTextEmphasisFillOrMark:
  • trunk/Source/WebCore/rendering/SimpleLineLayout.h

    r208668 r211108  
    4747    Run() { }
    4848#endif
    49     Run(unsigned start, unsigned end, float logicalLeft, float logicalRight, bool isEndOfLine)
    50         : start(start)
    51         , end(end)
     49    Run(unsigned start, unsigned end, float logicalLeft, float logicalRight, bool isEndOfLine, bool hasHyphen)
     50        : end(end)
     51        , start(start)
    5252        , isEndOfLine(isEndOfLine)
     53        , hasHyphen(hasHyphen)
    5354        , logicalLeft(logicalLeft)
    5455        , logicalRight(logicalRight)
    5556    { }
    5657
    57     unsigned start;
    58     unsigned end : 31;
     58    unsigned end;
     59    unsigned start : 30;
    5960    unsigned isEndOfLine : 1;
     61    unsigned hasHyphen : 1;
    6062    float logicalLeft;
    6163    float logicalRight;
  • trunk/Source/WebCore/rendering/SimpleLineLayoutFlowContents.h

    r208668 r211108  
    3838
    3939    struct Segment {
     40        unsigned toSegmentPosition(unsigned position) const
     41        {
     42            ASSERT(position >= start);
     43            return position - start;
     44        }
     45        unsigned toRenderPosition(unsigned position) const { return start + position; }
    4046        unsigned start;
    4147        unsigned end;
  • trunk/Source/WebCore/rendering/SimpleLineLayoutResolver.cpp

    r196561 r211108  
    4848    : m_iterator(iterator)
    4949{
     50    constructStringForHyphenIfNeeded();
     51}
     52
     53void RunResolver::Run::constructStringForHyphenIfNeeded()
     54{
     55    auto& run = m_iterator.simpleRun();
     56    if (!run.hasHyphen)
     57        return;
     58    // Empty runs should not have hyphen.
     59    ASSERT(run.start < run.end);
     60    auto& segment = m_iterator.resolver().m_flowContents.segmentForRun(run.start, run.end);
     61    auto text = StringView(segment.text).substring(segment.toSegmentPosition(run.start), run.end - run.start);
     62    m_textWithHyphen = makeString(text, m_iterator.resolver().flow().style().hyphenString());
    5063}
    5164
     
    7083StringView RunResolver::Run::text() const
    7184{
     85    if (m_textWithHyphen)
     86        return StringView(*m_textWithHyphen);
    7287    auto& run = m_iterator.simpleRun();
    7388    ASSERT(run.start < run.end);
     
    7590    // We currently split runs on segment boundaries (different RenderObject).
    7691    ASSERT(run.end <= segment.end);
    77     return StringView(segment.text).substring(run.start - segment.start, run.end - run.start);
     92    return StringView(segment.text).substring(segment.toSegmentPosition(run.start), run.end - run.start);
    7893}
    7994
  • trunk/Source/WebCore/rendering/SimpleLineLayoutResolver.h

    r208668 r211108  
    6666        StringView text() const;
    6767        bool isEndOfLine() const;
     68        bool hasHyphen() const { return m_iterator.simpleRun().hasHyphen; }
    6869
    6970        unsigned lineIndex() const;
     
    7172    private:
    7273        float computeBaselinePosition() const;
     74        void constructStringForHyphenIfNeeded();
    7375
    7476        const Iterator& m_iterator;
     77        std::optional<String> m_textWithHyphen;
    7578    };
    7679
  • trunk/Source/WebCore/rendering/SimpleLineLayoutTextFragmentIterator.cpp

    r210456 r211108  
    2727#include "SimpleLineLayoutTextFragmentIterator.h"
    2828
     29#include "Hyphenation.h"
    2930#include "RenderBlockFlow.h"
    3031#include "RenderChildIterator.h"
     
    4748    , wordSpacing(font.wordSpacing())
    4849    , tabWidth(collapseWhitespace ? 0 : style.tabSize())
     50    , shouldHyphenate(style.hyphens() == HyphensAuto && canHyphenate(style.locale()))
     51    , hyphenStringWidth(shouldHyphenate ? font.width(TextRun(style.hyphenString())) : 0)
    4952    , locale(style.locale())
    5053{
     
    144147        m_lineBreakIterator.resetStringAndReleaseIterator(segment.text, m_style.locale, LineBreakIteratorMode::Default);
    145148    }
    146     unsigned segmentPosition = startPosition - segment.start;
    147     return segment.start + nextBreakablePositionInSegment(m_lineBreakIterator, segmentPosition, m_style.breakNBSP, m_style.keepAllWordsForCJK);
     149    return segment.toRenderPosition(nextBreakablePositionInSegment(m_lineBreakIterator, segment.toSegmentPosition(startPosition), m_style.breakNBSP, m_style.keepAllWordsForCJK));
    148150}
    149151
     
    155157    unsigned position = startPosition;
    156158    for (; position < segment.end; ++position) {
    157         auto character = text[position - segment.start];
     159        auto character = text[segment.toSegmentPosition(position)];
    158160        bool isWhitespace = character == ' ' || character == '\t' || (!m_style.preserveNewline && character == '\n');
    159161        if (!isWhitespace)
     
    171173        return 0;
    172174    if (m_style.font.isFixedPitch() || (from == segment.start && to == segment.end))
    173         return downcast<RenderText>(segment.renderer).width(from - segment.start, to - from, m_style.font, xPosition, nullptr, nullptr);
     175        return downcast<RenderText>(segment.renderer).width(segment.toSegmentPosition(from), to - from, m_style.font, xPosition, nullptr, nullptr);
    174176    return runWidth(segment, from, to, xPosition);
     177}
     178
     179std::optional<unsigned> TextFragmentIterator::lastHyphenPosition(const TextFragmentIterator::TextFragment& run, unsigned beforeIndex) const
     180{
     181    ASSERT(run.start() < beforeIndex);
     182    auto& segment = *m_currentSegment;
     183    ASSERT(segment.start <= beforeIndex && beforeIndex <= segment.end);
     184    ASSERT(is<RenderText>(segment.renderer));
     185    if (!m_style.shouldHyphenate || run.type() != TextFragment::NonWhitespace)
     186        return std::nullopt;
     187   
     188    auto runStart = segment.toSegmentPosition(run.start());
     189    auto before = segment.toSegmentPosition(beforeIndex) - runStart;
     190    auto substringForHyphenation = StringView(segment.text).substring(runStart, run.end() - run.start());
     191    auto hyphenLocation = lastHyphenLocation(substringForHyphenation, before, m_style.locale);
     192    if (hyphenLocation)
     193        return segment.toRenderPosition(hyphenLocation + runStart);
     194    return std::nullopt;
    175195}
    176196
     
    220240    if (startPosition == endPosition)
    221241        return 0;
    222     unsigned segmentFrom = startPosition - segment.start;
    223     unsigned segmentTo = endPosition - segment.start;
     242    unsigned segmentFrom = segment.toSegmentPosition(startPosition);
     243    unsigned segmentTo = segment.toSegmentPosition(endPosition);
    224244    bool measureWithEndSpace = m_style.collapseWhitespace && segmentTo < segment.text.length() && segment.text[segmentTo] == ' ';
    225245    if (measureWithEndSpace)
  • trunk/Source/WebCore/rendering/SimpleLineLayoutTextFragmentIterator.h

    r210456 r211108  
    4444        enum Type { ContentEnd, SoftLineBreak, HardLineBreak, Whitespace, NonWhitespace };
    4545        TextFragment() = default;
    46         TextFragment(unsigned start, unsigned end, float width, Type type, bool isLastInRenderer = false, bool overlapsToNextRenderer = false, bool isCollapsed = false, bool isCollapsible = false)
     46        TextFragment(unsigned start, unsigned end, float width, Type type, bool isLastInRenderer = false, bool overlapsToNextRenderer = false, bool isCollapsed = false, bool isCollapsible = false, bool hasHyphen = false)
    4747            : m_start(start)
    4848            , m_end(end)
     
    5353            , m_isCollapsed(isCollapsed)
    5454            , m_isCollapsible(isCollapsible)
     55            , m_hasHyphen(hasHyphen)
    5556        {
    5657        }
     
    6566        bool isCollapsed() const { return m_isCollapsed; }
    6667        bool isCollapsible() const { return m_isCollapsible; }
     68        bool hasHyphen() const { return m_hasHyphen; }
    6769
    6870        bool isEmpty() const { return start() == end() && !isLineBreak(); }
    6971        TextFragment split(unsigned splitPosition, const TextFragmentIterator&);
     72        TextFragment splitWithHyphen(unsigned hyphenPosition, const TextFragmentIterator&);
    7073        bool operator==(const TextFragment& other) const
    7174        {
     
    7780                && m_overlapsToNextRenderer == other.m_overlapsToNextRenderer
    7881                && m_isCollapsed == other.m_isCollapsed
    79                 && m_isCollapsible == other.m_isCollapsible;
     82                && m_isCollapsible == other.m_isCollapsible
     83                && m_hasHyphen == other.m_hasHyphen;
    8084        }
    8185
     
    8993        bool m_isCollapsed { false };
    9094        bool m_isCollapsible { false };
     95        bool m_hasHyphen { false };
    9196    };
    9297    TextFragment nextTextFragment(float xPosition = 0);
    9398    void revertToEndOfFragment(const TextFragment&);
     99
     100    // FIXME: These functions below should be decoupled from the text iterator.
    94101    float textWidth(unsigned startPosition, unsigned endPosition, float xPosition) const;
     102    std::optional<unsigned> lastHyphenPosition(const TextFragmentIterator::TextFragment& run, unsigned beforeIndex) const;
    95103
    96104    struct Style {
     
    109117        float wordSpacing;
    110118        unsigned tabWidth;
     119        bool shouldHyphenate;
     120        float hyphenStringWidth;
    111121        AtomicString locale;
    112122    };
     
    143153    };
    144154
    145     TextFragment newFragment(*this);
     155    TextFragment rightSide(*this);
    146156    m_end = splitPosition;
    147157    updateFragmentProperties(*this);
    148158
    149     newFragment.m_start = splitPosition;
    150     updateFragmentProperties(newFragment);
    151     return newFragment;
     159    rightSide.m_start = splitPosition;
     160    updateFragmentProperties(rightSide);
     161    return rightSide;
     162}
     163
     164inline TextFragmentIterator::TextFragment TextFragmentIterator::TextFragment::splitWithHyphen(unsigned hyphenPosition,
     165    const TextFragmentIterator& textFragmentIterator)
     166{
     167    ASSERT(textFragmentIterator.style().shouldHyphenate);
     168    auto rightSide = split(hyphenPosition, textFragmentIterator);
     169    m_hasHyphen = true;
     170    m_width += textFragmentIterator.style().hyphenStringWidth;
     171    return rightSide;
    152172}
    153173
  • trunk/Source/WebCore/rendering/line/BreakingContext.h

    r208985 r211108  
    688688
    689689    float maxPrefixWidth = availableWidth - xPos - hyphenWidth - lastSpaceWordSpacing;
    690     // If the maximum width available for the prefix before the hyphen is small, then it is very unlikely
    691     // that an hyphenation opportunity exists, so do not bother to look for it.
    692     if (maxPrefixWidth <= font.pixelSize() * 5 / 4)
     690    if (!enoughWidthForHyphenation(maxPrefixWidth, font.pixelSize()))
    693691        return;
    694692
Note: See TracChangeset for help on using the changeset viewer.