Diff
Modified: trunk/Source/WebCore/ChangeLog (237287 => 237288)
--- trunk/Source/WebCore/ChangeLog 2018-10-19 16:31:19 UTC (rev 237287)
+++ trunk/Source/WebCore/ChangeLog 2018-10-19 16:41:58 UTC (rev 237288)
@@ -1,5 +1,56 @@
2018-10-19 Zalan Bujtas <za...@apple.com>
+ [LFC][IFC] Add generic inline content handling.
+ https://bugs.webkit.org/show_bug.cgi?id=190713
+
+ Reviewed by Antti Koivisto.
+
+ layoutInlineContent turns InlineLineBreaker::Run objects into final inline runs by
+ resolving heading/trailing whitespace, aligment, expansion opportunities etc.
+ These inline runs are input to the display tree construction.
+
+ * Sources.txt:
+ * WebCore.xcodeproj/project.pbxproj:
+ * layout/displaytree/DisplayBox.h:
+ * layout/inlineformatting/InlineFormattingContext.cpp:
+ (WebCore::Layout::InlineFormattingContext::layout const):
+ (WebCore::Layout::trimLeadingRun):
+ (WebCore::Layout::InlineFormattingContext::layoutInlineContent const):
+ (WebCore::Layout::InlineFormattingContext::computeWidthAndHeight const):
+ * layout/inlineformatting/InlineFormattingContext.h:
+ (WebCore::Layout::InlineFormattingContext::Line::hasContent const):
+ (WebCore::Layout::InlineFormattingContext::Line::contentLogicalLeft const):
+ (WebCore::Layout::InlineFormattingContext::Line::availableWidth const):
+ * layout/inlineformatting/InlineFormattingState.h:
+ (WebCore::Layout::InlineFormattingState::inlineRuns):
+ (WebCore::Layout::InlineFormattingState::appendInlineRun):
+ * layout/inlineformatting/InlineLineBreaker.cpp:
+ (WebCore::Layout::InlineLineBreaker::nextRun):
+ (WebCore::Layout::InlineLineBreaker::nextLayoutRun): Deleted.
+ * layout/inlineformatting/InlineLineBreaker.h:
+ * layout/inlineformatting/InlineRun.h: Added.
+ (WebCore::Layout::InlineRun::logicalLeft const):
+ (WebCore::Layout::InlineRun::logicalRight const):
+ (WebCore::Layout::InlineRun::width const):
+ (WebCore::Layout::InlineRun::setWidth):
+ (WebCore::Layout::InlineRun::setLogicalRight):
+ (WebCore::Layout::InlineRun::TextContext::position const):
+ (WebCore::Layout::InlineRun::TextContext::length const):
+ (WebCore::Layout::InlineRun::TextContext::setLength):
+ (WebCore::Layout::InlineRun::textContext):
+ (WebCore::Layout::InlineRun::inlineItem const):
+ (WebCore::Layout::InlineRun::InlineRun):
+ (WebCore::Layout::InlineRun::TextContext::TextContext):
+ * layout/inlineformatting/Line.cpp: Added.
+ (WebCore::Layout::InlineFormattingContext::Line::Line):
+ (WebCore::Layout::InlineFormattingContext::Line::setConstraints):
+ (WebCore::Layout::isNonCollapsedText):
+ (WebCore::Layout::isTrimmableContent):
+ (WebCore::Layout::InlineFormattingContext::Line::appendContent):
+ (WebCore::Layout::InlineFormattingContext::Line::close):
+
+2018-10-19 Zalan Bujtas <za...@apple.com>
+
[LFC][IFC] Add generic inline line breaker
https://bugs.webkit.org/show_bug.cgi?id=190698
Modified: trunk/Source/WebCore/Sources.txt (237287 => 237288)
--- trunk/Source/WebCore/Sources.txt 2018-10-19 16:31:19 UTC (rev 237287)
+++ trunk/Source/WebCore/Sources.txt 2018-10-19 16:41:58 UTC (rev 237288)
@@ -1261,6 +1261,7 @@
layout/inlineformatting/InlineInvalidation.cpp
layout/inlineformatting/InlineLineBreaker.cpp
layout/inlineformatting/InlineRunProvider.cpp
+layout/inlineformatting/Line.cpp
layout/inlineformatting/textlayout/TextContentProvider.cpp
layout/inlineformatting/textlayout/TextUtil.cpp
layout/inlineformatting/textlayout/simple/SimpleTextRunGenerator.cpp
Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (237287 => 237288)
--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2018-10-19 16:31:19 UTC (rev 237287)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2018-10-19 16:41:58 UTC (rev 237288)
@@ -1988,6 +1988,7 @@
6ED878C5147493F4004C3597 /* RenderTableCaption.h in Headers */ = {isa = PBXBuildFile; fileRef = 6ED878C3147493F4004C3597 /* RenderTableCaption.h */; };
6ED8C37A183BFF8C009E53BD /* BoxShape.h in Headers */ = {isa = PBXBuildFile; fileRef = 6ED8C378183BFF8C009E53BD /* BoxShape.h */; settings = {ATTRIBUTES = (Private, ); }; };
6EE8A77310F803F3005A4A24 /* JSWebGLContextAttributes.h in Headers */ = {isa = PBXBuildFile; fileRef = 6EE8A77110F803F3005A4A24 /* JSWebGLContextAttributes.h */; };
+ 6F219D772178D37200BB033C /* InlineRun.h in Headers */ = {isa = PBXBuildFile; fileRef = 6F219D742178D37100BB033C /* InlineRun.h */; settings = {ATTRIBUTES = (Private, ); }; };
6F222B761AB52D8A0094651A /* WebGLVertexArrayObjectBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6F222B751AB52D8A0094651A /* WebGLVertexArrayObjectBase.cpp */; };
6F3E1F622136142000A65A08 /* FloatBox.h in Headers */ = {isa = PBXBuildFile; fileRef = 6F3E1F612136141700A65A08 /* FloatBox.h */; settings = {ATTRIBUTES = (Private, ); }; };
6F5217C72177F5A7006583BB /* InlineRunProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = 6F5217C42177F5A6006583BB /* InlineRunProvider.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -9065,6 +9066,8 @@
6EE8A77010F803F3005A4A24 /* JSWebGLContextAttributes.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSWebGLContextAttributes.cpp; sourceTree = "<group>"; };
6EE8A77110F803F3005A4A24 /* JSWebGLContextAttributes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSWebGLContextAttributes.h; sourceTree = "<group>"; };
6F0830DF20B46951008A945B /* BlockFormattingContextGeometry.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = BlockFormattingContextGeometry.cpp; sourceTree = "<group>"; };
+ 6F219D742178D37100BB033C /* InlineRun.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InlineRun.h; sourceTree = "<group>"; };
+ 6F219D762178D37100BB033C /* Line.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Line.cpp; sourceTree = "<group>"; };
6F222B741AB52D640094651A /* WebGLVertexArrayObjectBase.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WebGLVertexArrayObjectBase.h; sourceTree = "<group>"; };
6F222B751AB52D8A0094651A /* WebGLVertexArrayObjectBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebGLVertexArrayObjectBase.cpp; sourceTree = "<group>"; };
6F3E1F5F2136141700A65A08 /* FloatBox.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = FloatBox.cpp; sourceTree = "<group>"; };
@@ -16056,6 +16059,8 @@
115CFA9A208BC140001E6991 /* inlineformatting */ = {
isa = PBXGroup;
children = (
+ 6F219D742178D37100BB033C /* InlineRun.h */,
+ 6F219D762178D37100BB033C /* Line.cpp */,
6FE198132178397B00446F08 /* InlineLineBreaker.cpp */,
6FE198152178397C00446F08 /* InlineLineBreaker.h */,
6FE7DDDD20EC6E8B008B5B4E /* textlayout */,
@@ -30453,6 +30458,7 @@
A10BB5851484E3A700B2E87A /* RenderSVGRect.h in Headers */,
436708CD12D9CA4B00044234 /* RenderSVGResource.h in Headers */,
436708CF12D9CA4B00044234 /* RenderSVGResourceClipper.h in Headers */,
+ 6F219D772178D37200BB033C /* InlineRun.h in Headers */,
436708D112D9CA4B00044234 /* RenderSVGResourceContainer.h in Headers */,
436708D312D9CA4B00044234 /* RenderSVGResourceFilter.h in Headers */,
436708D512D9CA4B00044234 /* RenderSVGResourceFilterPrimitive.h in Headers */,
Modified: trunk/Source/WebCore/layout/displaytree/DisplayBox.h (237287 => 237288)
--- trunk/Source/WebCore/layout/displaytree/DisplayBox.h 2018-10-19 16:31:19 UTC (rev 237287)
+++ trunk/Source/WebCore/layout/displaytree/DisplayBox.h 2018-10-19 16:41:58 UTC (rev 237288)
@@ -41,6 +41,7 @@
class FloatBox;
class FormattingContext;
class FloatingContext;
+class InlineFormattingContext;
class LayoutContext;
}
@@ -54,6 +55,7 @@
friend class Layout::FloatBox;
friend class Layout::FormattingContext;
friend class Layout::FloatingContext;
+ friend class Layout::InlineFormattingContext;
friend class Layout::LayoutContext;
Box(const RenderStyle&);
Modified: trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.cpp (237287 => 237288)
--- trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.cpp 2018-10-19 16:31:19 UTC (rev 237287)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.cpp 2018-10-19 16:41:58 UTC (rev 237288)
@@ -30,6 +30,8 @@
#include "FloatingState.h"
#include "InlineFormattingState.h"
+#include "InlineLineBreaker.h"
+#include "InlineRunProvider.h"
#include "LayoutBox.h"
#include "LayoutContainer.h"
#include "LayoutContext.h"
@@ -36,8 +38,6 @@
#include "LayoutInlineBox.h"
#include "LayoutInlineContainer.h"
#include "Logging.h"
-#include "SimpleLineBreaker.h"
-#include "TextContentProvider.h"
#include <wtf/IsoMallocInlines.h>
#include <wtf/text/TextStream.h>
@@ -51,7 +51,7 @@
{
}
-void InlineFormattingContext::layout(LayoutContext& layoutContext, FormattingState& inlineFormattingState) const
+void InlineFormattingContext::layout(LayoutContext& layoutContext, FormattingState& formattingState) const
{
if (!is<Container>(root()))
return;
@@ -58,7 +58,8 @@
LOG_WITH_STREAM(FormattingContextLayout, stream << "[Start] -> inline formatting context -> layout context(" << &layoutContext << ") formatting root(" << &root() << ")");
- TextContentProvider textContentProvider;
+ auto& inlineFormattingState = downcast<InlineFormattingState>(formattingState);
+ InlineRunProvider inlineRunProvider(inlineFormattingState);
auto& formattingRoot = downcast<Container>(root());
auto* layoutBox = formattingRoot.firstInFlowOrFloatingChild();
// Casually walk through the block's descendants and place the inline boxes one after the other as much as we can (yeah, I am looking at you floats).
@@ -68,12 +69,11 @@
layoutBox = downcast<Container>(*layoutBox).firstInFlowOrFloatingChild();
continue;
}
- auto& inlineBox = downcast<InlineBox>(*layoutBox);
- // Only text content at this point.
- if (inlineBox.hasTextContent())
- textContentProvider.appendText(inlineBox.textContent(), inlineBox.style(), true);
- for (; layoutBox; layoutBox = layoutBox->containingBlock()) {
+ inlineRunProvider.append(*layoutBox);
+ computeWidthAndHeight(layoutContext, *layoutBox);
+
+ for (; layoutBox; layoutBox = layoutBox->parent()) {
if (layoutBox == &formattingRoot) {
layoutBox = nullptr;
break;
@@ -86,22 +86,106 @@
ASSERT(!layoutBox || layoutBox->isDescendantOf(formattingRoot));
}
+ layoutInlineContent(layoutContext, inlineFormattingState, inlineRunProvider);
+
+ LOG_WITH_STREAM(FormattingContextLayout, stream << "[End] -> inline formatting context -> layout context(" << &layoutContext << ") formatting root(" << &root() << ")");
+}
+
+static bool trimLeadingRun(const InlineLineBreaker::Run& run)
+{
+ ASSERT(run.position == InlineLineBreaker::Run::Position::LineBegin);
+
+ auto& inlineRun = run.inlineRun;
+ if (!inlineRun.isWhitespace())
+ return false;
+
+ return inlineRun.style().collapseWhiteSpace();
+}
+
+void InlineFormattingContext::layoutInlineContent(const LayoutContext& layoutContext, InlineFormattingState& inlineFormattingState, const InlineRunProvider& inlineRunProvider) const
+{
+ auto& formattingRoot = downcast<Container>(root());
auto& formattingRootDisplayBox = layoutContext.displayBoxForLayoutBox(formattingRoot);
- auto lineLeft = formattingRootDisplayBox.contentBoxLeft();
- auto lineRight = formattingRootDisplayBox.contentBoxRight();
- SimpleLineBreaker::LineConstraintList constraints;
- constraints.append({ { }, lineLeft, lineRight });
- auto textRunList = textContentProvider.textRuns();
- SimpleLineBreaker simpleLineBreaker(textRunList, textContentProvider, WTFMove(constraints), formattingRoot.style());
+ auto lineLogicalLeft = formattingRootDisplayBox.contentBoxLeft();
+ auto availableWidth = formattingRootDisplayBox.contentBoxWidth();
+ auto previousRunPositionIsLineEnd = false;
- // Since we don't yet have a display tree context for inline boxes, let's just cache the runs on the state so that they can be verified against the sll/inline tree runs later.
- ASSERT(is<InlineFormattingState>(inlineFormattingState));
- downcast<InlineFormattingState>(inlineFormattingState).addLayoutRuns(simpleLineBreaker.runs());
+ Line line(inlineFormattingState);
+ line.setConstraints(lineLogicalLeft, availableWidth);
- LOG_WITH_STREAM(FormattingContextLayout, stream << "[End] -> inline formatting context -> layout context(" << &layoutContext << ") formatting root(" << &root() << ")");
+ InlineLineBreaker lineBreaker(layoutContext, inlineFormattingState.inlineContent(), inlineRunProvider.runs());
+ while (auto run = lineBreaker.nextRun(line.contentLogicalLeft(), line.availableWidth(), !line.hasContent())) {
+
+ if (run->position == InlineLineBreaker::Run::Position::LineBegin) {
+ // First run on line.
+
+ // Previous run ended up being at the line end. Adjust the line accordingly.
+ if (!previousRunPositionIsLineEnd) {
+ line.close();
+ line.setConstraints(lineLogicalLeft, availableWidth);
+ }
+ // Skip leading whitespace.
+ if (!trimLeadingRun(*run))
+ line.appendContent(*run);
+ continue;
+ }
+
+ if (run->position == InlineLineBreaker::Run::Position::LineEnd) {
+ // Last run on line.
+ previousRunPositionIsLineEnd = true;
+ line.appendContent(*run);
+ // Move over to the next line.
+ line.close();
+ line.setConstraints(lineLogicalLeft, availableWidth);
+ continue;
+ }
+
+ // This may or may not be the last run on line -but definitely not the first one.
+ line.appendContent(*run);
+ }
+ line.close();
}
+void InlineFormattingContext::computeWidthAndHeight(const LayoutContext& layoutContext, const Box& layoutBox) const
+{
+ if (is<InlineBox>(layoutBox) && downcast<InlineBox>(layoutBox).hasTextContent()) {
+ // Text content width is computed during text run generation. -It does not make any sense to measure unprocessed text here, since it will likely be
+ // split up (or concatenated).
+ return;
+ }
+
+ if (layoutBox.isFloatingPositioned()) {
+ ASSERT_NOT_IMPLEMENTED_YET();
+ return;
+ }
+
+ if (layoutBox.isInlineBlockBox()) {
+ ASSERT_NOT_IMPLEMENTED_YET();
+ return;
+ }
+
+ if (layoutBox.replaced()) {
+ computeBorderAndPadding(layoutContext, layoutBox);
+
+ auto& displayBox = layoutContext.displayBoxForLayoutBox(layoutBox);
+
+ auto widthAndMargin = Geometry::inlineReplacedWidthAndMargin(layoutContext, layoutBox);
+ displayBox.setContentBoxWidth(widthAndMargin.width);
+ displayBox.setHorizontalMargin(widthAndMargin.margin);
+ displayBox.setHorizontalNonComputedMargin(widthAndMargin.nonComputedMargin);
+
+ auto heightAndMargin = Geometry::inlineReplacedHeightAndMargin(layoutContext, layoutBox);
+ displayBox.setContentBoxHeight(heightAndMargin.height);
+ displayBox.setVerticalNonCollapsedMargin(heightAndMargin.margin);
+ displayBox.setVerticalMargin(heightAndMargin.collapsedMargin.value_or(heightAndMargin.margin));
+ return;
+ }
+
+ ASSERT_NOT_REACHED();
+ return;
+}
+
void InlineFormattingContext::computeStaticPosition(const LayoutContext&, const Box&) const
{
}
Modified: trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.h (237287 => 237288)
--- trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.h 2018-10-19 16:31:19 UTC (rev 237287)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.h 2018-10-19 16:41:58 UTC (rev 237288)
@@ -28,13 +28,14 @@
#if ENABLE(LAYOUT_FORMATTING_CONTEXT)
#include "FormattingContext.h"
+#include "InlineLineBreaker.h"
#include <wtf/IsoMalloc.h>
namespace WebCore {
-
namespace Layout {
class InlineFormattingState;
+class InlineRunProvider;
// This class implements the layout logic for inline formatting contexts.
// https://www.w3.org/TR/CSS22/visuren.html#inline-formatting
@@ -46,6 +47,33 @@
void layout(LayoutContext&, FormattingState&) const override;
private:
+ class Line {
+ public:
+ Line(InlineFormattingState&);
+
+ void setConstraints(LayoutUnit lineLogicalLeft, LayoutUnit availableWidth);
+ void appendContent(const InlineLineBreaker::Run&);
+ void close();
+ bool hasContent() const { return !m_isEmpty; }
+ LayoutUnit contentLogicalLeft() const { return m_contentLogicalLeft; }
+ LayoutUnit availableWidth() const { return m_availableWidth; }
+
+ private:
+ struct TrailingTrimmableContent {
+ LayoutUnit width;
+ unsigned length;
+ };
+ std::optional<TrailingTrimmableContent> m_trailingTrimmableContent;
+ InlineFormattingState& m_inlineFormattingState;
+ LayoutUnit m_contentLogicalLeft;
+ LayoutUnit m_availableWidth;
+ bool m_isEmpty { true };
+ bool m_lastRunIsNotCollapsedText { true };
+ };
+
+ void layoutInlineContent(const LayoutContext&, InlineFormattingState&, const InlineRunProvider&) const;
+
+ void computeWidthAndHeight(const LayoutContext&, const Box&) const;
void computeStaticPosition(const LayoutContext&, const Box&) const override;
void computeInFlowPositionedPosition(const LayoutContext&, const Box&) const override;
Modified: trunk/Source/WebCore/layout/inlineformatting/InlineFormattingState.h (237287 => 237288)
--- trunk/Source/WebCore/layout/inlineformatting/InlineFormattingState.h 2018-10-19 16:31:19 UTC (rev 237287)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineFormattingState.h 2018-10-19 16:41:58 UTC (rev 237288)
@@ -29,6 +29,7 @@
#include "FormattingState.h"
#include "InlineItem.h"
+#include "InlineRun.h"
#include "Runs.h"
#include <wtf/IsoMalloc.h>
@@ -47,9 +48,14 @@
void addLayoutRuns(Vector<LayoutRun>&& layoutRuns) { m_layoutRuns = WTFMove(layoutRuns); }
const Vector<LayoutRun>& layoutRuns() const { return m_layoutRuns; }
+ // Temp
+ InlineRuns& inlineRuns() { return m_inlineRuns; }
+ void appendInlineRun(InlineRun inlineRun) { m_inlineRuns.append(inlineRun); }
+
private:
InlineContent m_inlineContent;
Vector<LayoutRun> m_layoutRuns;
+ InlineRuns m_inlineRuns;
};
}
Modified: trunk/Source/WebCore/layout/inlineformatting/InlineLineBreaker.cpp (237287 => 237288)
--- trunk/Source/WebCore/layout/inlineformatting/InlineLineBreaker.cpp 2018-10-19 16:31:19 UTC (rev 237287)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineLineBreaker.cpp 2018-10-19 16:41:58 UTC (rev 237288)
@@ -45,7 +45,7 @@
{
}
-std::optional<InlineLineBreaker::Run> InlineLineBreaker::nextLayoutRun(LayoutUnit contentLogicalLeft, LayoutUnit availableWidth, bool lineIsEmpty)
+std::optional<InlineLineBreaker::Run> InlineLineBreaker::nextRun(LayoutUnit contentLogicalLeft, LayoutUnit availableWidth, bool lineIsEmpty)
{
if (isAtContentEnd())
return std::nullopt;
Modified: trunk/Source/WebCore/layout/inlineformatting/InlineLineBreaker.h (237287 => 237288)
--- trunk/Source/WebCore/layout/inlineformatting/InlineLineBreaker.h 2018-10-19 16:31:19 UTC (rev 237287)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineLineBreaker.h 2018-10-19 16:41:58 UTC (rev 237288)
@@ -45,7 +45,7 @@
InlineRunProvider::Run inlineRun;
LayoutUnit width;
};
- std::optional<Run> nextLayoutRun(LayoutUnit contentLogicalLeft, LayoutUnit availableWidth, bool lineIsEmpty);
+ std::optional<Run> nextRun(LayoutUnit contentLogicalLeft, LayoutUnit availableWidth, bool lineIsEmpty);
private:
enum class LineBreakingBehavior { Keep, Break, WrapToNextLine };
Added: trunk/Source/WebCore/layout/inlineformatting/InlineRun.h (0 => 237288)
--- trunk/Source/WebCore/layout/inlineformatting/InlineRun.h (rev 0)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineRun.h 2018-10-19 16:41:58 UTC (rev 237288)
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2018 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(LAYOUT_FORMATTING_CONTEXT)
+
+#include "InlineRunProvider.h"
+#include "LayoutUnit.h"
+
+namespace WebCore {
+namespace Layout {
+
+struct InlineRun {
+ InlineRun(LayoutUnit logcialLeft, LayoutUnit width, const InlineItem&);
+ InlineRun(LayoutUnit logcialLeft, LayoutUnit width, ItemPosition, unsigned length, const InlineItem&);
+
+ LayoutUnit logicalLeft() const { return m_logicalLeft; }
+ LayoutUnit logicalRight() const { return logicalLeft() + width(); }
+ LayoutUnit width() const { return m_width; }
+
+ void setWidth(LayoutUnit width) { m_width = width; }
+ void setLogicalRight(LayoutUnit logicalRight) { m_width -= (this->logicalRight() - logicalRight); }
+
+ struct TextContext {
+ public:
+ TextContext(ItemPosition, unsigned length);
+
+ ItemPosition position() const { return m_position; }
+ unsigned length() const { return m_length; }
+
+ void setLength(unsigned length) { m_length = length; }
+
+ private:
+ ItemPosition m_position;
+ unsigned m_length;
+ };
+ std::optional<TextContext>& textContext() { return m_textContext; }
+ const InlineItem& inlineItem() const { return m_inlineItem; }
+
+private:
+ LayoutUnit m_logicalLeft;
+ LayoutUnit m_width;
+
+ const InlineItem& m_inlineItem;
+ std::optional<TextContext> m_textContext;
+};
+
+using InlineRuns = Vector<InlineRun>;
+
+inline InlineRun::InlineRun(LayoutUnit logicalLeft, LayoutUnit width, const InlineItem& inlineItem)
+ : m_logicalLeft(logicalLeft)
+ , m_width(width)
+ , m_inlineItem(inlineItem)
+{
+}
+
+inline InlineRun::InlineRun(LayoutUnit logicalLeft, LayoutUnit width, ItemPosition position, unsigned length, const InlineItem& inlineItem)
+ : m_logicalLeft(logicalLeft)
+ , m_width(width)
+ , m_inlineItem(inlineItem)
+ , m_textContext(TextContext { position, length })
+{
+}
+
+inline InlineRun::TextContext::TextContext(ItemPosition position, unsigned length)
+ : m_position(position)
+ , m_length(length)
+{
+}
+
+}
+}
+#endif
Added: trunk/Source/WebCore/layout/inlineformatting/Line.cpp (0 => 237288)
--- trunk/Source/WebCore/layout/inlineformatting/Line.cpp (rev 0)
+++ trunk/Source/WebCore/layout/inlineformatting/Line.cpp 2018-10-19 16:41:58 UTC (rev 237288)
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2018 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "InlineFormattingContext.h"
+#include "InlineFormattingState.h"
+#include "InlineRunProvider.h"
+
+#if ENABLE(LAYOUT_FORMATTING_CONTEXT)
+
+namespace WebCore {
+namespace Layout {
+
+InlineFormattingContext::Line::Line(InlineFormattingState& inlineFormattingState)
+ : m_inlineFormattingState(inlineFormattingState)
+{
+}
+
+void InlineFormattingContext::Line::setConstraints(LayoutUnit lineLogicalLeft, LayoutUnit availableWidth)
+{
+ m_contentLogicalLeft = lineLogicalLeft;
+ m_availableWidth = availableWidth;
+}
+
+static bool isNonCollapsedText(const InlineRunProvider::Run& inlineRun)
+{
+ return inlineRun.isText() && !inlineRun.textContext()->isCollapsed();
+}
+
+static bool isTrimmableContent(const InlineRunProvider::Run& inlineRun)
+{
+ return inlineRun.isWhitespace() && inlineRun.style().collapseWhiteSpace();
+}
+
+void InlineFormattingContext::Line::appendContent(const InlineLineBreaker::Run& run)
+{
+ auto lastRunWasNotCollapsedText = m_lastRunIsNotCollapsedText;
+ auto hadContent = hasContent();
+ auto contentLogicalLeft = m_contentLogicalLeft;
+ m_trailingTrimmableContent = { };
+
+ auto& inlineRun = run.inlineRun;
+ m_availableWidth -= run.width;
+ m_lastRunIsNotCollapsedText = isNonCollapsedText(inlineRun);
+ m_isEmpty = false;
+ m_contentLogicalLeft += run.width;
+
+ // Append this text run to the end of the last text run, if the last run is continuous.
+ if (inlineRun.isText()) {
+ auto textContext = inlineRun.textContext();
+ auto runLength = textContext->isCollapsed() ? 1 : textContext->length();
+
+ if (isTrimmableContent(inlineRun))
+ m_trailingTrimmableContent = TrailingTrimmableContent { run.width, runLength };
+
+ if (hadContent && lastRunWasNotCollapsedText) {
+ auto& inlineRun = m_inlineFormattingState.inlineRuns().last();
+ inlineRun.setWidth(inlineRun.width() + run.width);
+ inlineRun.textContext()->setLength(inlineRun.textContext()->length() + runLength);
+ return;
+ }
+
+ return m_inlineFormattingState.appendInlineRun({ contentLogicalLeft, run.width, textContext->start(), runLength, inlineRun.inlineItem()});
+ }
+
+ m_inlineFormattingState.appendInlineRun({ contentLogicalLeft, run.width, inlineRun.inlineItem() });
+}
+
+void InlineFormattingContext::Line::close()
+{
+ auto trimTrailingContent = [&]() {
+
+ if (!m_trailingTrimmableContent)
+ return;
+
+ auto& lastInlineRun = m_inlineFormattingState.inlineRuns().last();
+ lastInlineRun.setWidth(lastInlineRun.width() - m_trailingTrimmableContent->width);
+ lastInlineRun.textContext()->setLength(lastInlineRun.textContext()->length() - m_trailingTrimmableContent->length);
+
+ if (!lastInlineRun.textContext()->length())
+ m_inlineFormattingState.inlineRuns().removeLast();
+ m_availableWidth += m_trailingTrimmableContent->width;
+ m_trailingTrimmableContent = { };
+ };
+
+ trimTrailingContent();
+ m_isEmpty = true;
+}
+
+}
+}
+
+#endif