Changeset 241023 in webkit
- Timestamp:
- Feb 6, 2019 9:04:44 AM (5 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 1 added
- 1 deleted
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r241022 r241023 1 2019-02-06 Zalan Bujtas <zalan@apple.com> 2 3 [LFC][IFC] Move line layout code to a dedicated file 4 https://bugs.webkit.org/show_bug.cgi?id=194328 5 6 Reviewed by Antti Koivisto. 7 8 * Sources.txt: 9 * WebCore.xcodeproj/project.pbxproj: 10 * layout/inlineformatting/InlineFormattingContext.cpp: 11 (WebCore::Layout::InlineFormattingContext::layout const): 12 (WebCore::Layout::isTrimmableContent): Deleted. 13 (WebCore::Layout::InlineFormattingContext::initializeNewLine const): Deleted. 14 (WebCore::Layout::InlineFormattingContext::splitInlineRunIfNeeded const): Deleted. 15 (WebCore::Layout::InlineFormattingContext::createFinalRuns const): Deleted. 16 (WebCore::Layout::InlineFormattingContext::postProcessInlineRuns const): Deleted. 17 (WebCore::Layout::InlineFormattingContext::closeLine const): Deleted. 18 (WebCore::Layout::InlineFormattingContext::appendContentToLine const): Deleted. 19 (WebCore::Layout::InlineFormattingContext::layoutInlineContent const): Deleted. 20 (WebCore::Layout::InlineFormattingContext::computeFloatPosition const): Deleted. 21 (WebCore::Layout::InlineFormattingContext::placeInFlowPositionedChildren const): Deleted. 22 * layout/inlineformatting/InlineFormattingContext.h: 23 (WebCore::Layout::InlineFormattingContext::LineLayout::Line::hasContent const): 24 (WebCore::Layout::InlineFormattingContext::LineLayout::Line::isClosed const): 25 (WebCore::Layout::InlineFormattingContext::LineLayout::Line::isFirstLine const): 26 (WebCore::Layout::InlineFormattingContext::LineLayout::Line::runs): 27 (WebCore::Layout::InlineFormattingContext::LineLayout::Line::contentLogicalLeft const): 28 (WebCore::Layout::InlineFormattingContext::LineLayout::Line::availableWidth const): 29 (WebCore::Layout::InlineFormattingContext::LineLayout::Line::lastRunType const): 30 (WebCore::Layout::InlineFormattingContext::LineLayout::Line::logicalTop const): 31 (WebCore::Layout::InlineFormattingContext::LineLayout::Line::logicalBottom const): 32 (WebCore::Layout::InlineFormattingContext::LineLayout::Line::logicalHeight const): 33 (WebCore::Layout::InlineFormattingContext::Line::hasContent const): Deleted. 34 (WebCore::Layout::InlineFormattingContext::Line::isClosed const): Deleted. 35 (WebCore::Layout::InlineFormattingContext::Line::isFirstLine const): Deleted. 36 (WebCore::Layout::InlineFormattingContext::Line::runs): Deleted. 37 (WebCore::Layout::InlineFormattingContext::Line::contentLogicalLeft const): Deleted. 38 (WebCore::Layout::InlineFormattingContext::Line::availableWidth const): Deleted. 39 (WebCore::Layout::InlineFormattingContext::Line::lastRunType const): Deleted. 40 (WebCore::Layout::InlineFormattingContext::Line::logicalTop const): Deleted. 41 (WebCore::Layout::InlineFormattingContext::Line::logicalBottom const): Deleted. 42 (WebCore::Layout::InlineFormattingContext::Line::logicalHeight const): Deleted. 43 * layout/inlineformatting/InlineFormattingContextGeometry.cpp: 44 (WebCore::Layout::adjustedLineLogicalLeft): Deleted. 45 (WebCore::Layout::InlineFormattingContext::Geometry::justifyRuns): Deleted. 46 (WebCore::Layout::InlineFormattingContext::Geometry::computeExpansionOpportunities): Deleted. 47 (WebCore::Layout::InlineFormattingContext::Geometry::alignRuns): Deleted. 48 (WebCore::Layout::InlineFormattingContext::Geometry::runWidth): Deleted. 49 * layout/inlineformatting/Line.cpp: 50 (WebCore::Layout::InlineFormattingContext::LineLayout::Line::init): 51 (WebCore::Layout::InlineFormattingContext::LineLayout::Line::adjustLogicalLeft): 52 (WebCore::Layout::InlineFormattingContext::LineLayout::Line::adjustLogicalRight): 53 (WebCore::Layout::InlineFormattingContext::LineLayout::Line::contentLogicalRight const): 54 (WebCore::Layout::InlineFormattingContext::LineLayout::Line::appendContent): 55 (WebCore::Layout::InlineFormattingContext::LineLayout::Line::close): 56 (WebCore::Layout::InlineFormattingContext::Line::init): Deleted. 57 (WebCore::Layout::InlineFormattingContext::Line::adjustLogicalLeft): Deleted. 58 (WebCore::Layout::InlineFormattingContext::Line::adjustLogicalRight): Deleted. 59 (WebCore::Layout::InlineFormattingContext::Line::contentLogicalRight const): Deleted. 60 (WebCore::Layout::InlineFormattingContext::Line::appendContent): Deleted. 61 (WebCore::Layout::InlineFormattingContext::Line::close): Deleted. 62 1 63 2019-02-06 Youenn Fablet <youenn@apple.com> 2 64 -
trunk/Source/WebCore/Sources.txt
r240898 r241023 1341 1341 layout/inlineformatting/InlineFormattingContext.cpp 1342 1342 layout/inlineformatting/InlineFormattingContextGeometry.cpp 1343 layout/inlineformatting/InlineFormattingContextLineLayout.cpp 1343 1344 layout/inlineformatting/InlineFormattingState.cpp 1344 1345 layout/inlineformatting/InlineInvalidation.cpp 1345 1346 layout/inlineformatting/InlineLineBreaker.cpp 1346 1347 layout/inlineformatting/InlineRunProvider.cpp 1347 layout/inlineformatting/Line.cpp1348 1348 layout/inlineformatting/text/TextUtil.cpp 1349 1349 layout/layouttree/LayoutBlockContainer.cpp -
trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj
r240994 r241023 9197 9197 6F0830DF20B46951008A945B /* BlockFormattingContextGeometry.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = BlockFormattingContextGeometry.cpp; sourceTree = "<group>"; }; 9198 9198 6F219D742178D37100BB033C /* InlineRun.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InlineRun.h; sourceTree = "<group>"; }; 9199 6F219D762178D37100BB033C /* Line.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Line.cpp; sourceTree = "<group>"; };9200 9199 6F222B741AB52D640094651A /* WebGLVertexArrayObjectBase.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WebGLVertexArrayObjectBase.h; sourceTree = "<group>"; }; 9201 9200 6F222B751AB52D8A0094651A /* WebGLVertexArrayObjectBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebGLVertexArrayObjectBase.cpp; sourceTree = "<group>"; }; 9201 6F25B200220A85AB0000011B /* InlineFormattingContextLineLayout.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = InlineFormattingContextLineLayout.cpp; sourceTree = "<group>"; }; 9202 9202 6F35EFAF2187CBD50044E0F4 /* InlineFormattingContextGeometry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InlineFormattingContextGeometry.cpp; sourceTree = "<group>"; }; 9203 9203 6F3E1F5F2136141700A65A08 /* FloatBox.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = FloatBox.cpp; sourceTree = "<group>"; }; … … 16457 16457 6F7CA3C8208C2B2E002F29AB /* InlineFormattingContext.h */, 16458 16458 6F35EFAF2187CBD50044E0F4 /* InlineFormattingContextGeometry.cpp */, 16459 6F25B200220A85AB0000011B /* InlineFormattingContextLineLayout.cpp */, 16459 16460 115CFA7D208B8E10001E6991 /* InlineFormattingState.cpp */, 16460 16461 115CFA7C208B8E10001E6991 /* InlineFormattingState.h */, … … 16467 16468 6F5217C62177F5A6006583BB /* InlineRunProvider.cpp */, 16468 16469 6F5217C42177F5A6006583BB /* InlineRunProvider.h */, 16469 6F219D762178D37100BB033C /* Line.cpp */,16470 16470 ); 16471 16471 path = inlineformatting; -
trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.cpp
r240975 r241023 29 29 #if ENABLE(LAYOUT_FORMATTING_CONTEXT) 30 30 31 #include "FloatingContext.h"32 #include "FloatingState.h"33 31 #include "InlineFormattingState.h" 34 32 #include "InlineLineBreaker.h" … … 88 86 InlineRunProvider inlineRunProvider; 89 87 collectInlineContent(inlineRunProvider); 90 layoutInlineContent(inlineRunProvider);88 LineLayout(*this).layout(inlineRunProvider); 91 89 LOG_WITH_STREAM(FormattingContextLayout, stream << "[End] -> inline formatting context -> formatting root(" << &root << ")"); 92 }93 94 static bool isTrimmableContent(const InlineLineBreaker::Run& run)95 {96 return run.content.isWhitespace() && run.content.style().collapseWhiteSpace();97 }98 99 void InlineFormattingContext::initializeNewLine(Line& line) const100 {101 auto& formattingRoot = downcast<Container>(root());102 auto& formattingRootDisplayBox = layoutState().displayBoxForLayoutBox(formattingRoot);103 104 auto lineLogicalLeft = formattingRootDisplayBox.contentBoxLeft();105 auto lineLogicalTop = line.isFirstLine() ? formattingRootDisplayBox.contentBoxTop() : line.logicalBottom();106 auto availableWidth = formattingRootDisplayBox.contentBoxWidth();107 108 // Check for intruding floats and adjust logical left/available width for this line accordingly.109 auto& floatingState = formattingState().floatingState();110 if (!floatingState.isEmpty()) {111 auto floatConstraints = floatingState.constraints({ lineLogicalTop }, formattingRoot);112 // Check if these constraints actually put limitation on the line.113 if (floatConstraints.left && *floatConstraints.left <= formattingRootDisplayBox.contentBoxLeft())114 floatConstraints.left = { };115 116 if (floatConstraints.right && *floatConstraints.right >= formattingRootDisplayBox.contentBoxRight())117 floatConstraints.right = { };118 119 if (floatConstraints.left && floatConstraints.right) {120 ASSERT(*floatConstraints.left < *floatConstraints.right);121 availableWidth = *floatConstraints.right - *floatConstraints.left;122 lineLogicalLeft = *floatConstraints.left;123 } else if (floatConstraints.left) {124 ASSERT(*floatConstraints.left > lineLogicalLeft);125 availableWidth -= (*floatConstraints.left - lineLogicalLeft);126 lineLogicalLeft = *floatConstraints.left;127 } else if (floatConstraints.right) {128 ASSERT(*floatConstraints.right > lineLogicalLeft);129 availableWidth = *floatConstraints.right - lineLogicalLeft;130 }131 }132 133 line.init({ lineLogicalLeft, lineLogicalTop }, availableWidth, formattingRoot.style().computedLineHeight());134 }135 136 void InlineFormattingContext::splitInlineRunIfNeeded(const InlineRun& inlineRun, InlineRuns& splitRuns) const137 {138 ASSERT(inlineRun.textContext());139 ASSERT(inlineRun.overlapsMultipleInlineItems());140 // In certain cases, a run can overlap multiple inline elements like this:141 // <span>normal text content</span><span style="position: relative; left: 10px;">but this one needs a dedicated run</span><span>end of text</span>142 // The content above generates one long run <normal text contentbut this one needs dedicated runend of text>143 // However, since the middle run is positioned, it needs to be moved independently from the rest of the content, hence it needs a dedicated inline run.144 145 // 1. Start with the first inline item (element) and travers the list until146 // 2. either find an inline item that needs a dedicated run or we reach the end of the run147 // 3. Create dedicate inline runs.148 auto& inlineContent = formattingState().inlineContent();149 auto contentStart = inlineRun.logicalLeft();150 auto startPosition = inlineRun.textContext()->start();151 auto remaningLength = inlineRun.textContext()->length();152 153 struct Uncommitted {154 const InlineItem* firstInlineItem { nullptr };155 const InlineItem* lastInlineItem { nullptr };156 unsigned length { 0 };157 };158 Optional<Uncommitted> uncommitted;159 160 auto commit = [&] {161 if (!uncommitted)162 return;163 164 contentStart += uncommitted->firstInlineItem->nonBreakableStart();165 166 auto runWidth = Geometry::runWidth(inlineContent, *uncommitted->firstInlineItem, startPosition, uncommitted->length, contentStart);167 auto run = InlineRun { { inlineRun.logicalTop(), contentStart, runWidth, inlineRun.logicalHeight() }, *uncommitted->firstInlineItem };168 run.setTextContext({ startPosition, uncommitted->length });169 splitRuns.append(run);170 171 contentStart += runWidth + uncommitted->lastInlineItem->nonBreakableEnd();172 173 startPosition = 0;174 uncommitted = { };175 };176 177 for (auto iterator = inlineContent.find(const_cast<InlineItem*>(&inlineRun.inlineItem())); iterator != inlineContent.end() && remaningLength > 0; ++iterator) {178 auto& inlineItem = **iterator;179 180 // Skip all non-inflow boxes (floats, out-of-flow positioned elements). They don't participate in the inline run context.181 if (!inlineItem.layoutBox().isInFlow())182 continue;183 184 auto currentLength = [&] {185 return std::min(remaningLength, inlineItem.textContent().length() - startPosition);186 };187 188 // 1. Break before/after -> requires dedicated run -> commit what we've got so far and also commit the current inline element as a separate inline run.189 // 2. Break at the beginning of the inline element -> commit what we've got so far. Current element becomes the first uncommitted.190 // 3. Break at the end of the inline element -> commit what we've got so far including the current element.191 // 4. Inline element does not require run breaking -> add current inline element to uncommitted. Jump to the next element.192 auto detachingRules = inlineItem.detachingRules();193 194 // #1195 if (detachingRules.containsAll({ InlineItem::DetachingRule::BreakAtStart, InlineItem::DetachingRule::BreakAtEnd })) {196 commit();197 auto contentLength = currentLength();198 uncommitted = Uncommitted { &inlineItem, &inlineItem, contentLength };199 remaningLength -= contentLength;200 commit();201 continue;202 }203 204 // #2205 if (detachingRules.contains(InlineItem::DetachingRule::BreakAtStart))206 commit();207 208 // Add current inline item to uncommitted.209 // #3 and #4210 auto contentLength = currentLength();211 if (!uncommitted)212 uncommitted = Uncommitted { &inlineItem, &inlineItem, 0 };213 uncommitted->length += contentLength;214 uncommitted->lastInlineItem = &inlineItem;215 remaningLength -= contentLength;216 217 // #3218 if (detachingRules.contains(InlineItem::DetachingRule::BreakAtEnd))219 commit();220 }221 // Either all inline elements needed dedicated runs or neither of them.222 if (!remaningLength || remaningLength == inlineRun.textContext()->length())223 return;224 225 commit();226 }227 228 void InlineFormattingContext::createFinalRuns(Line& line) const229 {230 auto& inlineFormattingState = formattingState();231 for (auto& inlineRun : line.runs()) {232 if (inlineRun.overlapsMultipleInlineItems()) {233 InlineRuns splitRuns;234 splitInlineRunIfNeeded(inlineRun, splitRuns);235 for (auto& splitRun : splitRuns)236 inlineFormattingState.appendInlineRun(splitRun);237 238 if (!splitRuns.isEmpty())239 continue;240 }241 242 auto finalRun = [&] {243 auto& inlineItem = inlineRun.inlineItem();244 if (inlineItem.detachingRules().isEmpty())245 return inlineRun;246 247 InlineRun adjustedRun = inlineRun;248 auto width = inlineRun.logicalWidth() - inlineItem.nonBreakableStart() - inlineItem.nonBreakableEnd();249 adjustedRun.setLogicalLeft(inlineRun.logicalLeft() + inlineItem.nonBreakableStart());250 adjustedRun.setLogicalWidth(width);251 return adjustedRun;252 };253 254 inlineFormattingState.appendInlineRun(finalRun());255 }256 }257 258 void InlineFormattingContext::postProcessInlineRuns(Line& line, IsLastLine isLastLine) const259 {260 Geometry::alignRuns(root().style().textAlign(), line, isLastLine);261 auto firstRunIndex = formattingState().inlineRuns().size();262 createFinalRuns(line);263 264 placeInFlowPositionedChildren(firstRunIndex);265 }266 267 void InlineFormattingContext::closeLine(Line& line, IsLastLine isLastLine) const268 {269 line.close();270 if (!line.hasContent())271 return;272 273 postProcessInlineRuns(line, isLastLine);274 }275 276 void InlineFormattingContext::appendContentToLine(Line& line, const InlineRunProvider::Run& run, const LayoutSize& runSize) const277 {278 auto lastRunType = line.lastRunType();279 line.appendContent(run, runSize);280 281 if (root().style().textAlign() == TextAlignMode::Justify)282 Geometry::computeExpansionOpportunities(line, run, lastRunType.valueOr(InlineRunProvider::Run::Type::NonWhitespace));283 }284 285 void InlineFormattingContext::layoutInlineContent(const InlineRunProvider& inlineRunProvider) const286 {287 auto& layoutState = this->layoutState();288 auto& inlineFormattingState = formattingState();289 auto floatingContext = FloatingContext { inlineFormattingState.floatingState() };290 291 Line line;292 initializeNewLine(line);293 294 InlineLineBreaker lineBreaker(layoutState, inlineFormattingState.inlineContent(), inlineRunProvider.runs());295 while (auto run = lineBreaker.nextRun(line.contentLogicalRight(), line.availableWidth(), !line.hasContent())) {296 auto isFirstRun = run->position == InlineLineBreaker::Run::Position::LineBegin;297 auto isLastRun = run->position == InlineLineBreaker::Run::Position::LineEnd;298 auto generatesInlineRun = true;299 300 // Position float and adjust the runs on line.301 if (run->content.isFloat()) {302 auto& floatBox = run->content.inlineItem().layoutBox();303 computeFloatPosition(floatingContext, line, floatBox);304 inlineFormattingState.floatingState().append(floatBox);305 306 auto floatBoxWidth = layoutState.displayBoxForLayoutBox(floatBox).marginBox().width();307 // Shrink availble space for current line and move existing inline runs.308 floatBox.isLeftFloatingPositioned() ? line.adjustLogicalLeft(floatBoxWidth) : line.adjustLogicalRight(floatBoxWidth);309 310 generatesInlineRun = false;311 }312 313 // 1. Initialize new line if needed.314 // 2. Append inline run unless it is skipped.315 // 3. Close current line if needed.316 if (isFirstRun) {317 // When the first run does not generate an actual inline run, the next run comes in first-run as well.318 // No need to spend time on closing/initializing.319 // Skip leading whitespace.320 if (!generatesInlineRun || isTrimmableContent(*run))321 continue;322 323 if (line.hasContent()) {324 // Previous run ended up being at the line end. Adjust the line accordingly.325 if (!line.isClosed())326 closeLine(line, IsLastLine::No);327 initializeNewLine(line);328 }329 }330 331 if (generatesInlineRun) {332 auto width = run->width;333 auto height = run->content.isText() ? LayoutUnit(root().style().computedLineHeight()) : layoutState.displayBoxForLayoutBox(run->content.inlineItem().layoutBox()).height();334 appendContentToLine(line, run->content, { width, height });335 }336 337 if (isLastRun)338 closeLine(line, IsLastLine::No);339 }340 341 closeLine(line, IsLastLine::Yes);342 90 } 343 91 … … 418 166 computeWidthAndMargin(layoutBox); 419 167 computeHeightAndMargin(layoutBox); 420 }421 422 void InlineFormattingContext::computeFloatPosition(const FloatingContext& floatingContext, Line& line, const Box& floatBox) const423 {424 auto& layoutState = this->layoutState();425 ASSERT(layoutState.hasDisplayBox(floatBox));426 auto& displayBox = layoutState.displayBoxForLayoutBox(floatBox);427 428 // Set static position first.429 displayBox.setTopLeft({ line.contentLogicalRight(), line.logicalTop() });430 // Float it.431 displayBox.setTopLeft(floatingContext.positionForFloat(floatBox));432 }433 434 void InlineFormattingContext::placeInFlowPositionedChildren(unsigned fistRunIndex) const435 {436 auto& inlineRuns = formattingState().inlineRuns();437 for (auto runIndex = fistRunIndex; runIndex < inlineRuns.size(); ++runIndex) {438 auto& inlineRun = inlineRuns[runIndex];439 440 auto positionOffset = [&](auto& layoutBox) {441 // FIXME: Need to figure out whether in-flow offset should stick. This might very well be temporary.442 Optional<LayoutSize> offset;443 for (auto* box = &layoutBox; box != &root(); box = box->parent()) {444 if (!box->isInFlowPositioned())445 continue;446 offset = offset.valueOr(LayoutSize()) + Geometry::inFlowPositionedPositionOffset(layoutState(), *box);447 }448 return offset;449 };450 451 if (auto offset = positionOffset(inlineRun.inlineItem().layoutBox())) {452 inlineRun.moveVertically(offset->height());453 inlineRun.moveHorizontally(offset->width());454 }455 }456 168 } 457 169 -
trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.h
r240975 r241023 30 30 #include "DisplayBox.h" 31 31 #include "FormattingContext.h" 32 #include "InlineFormattingState.h" 32 33 #include "InlineRun.h" 33 34 #include <wtf/IsoMalloc.h> … … 36 37 namespace Layout { 37 38 39 class FloatingState; 38 40 class InlineContainer; 39 class InlineFormattingState;40 41 class InlineRunProvider; 42 class Line; 41 43 42 44 // This class implements the layout logic for inline formatting contexts. … … 46 48 public: 47 49 InlineFormattingContext(const Box& formattingContextRoot, InlineFormattingState&); 48 49 50 void layout() const override; 50 51 51 52 private: 52 class Line {53 class LineLayout { 53 54 public: 54 void init(const LayoutPoint& topLeft, LayoutUnit availableWidth, LayoutUnit minimalHeight); 55 void close(); 56 57 void appendContent(const InlineRunProvider::Run&, const LayoutSize&); 58 59 void adjustLogicalLeft(LayoutUnit delta); 60 void adjustLogicalRight(LayoutUnit delta); 61 62 bool hasContent() const { return !m_inlineRuns.isEmpty(); } 63 bool isClosed() const { return m_closed; } 64 bool isFirstLine() const { return m_isFirstLine; } 65 Vector<InlineRun>& runs() { return m_inlineRuns; } 66 67 LayoutUnit contentLogicalRight() const; 68 LayoutUnit contentLogicalLeft() const { return m_logicalRect.left(); } 69 LayoutUnit availableWidth() const { return m_availableWidth; } 70 Optional<InlineRunProvider::Run::Type> lastRunType() const { return m_lastRunType; } 71 72 LayoutUnit logicalTop() const { return m_logicalRect.top(); } 73 LayoutUnit logicalBottom() const { return m_logicalRect.bottom(); } 74 LayoutUnit logicalHeight() const { return logicalBottom() - logicalTop(); } 55 LineLayout(const InlineFormattingContext&); 56 void layout(const InlineRunProvider&) const; 75 57 76 58 private: 77 struct TrailingTrimmableContent { 78 LayoutUnit width; 79 unsigned length; 80 }; 81 Optional<TrailingTrimmableContent> m_trailingTrimmableContent; 82 Optional<InlineRunProvider::Run::Type> m_lastRunType; 83 bool m_lastRunCanExpand { false }; 59 enum class IsLastLine { No, Yes }; 60 void initializeNewLine(Line&) const; 61 void closeLine(Line&, IsLastLine) const; 62 void appendContentToLine(Line&, const InlineRunProvider::Run&, const LayoutSize&) const; 63 void postProcessInlineRuns(Line&, IsLastLine) const; 64 void createFinalRuns(Line&) const; 65 void splitInlineRunIfNeeded(const InlineRun&, InlineRuns& splitRuns) const; 66 void computeFloatPosition(const FloatingContext&, Line&, const Box&) const; 67 void placeInFlowPositionedChildren(unsigned firstRunIndex) const; 68 void alignRuns(TextAlignMode, Line&, IsLastLine) const; 69 void computeExpansionOpportunities(Line&, const InlineRunProvider::Run&, InlineRunProvider::Run::Type lastRunType) const; 70 LayoutUnit runWidth(const InlineContent&, const InlineItem&, ItemPosition from, unsigned length, LayoutUnit contentLogicalLeft) const; 84 71 85 Display::Box::Rect m_logicalRect;86 LayoutUnit m_availableWidth;72 private: 73 static void justifyRuns(Line&); 87 74 88 Vector<InlineRun> m_inlineRuns; 89 bool m_isFirstLine { true }; 90 bool m_closed { true }; 75 private: 76 const InlineFormattingContext& m_formattingContext; 77 InlineFormattingState& m_formattingState; 78 FloatingState& m_floatingState; 79 const Container& m_formattingRoot; 91 80 }; 92 enum class IsLastLine { No, Yes };93 81 94 82 class Geometry : public FormattingContext::Geometry { … … 96 84 static HeightAndMargin inlineBlockHeightAndMargin(const LayoutState&, const Box&); 97 85 static WidthAndMargin inlineBlockWidthAndMargin(LayoutState&, const Box&); 98 static void alignRuns(TextAlignMode, Line&, IsLastLine);99 static void computeExpansionOpportunities(Line&, const InlineRunProvider::Run&, InlineRunProvider::Run::Type lastRunType);100 static LayoutUnit runWidth(const InlineContent&, const InlineItem&, ItemPosition from, unsigned length, LayoutUnit contentLogicalLeft);101 102 private:103 static void justifyRuns(Line&);104 86 }; 105 106 void layoutInlineContent(const InlineRunProvider&) const;107 void initializeNewLine(Line&) const;108 void closeLine(Line&, IsLastLine) const;109 void appendContentToLine(Line&, const InlineRunProvider::Run&, const LayoutSize&) const;110 void postProcessInlineRuns(Line&, IsLastLine) const;111 void createFinalRuns(Line&) const;112 void splitInlineRunIfNeeded(const InlineRun&, InlineRuns& splitRuns) const;113 87 114 88 void layoutFormattingContextRoot(const Box&) const; … … 117 91 void computeHeightAndMargin(const Box&) const; 118 92 void computeWidthAndMargin(const Box&) const; 119 void computeFloatPosition(const FloatingContext&, Line&, const Box&) const;120 void placeInFlowPositionedChildren(unsigned firstRunIndex) const;121 93 122 94 void collectInlineContent(InlineRunProvider&) const; -
trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContextGeometry.cpp
r239609 r241023 79 79 } 80 80 81 static LayoutUnit adjustedLineLogicalLeft(TextAlignMode align, LayoutUnit lineLogicalLeft, LayoutUnit remainingWidth)82 {83 switch (align) {84 case TextAlignMode::Left:85 case TextAlignMode::WebKitLeft:86 case TextAlignMode::Start:87 return lineLogicalLeft;88 case TextAlignMode::Right:89 case TextAlignMode::WebKitRight:90 case TextAlignMode::End:91 return lineLogicalLeft + std::max(remainingWidth, 0_lu);92 case TextAlignMode::Center:93 case TextAlignMode::WebKitCenter:94 return lineLogicalLeft + std::max(remainingWidth / 2, 0_lu);95 case TextAlignMode::Justify:96 ASSERT_NOT_REACHED();97 break;98 }99 ASSERT_NOT_REACHED();100 return lineLogicalLeft;101 }102 103 void InlineFormattingContext::Geometry::justifyRuns(Line& line)104 {105 auto& inlineRuns = line.runs();106 auto& lastInlineRun = inlineRuns.last();107 108 // Adjust (forbid) trailing expansion for the last text run on line.109 auto expansionBehavior = lastInlineRun.expansionOpportunity().behavior;110 // Remove allow and add forbid.111 expansionBehavior ^= AllowTrailingExpansion;112 expansionBehavior |= ForbidTrailingExpansion;113 lastInlineRun.expansionOpportunity().behavior = expansionBehavior;114 115 // Collect expansion opportunities and justify the runs.116 auto widthToDistribute = line.availableWidth();117 if (widthToDistribute <= 0)118 return;119 120 auto expansionOpportunities = 0;121 for (auto& inlineRun : inlineRuns)122 expansionOpportunities += inlineRun.expansionOpportunity().count;123 124 if (!expansionOpportunities)125 return;126 127 float expansion = widthToDistribute.toFloat() / expansionOpportunities;128 LayoutUnit accumulatedExpansion;129 for (auto& inlineRun : inlineRuns) {130 auto expansionForRun = inlineRun.expansionOpportunity().count * expansion;131 132 inlineRun.expansionOpportunity().expansion = expansionForRun;133 inlineRun.setLogicalLeft(inlineRun.logicalLeft() + accumulatedExpansion);134 inlineRun.setLogicalWidth(inlineRun.logicalWidth() + expansionForRun);135 accumulatedExpansion += expansionForRun;136 }137 }138 139 void InlineFormattingContext::Geometry::computeExpansionOpportunities(Line& line, const InlineRunProvider::Run& run, InlineRunProvider::Run::Type lastRunType)140 {141 auto isExpansionOpportunity = [](auto currentRunIsWhitespace, auto lastRunIsWhitespace) {142 return currentRunIsWhitespace || (!currentRunIsWhitespace && !lastRunIsWhitespace);143 };144 145 auto expansionBehavior = [](auto isAtExpansionOpportunity) {146 ExpansionBehavior expansionBehavior = AllowTrailingExpansion;147 expansionBehavior |= isAtExpansionOpportunity ? ForbidLeadingExpansion : AllowLeadingExpansion;148 return expansionBehavior;149 };150 151 auto isAtExpansionOpportunity = isExpansionOpportunity(run.isWhitespace(), lastRunType == InlineRunProvider::Run::Type::Whitespace);152 153 auto& currentInlineRun = line.runs().last();154 auto& expansionOpportunity = currentInlineRun.expansionOpportunity();155 if (isAtExpansionOpportunity)156 ++expansionOpportunity.count;157 158 expansionOpportunity.behavior = expansionBehavior(isAtExpansionOpportunity);159 }160 161 void InlineFormattingContext::Geometry::alignRuns(TextAlignMode textAlign, Line& line, IsLastLine isLastLine)162 {163 auto adjutedTextAlignment = textAlign != TextAlignMode::Justify ? textAlign : isLastLine == IsLastLine::No ? TextAlignMode::Justify : TextAlignMode::Left;164 if (adjutedTextAlignment == TextAlignMode::Justify) {165 justifyRuns(line);166 return;167 }168 169 auto lineLogicalLeft = line.contentLogicalLeft();170 auto adjustedLogicalLeft = adjustedLineLogicalLeft(adjutedTextAlignment, lineLogicalLeft, line.availableWidth());171 if (adjustedLogicalLeft == lineLogicalLeft)172 return;173 174 auto delta = adjustedLogicalLeft - lineLogicalLeft;175 for (auto& inlineRun : line.runs())176 inlineRun.setLogicalLeft(inlineRun.logicalLeft() + delta);177 }178 179 LayoutUnit InlineFormattingContext::Geometry::runWidth(const InlineContent& inlineContent, const InlineItem& inlineItem, ItemPosition from, unsigned length, LayoutUnit contentLogicalLeft)180 {181 LayoutUnit width;182 auto startPosition = from;183 auto iterator = inlineContent.find(const_cast<InlineItem*>(&inlineItem));184 #if !ASSERT_DISABLED185 auto inlineItemEnd = inlineContent.end();186 #endif187 while (length) {188 ASSERT(iterator != inlineItemEnd);189 auto& currentInlineItem = **iterator;190 auto endPosition = std::min<ItemPosition>(startPosition + length, currentInlineItem.textContent().length());191 auto textWidth = TextUtil::width(currentInlineItem, startPosition, endPosition, contentLogicalLeft);192 193 contentLogicalLeft += textWidth;194 width += textWidth;195 length -= (endPosition - startPosition);196 197 startPosition = 0;198 ++iterator;199 }200 return width;201 }202 203 81 } 204 82 }
Note: See TracChangeset
for help on using the changeset viewer.