Skip to content

Commit

Permalink
[IFC][Line clamp] Add basic line-clamp implementation for IFC
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=248160

Reviewed by Antti Koivisto.

1. Check if the deprecated flexbox subtree supports IFC
2. Run layout with line-clamp values set

* Source/WebCore/layout/formattingContexts/inline/InlineFormattingContext.cpp:
(WebCore::Layout::shouldTruncateOverflow): fix ordering.
* Source/WebCore/rendering/RenderDeprecatedFlexibleBox.cpp:
(WebCore::RenderDeprecatedFlexibleBox::applyModernLineClamp):
(WebCore::RenderDeprecatedFlexibleBox::applyLineClamp):
* Source/WebCore/rendering/RenderDeprecatedFlexibleBox.h:
* Source/WebCore/rendering/RenderLayoutState.h:
(WebCore::RenderLayoutState::resetLineClamp):

Canonical link: https://commits.webkit.org/256906@main
  • Loading branch information
alanbaradlay committed Nov 21, 2022
1 parent 16b1006 commit b360263
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 6 deletions.
Expand Up @@ -209,18 +209,16 @@ enum class ShouldLineEndWithEllispsis : uint8_t {
};
static ShouldLineEndWithEllispsis shouldTruncateOverflow(const RenderStyle& rootStyle, size_t numberOfLines, std::optional<size_t> maximumNumberOfLines)
{
// Truncation is in effect when the block container has overflow other than visible.
if (rootStyle.isOverflowVisible())
return ShouldLineEndWithEllispsis::No;
if (rootStyle.textOverflow() == TextOverflow::Ellipsis)
return ShouldLineEndWithEllispsis::WhenContentOverflows;
if (maximumNumberOfLines) {
ASSERT(numberOfLines < *maximumNumberOfLines);
// If the next call to layoutInlineContent() won't produce a line with content (e.g. only floats), we'll end up here again.
auto treatNextLineAsLastLine = *maximumNumberOfLines - numberOfLines == 1;
if (treatNextLineAsLastLine)
return ShouldLineEndWithEllispsis::Always;
}
// Truncation is in effect when the block container has overflow other than visible.
if (!rootStyle.isOverflowVisible() && rootStyle.textOverflow() == TextOverflow::Ellipsis)
return ShouldLineEndWithEllispsis::WhenContentOverflows;
return ShouldLineEndWithEllispsis::No;
}

Expand Down
55 changes: 54 additions & 1 deletion Source/WebCore/rendering/RenderDeprecatedFlexibleBox.cpp
Expand Up @@ -27,11 +27,13 @@

#include "FontCascade.h"
#include "LayoutRepainter.h"
#include "RenderDescendantIterator.h"
#include "RenderIterator.h"
#include "RenderLayer.h"
#include "RenderLayoutState.h"
#include "RenderView.h"
#include <wtf/IsoMallocInlines.h>
#include <wtf/Scope.h>
#include <wtf/StdLibExtras.h>
#include <wtf/unicode/CharacterNames.h>

Expand Down Expand Up @@ -1019,9 +1021,50 @@ static size_t lineCountFor(const RenderBlockFlow& blockFlow)
return count;
}

bool RenderDeprecatedFlexibleBox::applyModernLineClamp(FlexBoxIterator& iterator)
{
auto* firstFlowBlockWithInlineChildren = [&] () -> RenderBlockFlow* {
for (auto& descendant : descendantsOfType<RenderBlockFlow>(*this)) {
if (descendant.childrenInline())
return &descendant;
}
return nullptr;
}();
if (!firstFlowBlockWithInlineChildren)
return false;

// If the first block with inline content supports modern line layout, all siblings (and descendants) do as well.
// see LayoutIntegrationCoverage::canUseForStyle.
firstFlowBlockWithInlineChildren->computeAndSetLineLayoutPath();
if (firstFlowBlockWithInlineChildren->lineLayoutPath() != RenderBlockFlow::ModernPath)
return false;

auto& layoutState = *view().frameView().layoutContext().layoutState();
auto currentLineClamp = std::optional<std::pair<size_t, size_t>> { };
if (layoutState.hasLineClamp())
currentLineClamp = { *layoutState.maximumLineCountForLineClamp(), layoutState.visibleLineCountForLineClamp().value_or(0) };

auto restoreCurrentLineClamp = makeScopeExit([&] {
if (!currentLineClamp)
return layoutState.resetLineClamp();
layoutState.setMaximumLineCountForLineClamp(currentLineClamp->first);
layoutState.setVisibleLineCountForLineClamp(currentLineClamp->second);
});

// FIXME: Add support for percent values.
layoutState.setMaximumLineCountForLineClamp(style().lineClamp().value());
layoutState.setVisibleLineCountForLineClamp({ });
for (auto* child = iterator.first(); child; child = iterator.next()) {
if (childDoesNotAffectWidthOrFlexing(child))
continue;

child->layoutIfNeeded();
}
return true;
}

void RenderDeprecatedFlexibleBox::applyLineClamp(FlexBoxIterator& iterator, bool relayoutChildren)
{
size_t maxLineCount = 0;
for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
if (childDoesNotAffectWidthOrFlexing(child))
continue;
Expand All @@ -1037,6 +1080,16 @@ void RenderDeprecatedFlexibleBox::applyLineClamp(FlexBoxIterator& iterator, bool
clearTruncation(downcast<RenderBlockFlow>(*child));
}
}
}

if (applyModernLineClamp(iterator))
return;

size_t maxLineCount = 0;
for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
if (childDoesNotAffectWidthOrFlexing(child))
continue;

child->layoutIfNeeded();
if (child->style().height().isAuto() && is<RenderBlockFlow>(*child))
maxLineCount = std::max(maxLineCount, lineCountFor(downcast<RenderBlockFlow>(*child)));
Expand Down
1 change: 1 addition & 0 deletions Source/WebCore/rendering/RenderDeprecatedFlexibleBox.h
Expand Up @@ -63,6 +63,7 @@ class RenderDeprecatedFlexibleBox final : public RenderBlock {
bool isHorizontal() const { return style().boxOrient() == BoxOrient::Horizontal; }

void applyLineClamp(FlexBoxIterator&, bool relayoutChildren);
bool applyModernLineClamp(FlexBoxIterator&);
void clearLineClamp();

bool m_stretchingChildren;
Expand Down
7 changes: 7 additions & 0 deletions Source/WebCore/rendering/RenderLayoutState.h
Expand Up @@ -89,6 +89,7 @@ class RenderLayoutState {
#endif

bool hasLineClamp() const { return m_maximumLineCountForLineClamp.has_value(); }
void resetLineClamp();
void setMaximumLineCountForLineClamp(size_t maximumLineCount) { m_maximumLineCountForLineClamp = maximumLineCount; }
std::optional<size_t> maximumLineCountForLineClamp() { return m_maximumLineCountForLineClamp; }
void setVisibleLineCountForLineClamp(size_t visibleLineCount) { m_visibleLineCountForLineClamp = visibleLineCount; }
Expand Down Expand Up @@ -184,4 +185,10 @@ class PaginatedLayoutStateMaintainer {
bool m_pushed { false };
};

inline void RenderLayoutState::resetLineClamp()
{
m_maximumLineCountForLineClamp = { };
m_visibleLineCountForLineClamp = { };
}

} // namespace WebCore

0 comments on commit b360263

Please sign in to comment.