Diff
Modified: trunk/Source/WebCore/ChangeLog (285082 => 285083)
--- trunk/Source/WebCore/ChangeLog 2021-10-30 17:26:57 UTC (rev 285082)
+++ trunk/Source/WebCore/ChangeLog 2021-10-30 19:57:56 UTC (rev 285083)
@@ -1,5 +1,33 @@
2021-10-30 Alan Bujtas <za...@apple.com>
+ [LFC][IFC] Add bidi level to InlineDisplay::Box
+ https://bugs.webkit.org/show_bug.cgi?id=232531
+
+ Reviewed by Antti Koivisto.
+
+ InlineItem -> Line::Run -> InlineDisplay::Box.
+
+ * layout/formattingContexts/inline/InlineDisplayContentBuilder.cpp:
+ (WebCore::Layout::InlineDisplayContentBuilder::build):
+ (WebCore::Layout::InlineDisplayContentBuilder::createBoxesAndUpdateGeometryForLineContent):
+ (WebCore::Layout::InlineDisplayContentBuilder::createBoxesAndUpdateGeometryForLineSpanningInlineBoxes):
+ * layout/formattingContexts/inline/InlineLine.cpp:
+ (WebCore::Layout::Line::appendTextContent):
+ (WebCore::Layout::m_bidiLevel):
+ (WebCore::Layout::Line::Run::Run):
+ (WebCore::Layout::Line::Run::expand):
+ * layout/formattingContexts/inline/InlineLine.h:
+ (WebCore::Layout::Line::Run::bidiLevel const):
+ * layout/formattingContexts/inline/display/InlineDisplayBox.h:
+ (WebCore::InlineDisplay::Box::Box):
+ (WebCore::InlineDisplay::Box::bidiLevel const):
+ * layout/integration/InlineIteratorBoxModernPath.h:
+ (WebCore::InlineIterator::BoxModernPath::bidiLevel const):
+ * layout/integration/LayoutIntegrationPagination.cpp:
+ (WebCore::LayoutIntegration::makeAdjustedContent):
+
+2021-10-30 Alan Bujtas <za...@apple.com>
+
[LFC][IFC] Add skeleton implementation for bidi content handling
https://bugs.webkit.org/show_bug.cgi?id=232524
Modified: trunk/Source/WebCore/layout/formattingContexts/inline/InlineDisplayContentBuilder.cpp (285082 => 285083)
--- trunk/Source/WebCore/layout/formattingContexts/inline/InlineDisplayContentBuilder.cpp 2021-10-30 17:26:57 UTC (rev 285082)
+++ trunk/Source/WebCore/layout/formattingContexts/inline/InlineDisplayContentBuilder.cpp 2021-10-30 19:57:56 UTC (rev 285083)
@@ -60,7 +60,7 @@
// Every line starts with a root box, even the empty ones.
auto rootInlineBoxRect = lineBox.logicalRectForRootInlineBox();
rootInlineBoxRect.moveBy(lineBoxLogicalTopLeft);
- boxes.append({ lineIndex, InlineDisplay::Box::Type::RootInlineBox, root(), rootInlineBoxRect, rootInlineBoxRect, { }, { }, lineBox.rootInlineBox().hasContent() });
+ boxes.append({ lineIndex, InlineDisplay::Box::Type::RootInlineBox, root(), UBIDI_DEFAULT_LTR, rootInlineBoxRect, rootInlineBoxRect, { }, { }, lineBox.rootInlineBox().hasContent() });
createBoxesAndUpdateGeometryForLineSpanningInlineBoxes(lineBox, lineBoxLogicalTopLeft, lineIndex, boxes);
createBoxesAndUpdateGeometryForLineContent(lineContent, lineBox, lineBoxLogicalTopLeft, lineIndex, boxes);
@@ -105,6 +105,7 @@
boxes.append({ lineIndex
, InlineDisplay::Box::Type::Text
, layoutBox
+ , lineRun.bidiLevel()
, textRunRect
, inkOverflow()
, lineRun.expansion()
@@ -120,6 +121,7 @@
boxes.append({ lineIndex
, InlineDisplay::Box::Type::SoftLineBreak
, layoutBox
+ , lineRun.bidiLevel()
, softLineBreakRunRect
, softLineBreakRunRect
, lineRun.expansion()
@@ -130,7 +132,7 @@
// Only hard linebreaks have associated layout boxes.
auto lineBreakBoxRect = lineBox.logicalRectForLineBreakBox(layoutBox);
lineBreakBoxRect.moveBy(lineBoxLogicalTopLeft);
- boxes.append({ lineIndex, InlineDisplay::Box::Type::LineBreakBox, layoutBox, lineBreakBoxRect, lineBreakBoxRect, lineRun.expansion(), { } });
+ boxes.append({ lineIndex, InlineDisplay::Box::Type::LineBreakBox, layoutBox, lineRun.bidiLevel(), lineBreakBoxRect, lineBreakBoxRect, lineRun.expansion(), { } });
auto& boxGeometry = formattingState.boxGeometry(layoutBox);
boxGeometry.setLogicalTopLeft(toLayoutPoint(lineBreakBoxRect.topLeft()));
@@ -143,7 +145,7 @@
auto logicalBorderBox = lineBox.logicalBorderBoxForAtomicInlineLevelBox(layoutBox, boxGeometry);
logicalBorderBox.moveBy(lineBoxLogicalTopLeft);
// FIXME: Add ink overflow support for atomic inline level boxes (e.g. box shadow).
- boxes.append({ lineIndex, InlineDisplay::Box::Type::AtomicInlineLevelBox, layoutBox, logicalBorderBox, logicalBorderBox, lineRun.expansion(), { } });
+ boxes.append({ lineIndex, InlineDisplay::Box::Type::AtomicInlineLevelBox, layoutBox, lineRun.bidiLevel(), logicalBorderBox, logicalBorderBox, lineRun.expansion(), { } });
auto borderBoxLogicalTopLeft = logicalBorderBox.topLeft();
// Note that inline boxes are relative to the line and their top position can be negative.
@@ -174,7 +176,7 @@
auto& inlineBox = lineBox.inlineLevelBoxForLayoutBox(layoutBox);
ASSERT(inlineBox.isInlineBox());
ASSERT(inlineBox.isFirstBox());
- boxes.append({ lineIndex, InlineDisplay::Box::Type::NonRootInlineBox, layoutBox, inlineBoxBorderBox, inlineBoxBorderBox, { }, { }, inlineBox.hasContent(), isFirstLastBox(inlineBox) });
+ boxes.append({ lineIndex, InlineDisplay::Box::Type::NonRootInlineBox, layoutBox, lineRun.bidiLevel(), inlineBoxBorderBox, inlineBoxBorderBox, { }, { }, inlineBox.hasContent(), isFirstLastBox(inlineBox) });
}
auto inlineBoxSize = LayoutSize { LayoutUnit::fromFloatCeil(inlineBoxBorderBox.width()), LayoutUnit::fromFloatCeil(inlineBoxBorderBox.height()) };
@@ -200,6 +202,7 @@
}
auto& formattingState = this->formattingState();
+ // FiXME: Now that we have actual line runs on spanning inline boxes (see lineRun.isLineSpanningInlineBoxStart()), move this code over to createBoxesAndUpdateGeometryForLineContent.
for (auto& inlineLevelBox : lineBox.nonRootInlineLevelBoxes()) {
if (!inlineLevelBox.isLineSpanningInlineBox())
continue;
@@ -214,7 +217,7 @@
m_inlineBoxIndexMap.add(&layoutBox, boxes.size());
ASSERT(!inlineLevelBox.isFirstBox());
- boxes.append({ lineIndex, InlineDisplay::Box::Type::NonRootInlineBox, layoutBox, inlineBoxBorderBox, inlineBoxBorderBox, { }, { }, inlineLevelBox.hasContent(), isFirstLastBox(inlineLevelBox) });
+ boxes.append({ lineIndex, InlineDisplay::Box::Type::NonRootInlineBox, layoutBox, UBIDI_DEFAULT_LTR, inlineBoxBorderBox, inlineBoxBorderBox, { }, { }, inlineLevelBox.hasContent(), isFirstLastBox(inlineLevelBox) });
auto inlineBoxSize = LayoutSize { LayoutUnit::fromFloatCeil(inlineBoxBorderBox.width()), LayoutUnit::fromFloatCeil(inlineBoxBorderBox.height()) };
auto logicalRect = Rect { LayoutPoint { inlineBoxBorderBox.topLeft() }, inlineBoxSize };
Modified: trunk/Source/WebCore/layout/formattingContexts/inline/InlineLine.cpp (285082 => 285083)
--- trunk/Source/WebCore/layout/formattingContexts/inline/InlineLine.cpp 2021-10-30 17:26:57 UTC (rev 285082)
+++ trunk/Source/WebCore/layout/formattingContexts/inline/InlineLine.cpp 2021-10-30 19:57:56 UTC (rev 285083)
@@ -320,6 +320,8 @@
auto& lastRun = m_runs.last();
if (&lastRun.layoutBox() != &inlineTextItem.layoutBox())
return true;
+ if (lastRun.bidiLevel() != inlineTextItem.bidiLevel())
+ return true;
if (!lastRun.isText())
return true;
if (lastRun.hasCollapsedTrailingWhitespace())
@@ -558,6 +560,7 @@
, m_logicalLeft(logicalLeft)
, m_logicalWidth(logicalWidth)
, m_style({ { }, style.direction(), { }, { } })
+ , m_bidiLevel(inlineItem.bidiLevel())
{
}
@@ -565,6 +568,7 @@
: m_type(toLineRunType(zeroWidhtInlineItem.type()))
, m_layoutBox(&zeroWidhtInlineItem.layoutBox())
, m_logicalLeft(logicalLeft)
+ , m_bidiLevel(zeroWidhtInlineItem.bidiLevel())
{
}
@@ -573,6 +577,7 @@
, m_layoutBox(&lineSpanningInlineBoxItem.layoutBox())
, m_logicalLeft(logicalLeft)
, m_logicalWidth(logicalWidth)
+ , m_bidiLevel(lineSpanningInlineBoxItem.bidiLevel())
{
ASSERT(lineSpanningInlineBoxItem.isInlineBoxStart());
}
@@ -582,6 +587,7 @@
, m_layoutBox(&softLineBreakItem.layoutBox())
, m_logicalLeft(logicalLeft)
, m_textContent({ softLineBreakItem.position(), 1 })
+ , m_bidiLevel(softLineBreakItem.bidiLevel())
{
}
@@ -594,6 +600,7 @@
, m_trailingWhitespaceWidth(m_trailingWhitespaceType != TrailingWhitespace::None ? logicalWidth : InlineLayoutUnit { })
, m_textContent({ inlineTextItem.start(), m_trailingWhitespaceType == TrailingWhitespace::Collapsed ? 1 : inlineTextItem.length() })
, m_style({ style.whiteSpace() == WhiteSpace::PreWrap, style.direction(), style.letterSpacing(), style.hasTextCombine() })
+ , m_bidiLevel(inlineTextItem.bidiLevel())
{
}
@@ -602,6 +609,7 @@
ASSERT(!hasCollapsedTrailingWhitespace());
ASSERT(isText() && inlineTextItem.isText());
ASSERT(m_layoutBox == &inlineTextItem.layoutBox());
+ ASSERT(m_bidiLevel == inlineTextItem.bidiLevel());
m_logicalWidth += logicalWidth;
m_trailingWhitespaceType = trailingWhitespaceType(inlineTextItem);
Modified: trunk/Source/WebCore/layout/formattingContexts/inline/InlineLine.h (285082 => 285083)
--- trunk/Source/WebCore/layout/formattingContexts/inline/InlineLine.h 2021-10-30 17:26:57 UTC (rev 285082)
+++ trunk/Source/WebCore/layout/formattingContexts/inline/InlineLine.h 2021-10-30 19:57:56 UTC (rev 285083)
@@ -30,6 +30,7 @@
#include "InlineDisplayBox.h"
#include "InlineItem.h"
#include "InlineTextItem.h"
+#include <unicode/ubidi.h>
namespace WebCore {
namespace Layout {
@@ -107,6 +108,8 @@
InlineLayoutUnit letterSpacing() const;
bool hasTextCombine() const;
+ UBiDiLevel bidiLevel() const { return m_bidiLevel; }
+
private:
friend class Line;
@@ -153,6 +156,7 @@
bool hasTextCombine { false };
};
Style m_style { };
+ UBiDiLevel m_bidiLevel { UBIDI_DEFAULT_LTR };
};
using RunList = Vector<Run, 10>;
const RunList& runs() const { return m_runs; }
Modified: trunk/Source/WebCore/layout/formattingContexts/inline/display/InlineDisplayBox.h (285082 => 285083)
--- trunk/Source/WebCore/layout/formattingContexts/inline/display/InlineDisplayBox.h 2021-10-30 17:26:57 UTC (rev 285082)
+++ trunk/Source/WebCore/layout/formattingContexts/inline/display/InlineDisplayBox.h 2021-10-30 19:57:56 UTC (rev 285083)
@@ -30,6 +30,7 @@
#include "InlineRect.h"
#include "LayoutBox.h"
#include "TextFlags.h"
+#include <unicode/ubidi.h>
#include <wtf/OptionSet.h>
namespace WebCore {
@@ -72,7 +73,7 @@
First = 1 << 0,
Last = 1 << 1
};
- Box(size_t lineIndex, Type, const Layout::Box&, const Layout::InlineRect&, const Layout::InlineRect& inkOverflow, Expansion, std::optional<Text> = std::nullopt, bool hasContent = true, OptionSet<PositionWithinInlineLevelBox> = { PositionWithinInlineLevelBox::First, PositionWithinInlineLevelBox::Last });
+ Box(size_t lineIndex, Type, const Layout::Box&, UBiDiLevel, const Layout::InlineRect&, const Layout::InlineRect& inkOverflow, Expansion, std::optional<Text> = std::nullopt, bool hasContent = true, OptionSet<PositionWithinInlineLevelBox> = { PositionWithinInlineLevelBox::First, PositionWithinInlineLevelBox::Last });
bool isText() const { return m_type == Type::Text; }
bool isSoftLineBreak() const { return m_type == Type::SoftLineBreak; }
@@ -87,6 +88,8 @@
bool isNonRootInlineLevelBox() const { return isInlineLevelBox() && !isRootInlineBox(); }
Type type() const { return m_type; }
+ UBiDiLevel bidiLevel() const { return m_bidiLevel; }
+
bool hasContent() const { return m_hasContent; }
const Layout::InlineRect& logicalRect() const { return m_logicalRect; }
@@ -125,6 +128,7 @@
const size_t m_lineIndex { 0 };
const Type m_type { Type::GenericInlineLevelBox };
CheckedRef<const Layout::Box> m_layoutBox;
+ UBiDiLevel m_bidiLevel { UBIDI_DEFAULT_LTR };
Layout::InlineRect m_logicalRect;
Layout::InlineRect m_inkOverflow;
bool m_hasContent : 1;
@@ -134,10 +138,11 @@
std::optional<Text> m_text;
};
-inline Box::Box(size_t lineIndex, Type type, const Layout::Box& layoutBox, const Layout::InlineRect& logicalRect, const Layout::InlineRect& inkOverflow, Expansion expansion, std::optional<Text> text, bool hasContent, OptionSet<PositionWithinInlineLevelBox> positionWithinInlineLevelBox)
+inline Box::Box(size_t lineIndex, Type type, const Layout::Box& layoutBox, UBiDiLevel bidiLevel, const Layout::InlineRect& logicalRect, const Layout::InlineRect& inkOverflow, Expansion expansion, std::optional<Text> text, bool hasContent, OptionSet<PositionWithinInlineLevelBox> positionWithinInlineLevelBox)
: m_lineIndex(lineIndex)
, m_type(type)
, m_layoutBox(layoutBox)
+ , m_bidiLevel(bidiLevel)
, m_logicalRect(logicalRect)
, m_inkOverflow(inkOverflow)
, m_hasContent(hasContent)
Modified: trunk/Source/WebCore/layout/integration/InlineIteratorBoxModernPath.h (285082 => 285083)
--- trunk/Source/WebCore/layout/integration/InlineIteratorBoxModernPath.h 2021-10-30 17:26:57 UTC (rev 285082)
+++ trunk/Source/WebCore/layout/integration/InlineIteratorBoxModernPath.h 2021-10-30 19:57:56 UTC (rev 285083)
@@ -61,7 +61,7 @@
unsigned minimumCaretOffset() const { return isText() ? start() : 0; }
unsigned maximumCaretOffset() const { return isText() ? end() : 1; }
- unsigned char bidiLevel() const { return 0; }
+ unsigned char bidiLevel() const { return box().bidiLevel(); }
bool hasHyphen() const { return box().text()->hasHyphen(); }
StringView text() const { return box().text()->originalContent(); }
Modified: trunk/Source/WebCore/layout/integration/LayoutIntegrationPagination.cpp (285082 => 285083)
--- trunk/Source/WebCore/layout/integration/LayoutIntegrationPagination.cpp 2021-10-30 17:26:57 UTC (rev 285082)
+++ trunk/Source/WebCore/layout/integration/LayoutIntegrationPagination.cpp 2021-10-30 19:57:56 UTC (rev 285083)
@@ -146,6 +146,7 @@
box.lineIndex(),
box.type(),
box.layoutBox(),
+ box.bidiLevel(),
moveVertically(box.logicalRect(), offset),
moveVertically(box.inkOverflow(), offset),
box.expansion(),