Changeset 293218 in webkit


Ignore:
Timestamp:
Apr 22, 2022 6:27:43 AM (2 years ago)
Author:
Alan Bujtas
Message:

Book content is clipped at page boundary when displaying list with bullet points
https://bugs.webkit.org/show_bug.cgi?id=239638
<rdar://89257768>

Reviewed by Antti Koivisto.

Source/WebCore:

Table cell content needs special handling when does not fit the page.

When a table cell's first line does not fit the page, instead of the normal, "let's add a flow level pagination strut"
we have to handle it as a line level strut (not sure why it is implemted this way but this is the expected behavior).
-also implment LineBoxIteratorModernPath::isFirstAfterPageBreak.

Test: fast/multicol/pagination/table-cell-one-line-pagination.html

  • layout/integration/inline/InlineIteratorLineBoxModernPath.h:

(WebCore::InlineIterator::LineBoxIteratorModernPath::isFirstAfterPageBreak const):

  • layout/integration/inline/LayoutIntegrationLine.h:

(WebCore::LayoutIntegration::Line::Line):
(WebCore::LayoutIntegration::Line::isFirstAfterPageBreak const):

  • layout/integration/inline/LayoutIntegrationPagination.cpp:

(WebCore::LayoutIntegration::setPageBreakForLine): According to RenderBlockFlow::adjustLinePositionForPagination, we
have to call setPageBreak, even when the first line does not fit.
(WebCore::LayoutIntegration::makeAdjustedContent):
(WebCore::LayoutIntegration::adjustLinePositionsForPagination):

LayoutTests:

  • fast/multicol/pagination/table-cell-one-line-pagination-expected.html: Added.
  • fast/multicol/pagination/table-cell-one-line-pagination.html: Added.
Location:
trunk
Files:
2 added
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r293212 r293218  
     12022-04-22  Alan Bujtas  <zalan@apple.com>
     2
     3        Book content is clipped at page boundary when displaying list with bullet points
     4        https://bugs.webkit.org/show_bug.cgi?id=239638
     5        <rdar://89257768>
     6
     7        Reviewed by Antti Koivisto.
     8
     9        * fast/multicol/pagination/table-cell-one-line-pagination-expected.html: Added.
     10        * fast/multicol/pagination/table-cell-one-line-pagination.html: Added.
     11
    1122022-04-22  Tyler Wilcock  <tyler_w@apple.com>
    213
  • trunk/Source/WebCore/ChangeLog

    r293217 r293218  
     12022-04-22  Alan Bujtas  <zalan@apple.com>
     2
     3        Book content is clipped at page boundary when displaying list with bullet points
     4        https://bugs.webkit.org/show_bug.cgi?id=239638
     5        <rdar://89257768>
     6
     7        Reviewed by Antti Koivisto.
     8
     9        Table cell content needs special handling when does not fit the page.
     10
     11        When a table cell's first line does not fit the page, instead of the normal, "let's add a flow level pagination strut"
     12        we have to handle it as a line level strut (not sure why it is implemted this way but this is the expected behavior).
     13        -also implment LineBoxIteratorModernPath::isFirstAfterPageBreak.
     14
     15        Test: fast/multicol/pagination/table-cell-one-line-pagination.html
     16
     17        * layout/integration/inline/InlineIteratorLineBoxModernPath.h:
     18        (WebCore::InlineIterator::LineBoxIteratorModernPath::isFirstAfterPageBreak const):
     19        * layout/integration/inline/LayoutIntegrationLine.h:
     20        (WebCore::LayoutIntegration::Line::Line):
     21        (WebCore::LayoutIntegration::Line::isFirstAfterPageBreak const):
     22        * layout/integration/inline/LayoutIntegrationPagination.cpp:
     23        (WebCore::LayoutIntegration::setPageBreakForLine): According to RenderBlockFlow::adjustLinePositionForPagination, we
     24        have to call setPageBreak, even when the first line does not fit.
     25        (WebCore::LayoutIntegration::makeAdjustedContent):
     26        (WebCore::LayoutIntegration::adjustLinePositionsForPagination):
     27
    1282022-04-22  Antti Koivisto  <antti@apple.com>
    229
  • trunk/Source/WebCore/layout/integration/inline/InlineIteratorLineBoxModernPath.h

    r293027 r293218  
    6969
    7070    RenderFragmentContainer* containingFragment() const { return nullptr; }
    71     bool isFirstAfterPageBreak() const { return false; }
     71    bool isFirstAfterPageBreak() const { return line().isFirstAfterPageBreak(); }
    7272
    7373    void traverseNext()
  • trunk/Source/WebCore/layout/integration/inline/LayoutIntegrationLine.h

    r292954 r293218  
    3737    WTF_MAKE_FAST_ALLOCATED;
    3838public:
    39     Line(size_t firstBoxIndex, size_t boxCount, const FloatRect& lineBoxRect, float enclosingContentTop, float enclosingContentBottom, const FloatRect& scrollableOverflow, const FloatRect& inkOverflow, float baseline, FontBaseline baselineType, float contentLogicalOffset, float contentLogicalWidth, bool isHorizontal)
     39    Line(size_t firstBoxIndex, size_t boxCount, const FloatRect& lineBoxRect, float enclosingContentTop, float enclosingContentBottom, const FloatRect& scrollableOverflow, const FloatRect& inkOverflow, float baseline, FontBaseline baselineType, float contentLogicalOffset, float contentLogicalWidth, bool isHorizontal, bool isFirstAfterPageBreak = false)
    4040        : m_firstBoxIndex(firstBoxIndex)
    4141        , m_boxCount(boxCount)
     
    5050        , m_baselineType(baselineType)
    5151        , m_isHorizontal(isHorizontal)
     52        , m_isFirstAfterPageBreak(isFirstAfterPageBreak)
    5253    {
    5354    }
     
    7778    float contentLogicalWidth() const { return m_contentLogicalWidth; }
    7879
     80    bool isFirstAfterPageBreak() const { return m_isFirstAfterPageBreak; }
     81
    7982private:
    8083    size_t m_firstBoxIndex { 0 };
     
    9497    FontBaseline m_baselineType { AlphabeticBaseline };
    9598    bool m_isHorizontal { true };
     99    // FIXME: This is to match paginated legacy lines. Move it to some other, paginated related structure.
     100    bool m_isFirstAfterPageBreak { false };
    96101};
    97102
  • trunk/Source/WebCore/layout/integration/inline/LayoutIntegrationPagination.cpp

    r293027 r293218  
    3131#include "FontCascade.h"
    3232#include "RenderBlockFlow.h"
     33#include "RenderTableCell.h"
    3334
    3435namespace WebCore {
     
    8889}
    8990
    90 static void setPageBreakForLine(unsigned lineBreakIndex, PaginatedLines& lines, RenderBlockFlow& flow, Vector<Strut>& struts,
    91     bool atTheTopOfColumnOrPage, bool lineDoesNotFit)
     91static void setPageBreakForLine(unsigned lineBreakIndex, PaginatedLines& lines, RenderBlockFlow& flow, Vector<Strut>& struts, bool atTheTopOfColumnOrPage, bool lineDoesNotFit, bool& isPageBreakWithLineStrut)
    9292{
    9393    auto line = lines.at(lineBreakIndex);
    9494    auto remainingLogicalHeight = flow.pageRemainingLogicalHeightForOffset(line.top, RenderBlockFlow::ExcludePageBoundary);
    95     auto& style = flow.style();
    96     auto firstLineDoesNotFit = !lineBreakIndex && line.height < flow.pageLogicalHeightForOffset(line.top);
    97     auto moveOrphanToNextColumn = lineDoesNotFit && !style.hasAutoOrphans() && style.orphans() > (short)lineBreakIndex;
    98     if (firstLineDoesNotFit || moveOrphanToNextColumn) {
    99         auto firstLine = lines.first();
    100         auto firstLineUpperOverhang = std::max(LayoutUnit(-firstLine.top), 0_lu);
    101         flow.setPaginationStrut(line.top + remainingLogicalHeight + firstLineUpperOverhang);
    102         return;
    103     }
     95
    10496    if (atTheTopOfColumnOrPage)
    10597        flow.setPageBreak(line.top, line.height);
    10698    else
    10799        flow.setPageBreak(line.top, line.height - remainingLogicalHeight);
     100
     101    auto& style = flow.style();
     102    auto firstLineDoesNotFit = !lineBreakIndex && line.height < flow.pageLogicalHeightForOffset(line.top);
     103    auto moveOrphanToNextColumn = lineDoesNotFit && !style.hasAutoOrphans() && style.orphans() > (short)lineBreakIndex;
     104    // Special table cell handling. See RenderBlockFlow::adjustLinePositionForPagination for details.
     105    if ((firstLineDoesNotFit || moveOrphanToNextColumn) && !is<RenderTableCell>(flow)) {
     106        auto firstLine = lines.first();
     107        auto firstLineUpperOverhang = std::max(LayoutUnit(-firstLine.top), 0_lu);
     108        flow.setPaginationStrut(line.top + remainingLogicalHeight + firstLineUpperOverhang);
     109        isPageBreakWithLineStrut = false;
     110        return;
     111    }
     112    isPageBreakWithLineStrut = true;
    108113    struts.append({ lineBreakIndex, computeOffsetAfterLineBreak(lines[lineBreakIndex].top, !lineBreakIndex, atTheTopOfColumnOrPage, flow) });
    109114}
     
    118123}
    119124
    120 static std::unique_ptr<InlineContent> makeAdjustedContent(const InlineContent& inlineContent, Vector<float> adjustments)
     125static std::unique_ptr<InlineContent> makeAdjustedContent(const InlineContent& inlineContent, Vector<float> adjustments, Vector<bool> isFirstLineAfterPageBreakList)
    121126{
    122127    auto moveVertically = [](FloatRect rect, float offset) {
     
    125130    };
    126131
    127     auto adjustedLine = [&](const Line& line, float offset)
    128     {
     132    auto adjustedLine = [&] (auto& line, auto offset, auto isFirstAfterPageBreak) {
    129133        return Line {
    130134            line.firstBoxIndex(),
     
    139143            line.contentLogicalOffset(),
    140144            line.contentLogicalWidth(),
    141             line.isHorizontal()
     145            line.isHorizontal(),
     146            isFirstAfterPageBreak
    142147        };
    143148    };
    144149
    145     auto adjustedBox = [&](const InlineDisplay::Box& box, float offset)
    146     {
     150    auto adjustedBox = [&](auto& box, auto offset) {
    147151        auto adjustedBox = box;
    148152        adjustedBox.moveVertically(offset);
     
    153157
    154158    for (size_t lineIndex = 0; lineIndex < inlineContent.lines.size(); ++lineIndex)
    155         adjustedContent->lines.append(adjustedLine(inlineContent.lines[lineIndex], adjustments[lineIndex]));
     159        adjustedContent->lines.append(adjustedLine(inlineContent.lines[lineIndex], adjustments[lineIndex], isFirstLineAfterPageBreakList[lineIndex]));
    156160
    157161    for (auto& box : inlineContent.boxes)
     
    173177    auto orphans = flow.style().hasAutoOrphans() ? 1 : std::max<int>(flow.style().orphans(), 1);
    174178    PaginatedLines lines;
    175     for (unsigned lineIndex = 0; lineIndex < lineCount; ++lineIndex) {
     179    auto isFirstLineAfterPageBreakList = Vector<bool>(lineCount, false);
     180    for (size_t lineIndex = 0; lineIndex < lineCount; ++lineIndex) {
    176181        auto line = computeLineTopAndBottomWithOverflow(flow, inlineContent.lines, lineIndex, struts);
    177182        lines.append(line);
     
    183188            // Are we still at the top of the column/page?
    184189            atTheTopOfColumnOrPage = atTheTopOfColumnOrPage ? lineIndex == lineBreakIndex : false;
    185             setPageBreakForLine(lineBreakIndex, lines, flow, struts, atTheTopOfColumnOrPage, lineDoesNotFit);
     190            auto isPageBreakWithLineStrut = false;
     191            setPageBreakForLine(lineBreakIndex, lines, flow, struts, atTheTopOfColumnOrPage, lineDoesNotFit, isPageBreakWithLineStrut);
     192            isFirstLineAfterPageBreakList[lineIndex] = isPageBreakWithLineStrut;
    186193            // Recompute line positions that we already visited but widow break pushed them to a new page.
    187194            for (auto i = lineBreakIndex; i < lines.size(); ++i)
     
    199206    }
    200207
    201     return makeAdjustedContent(inlineContent, adjustments);
     208    return makeAdjustedContent(inlineContent, adjustments, isFirstLineAfterPageBreakList);
    202209}
    203210
Note: See TracChangeset for help on using the changeset viewer.