| Index: sky/engine/core/rendering/RenderParagraph.cpp
|
| diff --git a/sky/engine/core/rendering/RenderParagraph.cpp b/sky/engine/core/rendering/RenderParagraph.cpp
|
| index a427e45631aaf1f12c7142ba732c404d628a7607..2b04a7efa973d1f46cea2bd965ddbe07292be733 100644
|
| --- a/sky/engine/core/rendering/RenderParagraph.cpp
|
| +++ b/sky/engine/core/rendering/RenderParagraph.cpp
|
| @@ -11,7 +11,6 @@
|
| #include "sky/engine/core/rendering/RenderObjectInlines.h"
|
| #include "sky/engine/core/rendering/RenderView.h"
|
| #include "sky/engine/core/rendering/TextRunConstructor.h"
|
| -#include "sky/engine/core/rendering/TrailingFloatsRootInlineBox.h"
|
| #include "sky/engine/core/rendering/VerticalPositionCache.h"
|
| #include "sky/engine/core/rendering/line/BreakingContextInlineHeaders.h"
|
| #include "sky/engine/core/rendering/line/LineLayoutState.h"
|
| @@ -31,7 +30,7 @@ namespace blink {
|
| using namespace WTF::Unicode;
|
|
|
| RenderParagraph::RenderParagraph(ContainerNode* node)
|
| - : RenderBlockFlow(node)
|
| + : RenderBlock(node)
|
| {
|
| }
|
|
|
| @@ -53,6 +52,34 @@ RenderParagraph* RenderParagraph::createAnonymous(Document& document)
|
| return renderer;
|
| }
|
|
|
| +LayoutUnit RenderParagraph::logicalLeftSelectionOffset(RenderBlock* rootBlock, LayoutUnit position)
|
| +{
|
| + LayoutUnit logicalLeft = logicalLeftOffsetForLine(false);
|
| + if (logicalLeft == logicalLeftOffsetForContent())
|
| + return RenderBlock::logicalLeftSelectionOffset(rootBlock, position);
|
| +
|
| + RenderBlock* cb = this;
|
| + while (cb != rootBlock) {
|
| + logicalLeft += cb->logicalLeft();
|
| + cb = cb->containingBlock();
|
| + }
|
| + return logicalLeft;
|
| +}
|
| +
|
| +LayoutUnit RenderParagraph::logicalRightSelectionOffset(RenderBlock* rootBlock, LayoutUnit position)
|
| +{
|
| + LayoutUnit logicalRight = logicalRightOffsetForLine(false);
|
| + if (logicalRight == logicalRightOffsetForContent())
|
| + return RenderBlock::logicalRightSelectionOffset(rootBlock, position);
|
| +
|
| + RenderBlock* cb = this;
|
| + while (cb != rootBlock) {
|
| + logicalRight += cb->logicalLeft();
|
| + cb = cb->containingBlock();
|
| + }
|
| + return logicalRight;
|
| +}
|
| +
|
| RootInlineBox* RenderParagraph::lineAtIndex(int i) const
|
| {
|
| ASSERT(i >= 0);
|
| @@ -80,6 +107,11 @@ int RenderParagraph::lineCount(const RootInlineBox* stopRootInlineBox, bool* fou
|
| return count;
|
| }
|
|
|
| +void RenderParagraph::deleteLineBoxTree()
|
| +{
|
| + m_lineBoxes.deleteLineBoxTree();
|
| +}
|
| +
|
| GapRects RenderParagraph::inlineSelectionGaps(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
|
| LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLogicalRight, const PaintInfo* paintInfo)
|
| {
|
| @@ -211,10 +243,121 @@ void RenderParagraph::markLinesDirtyInBlockRange(LayoutUnit logicalTop, LayoutUn
|
| }
|
| }
|
|
|
| -static inline InlineBox* createInlineBoxForRenderer(RenderObject* obj, bool isRootLineBox, bool isOnlyRun = false)
|
| +static void updateLogicalWidthForLeftAlignedBlock(bool isLeftToRightDirection, BidiRun* trailingSpaceRun, float& logicalLeft, float& totalLogicalWidth, float availableLogicalWidth)
|
| +{
|
| + // The direction of the block should determine what happens with wide lines.
|
| + // In particular with RTL blocks, wide lines should still spill out to the left.
|
| + if (isLeftToRightDirection) {
|
| + if (totalLogicalWidth > availableLogicalWidth && trailingSpaceRun)
|
| + trailingSpaceRun->m_box->setLogicalWidth(std::max<float>(0, trailingSpaceRun->m_box->logicalWidth() - totalLogicalWidth + availableLogicalWidth));
|
| + return;
|
| + }
|
| +
|
| + if (trailingSpaceRun)
|
| + trailingSpaceRun->m_box->setLogicalWidth(0);
|
| + else if (totalLogicalWidth > availableLogicalWidth)
|
| + logicalLeft -= (totalLogicalWidth - availableLogicalWidth);
|
| +}
|
| +
|
| +static void updateLogicalWidthForRightAlignedBlock(bool isLeftToRightDirection, BidiRun* trailingSpaceRun, float& logicalLeft, float& totalLogicalWidth, float availableLogicalWidth)
|
| +{
|
| + // Wide lines spill out of the block based off direction.
|
| + // So even if text-align is right, if direction is LTR, wide lines should overflow out of the right
|
| + // side of the block.
|
| + if (isLeftToRightDirection) {
|
| + if (trailingSpaceRun) {
|
| + totalLogicalWidth -= trailingSpaceRun->m_box->logicalWidth();
|
| + trailingSpaceRun->m_box->setLogicalWidth(0);
|
| + }
|
| + if (totalLogicalWidth < availableLogicalWidth)
|
| + logicalLeft += availableLogicalWidth - totalLogicalWidth;
|
| + return;
|
| + }
|
| +
|
| + if (totalLogicalWidth > availableLogicalWidth && trailingSpaceRun) {
|
| + trailingSpaceRun->m_box->setLogicalWidth(std::max<float>(0, trailingSpaceRun->m_box->logicalWidth() - totalLogicalWidth + availableLogicalWidth));
|
| + totalLogicalWidth -= trailingSpaceRun->m_box->logicalWidth();
|
| + } else
|
| + logicalLeft += availableLogicalWidth - totalLogicalWidth;
|
| +}
|
| +
|
| +static void updateLogicalWidthForCenterAlignedBlock(bool isLeftToRightDirection, BidiRun* trailingSpaceRun, float& logicalLeft, float& totalLogicalWidth, float availableLogicalWidth)
|
| +{
|
| + float trailingSpaceWidth = 0;
|
| + if (trailingSpaceRun) {
|
| + totalLogicalWidth -= trailingSpaceRun->m_box->logicalWidth();
|
| + trailingSpaceWidth = std::min(trailingSpaceRun->m_box->logicalWidth(), (availableLogicalWidth - totalLogicalWidth + 1) / 2);
|
| + trailingSpaceRun->m_box->setLogicalWidth(std::max<float>(0, trailingSpaceWidth));
|
| + }
|
| + if (isLeftToRightDirection)
|
| + logicalLeft += std::max<float>((availableLogicalWidth - totalLogicalWidth) / 2, 0);
|
| + else
|
| + logicalLeft += totalLogicalWidth > availableLogicalWidth ? (availableLogicalWidth - totalLogicalWidth) : (availableLogicalWidth - totalLogicalWidth) / 2 - trailingSpaceWidth;
|
| +}
|
| +
|
| +void RenderParagraph::updateLogicalWidthForAlignment(const ETextAlign& textAlign, const RootInlineBox* rootInlineBox, BidiRun* trailingSpaceRun, float& logicalLeft, float& totalLogicalWidth, float& availableLogicalWidth, unsigned expansionOpportunityCount)
|
| +{
|
| + TextDirection direction;
|
| + if (rootInlineBox && rootInlineBox->renderer().style()->unicodeBidi() == Plaintext)
|
| + direction = rootInlineBox->direction();
|
| + else
|
| + direction = style()->direction();
|
| +
|
| + // Armed with the total width of the line (without justification),
|
| + // we now examine our text-align property in order to determine where to position the
|
| + // objects horizontally. The total width of the line can be increased if we end up
|
| + // justifying text.
|
| + switch (textAlign) {
|
| + case LEFT:
|
| + updateLogicalWidthForLeftAlignedBlock(style()->isLeftToRightDirection(), trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth);
|
| + break;
|
| + case RIGHT:
|
| + updateLogicalWidthForRightAlignedBlock(style()->isLeftToRightDirection(), trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth);
|
| + break;
|
| + case CENTER:
|
| + updateLogicalWidthForCenterAlignedBlock(style()->isLeftToRightDirection(), trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth);
|
| + break;
|
| + case JUSTIFY:
|
| + adjustInlineDirectionLineBounds(expansionOpportunityCount, logicalLeft, availableLogicalWidth);
|
| + if (expansionOpportunityCount) {
|
| + if (trailingSpaceRun) {
|
| + totalLogicalWidth -= trailingSpaceRun->m_box->logicalWidth();
|
| + trailingSpaceRun->m_box->setLogicalWidth(0);
|
| + }
|
| + break;
|
| + }
|
| + // Fall through
|
| + case TASTART:
|
| + if (direction == LTR)
|
| + updateLogicalWidthForLeftAlignedBlock(style()->isLeftToRightDirection(), trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth);
|
| + else
|
| + updateLogicalWidthForRightAlignedBlock(style()->isLeftToRightDirection(), trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth);
|
| + break;
|
| + case TAEND:
|
| + if (direction == LTR)
|
| + updateLogicalWidthForRightAlignedBlock(style()->isLeftToRightDirection(), trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth);
|
| + else
|
| + updateLogicalWidthForLeftAlignedBlock(style()->isLeftToRightDirection(), trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth);
|
| + break;
|
| + }
|
| +}
|
| +
|
| +RootInlineBox* RenderParagraph::createAndAppendRootInlineBox()
|
| +{
|
| + RootInlineBox* rootBox = createRootInlineBox();
|
| + m_lineBoxes.appendLineBox(rootBox);
|
| + return rootBox;
|
| +}
|
| +
|
| +RootInlineBox* RenderParagraph::createRootInlineBox()
|
| +{
|
| + return new RootInlineBox(*this);
|
| +}
|
| +
|
| +InlineBox* RenderParagraph::createInlineBoxForRenderer(RenderObject* obj, bool isRootLineBox, bool isOnlyRun)
|
| {
|
| if (isRootLineBox)
|
| - return toRenderBlockFlow(obj)->createAndAppendRootInlineBox();
|
| + return toRenderParagraph(obj)->createAndAppendRootInlineBox();
|
|
|
| if (obj->isText()) {
|
| InlineTextBox* textBox = toRenderText(obj)->createInlineTextBox();
|
| @@ -784,7 +927,6 @@ void RenderParagraph::layoutRunsAndFloatsInRange(LineLayoutState& layoutState,
|
| // Once BidiRunList is separated from BidiResolver this will not be needed.
|
| resolver.runs().deleteRuns();
|
| resolver.markCurrentRunEmpty(); // FIXME: This can probably be replaced by an ASSERT (or just removed).
|
| - layoutState.setCheckForFloatsFromLastLine(true);
|
| resolver.setPosition(InlineIterator(resolver.position().root(), 0, 0), 0);
|
| break;
|
| }
|
| @@ -1242,6 +1384,44 @@ int RenderParagraph::lastLineBoxBaseline(LineDirectionMode lineDirection) const
|
| return -1;
|
| }
|
|
|
| +void RenderParagraph::layout()
|
| +{
|
| + ASSERT(needsLayout());
|
| + ASSERT(isInlineBlock() || !isInline());
|
| +
|
| + if (simplifiedLayout())
|
| + return;
|
| +
|
| + SubtreeLayoutScope layoutScope(*this);
|
| +
|
| + LayoutUnit oldLeft = logicalLeft();
|
| + bool logicalWidthChanged = updateLogicalWidthAndColumnWidth();
|
| + bool relayoutChildren = logicalWidthChanged;
|
| +
|
| + LayoutUnit beforeEdge = borderBefore() + paddingBefore();
|
| + LayoutUnit afterEdge = borderAfter() + paddingAfter();
|
| + LayoutUnit previousHeight = logicalHeight();
|
| + setLogicalHeight(beforeEdge);
|
| +
|
| + layoutChildren(relayoutChildren, layoutScope, beforeEdge, afterEdge);
|
| +
|
| + LayoutUnit oldClientAfterEdge = clientLogicalBottom();
|
| +
|
| + updateLogicalHeight();
|
| +
|
| + if (previousHeight != logicalHeight())
|
| + relayoutChildren = true;
|
| +
|
| + layoutPositionedObjects(relayoutChildren, oldLeft != logicalLeft() ? ForcedLayoutAfterContainingBlockMoved : DefaultLayout);
|
| +
|
| + // Add overflow from children (unless we're multi-column, since in that case all our child overflow is clipped anyway).
|
| + computeOverflow(oldClientAfterEdge);
|
| +
|
| + updateLayerTransformAfterLayout();
|
| +
|
| + clearNeedsLayout();
|
| +}
|
| +
|
| void RenderParagraph::layoutChildren(bool relayoutChildren, SubtreeLayoutScope& layoutScope, LayoutUnit beforeEdge, LayoutUnit afterEdge)
|
| {
|
| // Figure out if we should clear out our line boxes.
|
| @@ -1327,59 +1507,11 @@ void RenderParagraph::layoutChildren(bool relayoutChildren, SubtreeLayoutScope&
|
| checkLinesForTextOverflow();
|
| }
|
|
|
| -void RenderParagraph::checkFloatsInCleanLine(RootInlineBox* line, Vector<FloatWithRect>& floats, size_t& floatIndex, bool& encounteredNewFloat, bool& dirtiedByFloat)
|
| -{
|
| - Vector<RenderBox*>* cleanLineFloats = line->floatsPtr();
|
| - if (!cleanLineFloats)
|
| - return;
|
| -
|
| - Vector<RenderBox*>::iterator end = cleanLineFloats->end();
|
| - for (Vector<RenderBox*>::iterator it = cleanLineFloats->begin(); it != end; ++it) {
|
| - RenderBox* floatingBox = *it;
|
| - floatingBox->layoutIfNeeded();
|
| - LayoutSize newSize(floatingBox->width() + floatingBox->marginWidth(), floatingBox->height() + floatingBox->marginHeight());
|
| - if (floats[floatIndex].object != floatingBox) {
|
| - encounteredNewFloat = true;
|
| - return;
|
| - }
|
| -
|
| - if (floats[floatIndex].rect.size() != newSize) {
|
| - LayoutUnit floatTop = floats[floatIndex].rect.y();
|
| - LayoutUnit floatHeight = std::max(floats[floatIndex].rect.height(), newSize.height());
|
| - floatHeight = std::min(floatHeight, LayoutUnit::max() - floatTop);
|
| - line->markDirty();
|
| - markLinesDirtyInBlockRange(line->lineBottomWithLeading(), floatTop + floatHeight, line);
|
| - floats[floatIndex].rect.setSize(newSize);
|
| - dirtiedByFloat = true;
|
| - }
|
| - floatIndex++;
|
| - }
|
| -}
|
| -
|
| RootInlineBox* RenderParagraph::determineStartPosition(LineLayoutState& layoutState, InlineBidiResolver& resolver)
|
| {
|
| RootInlineBox* curr = 0;
|
| RootInlineBox* last = 0;
|
|
|
| - // FIXME: This entire float-checking block needs to be broken into a new function.
|
| - bool dirtiedByFloat = false;
|
| - if (!layoutState.isFullLayout()) {
|
| - size_t floatIndex = 0;
|
| - for (curr = firstRootBox(); curr && !curr->isDirty(); curr = curr->nextRootBox()) {
|
| - // If a new float has been inserted before this line or before its last known float, just do a full layout.
|
| - bool encounteredNewFloat = false;
|
| - checkFloatsInCleanLine(curr, layoutState.floats(), floatIndex, encounteredNewFloat, dirtiedByFloat);
|
| - if (encounteredNewFloat)
|
| - layoutState.markForFullLayout();
|
| -
|
| - if (dirtiedByFloat || layoutState.isFullLayout())
|
| - break;
|
| - }
|
| - // Check if a new float has been inserted after the last known float.
|
| - if (!curr && floatIndex < layoutState.floats().size())
|
| - layoutState.markForFullLayout();
|
| - }
|
| -
|
| if (layoutState.isFullLayout()) {
|
| // If we encountered a new float and have inline children, mark ourself to force us to issue paint invalidations.
|
| if (layoutState.hasInlineChild() && !selfNeedsLayout()) {
|
| @@ -1401,7 +1533,7 @@ RootInlineBox* RenderParagraph::determineStartPosition(LineLayoutState& layoutSt
|
| // We have a dirty line.
|
| if (RootInlineBox* prevRootBox = curr->prevRootBox()) {
|
| // We have a previous line.
|
| - if (!dirtiedByFloat && (!prevRootBox->endsWithBreak() || !prevRootBox->lineBreakObj() || (prevRootBox->lineBreakObj()->isText() && prevRootBox->lineBreakPos() >= toRenderText(prevRootBox->lineBreakObj())->textLength())))
|
| + if (!prevRootBox->endsWithBreak() || !prevRootBox->lineBreakObj() || (prevRootBox->lineBreakObj()->isText() && prevRootBox->lineBreakPos() >= toRenderText(prevRootBox->lineBreakObj())->textLength()))
|
| // The previous line didn't break cleanly or broke at a newline
|
| // that has been deleted, so treat it as dirty too.
|
| curr = prevRootBox;
|
| @@ -1439,16 +1571,8 @@ RootInlineBox* RenderParagraph::determineStartPosition(LineLayoutState& layoutSt
|
| void RenderParagraph::determineEndPosition(LineLayoutState& layoutState, RootInlineBox* startLine, InlineIterator& cleanLineStart, BidiStatus& cleanLineBidiStatus)
|
| {
|
| ASSERT(!layoutState.endLine());
|
| - size_t floatIndex = layoutState.floatIndex();
|
| RootInlineBox* last = 0;
|
| for (RootInlineBox* curr = startLine->nextRootBox(); curr; curr = curr->nextRootBox()) {
|
| - if (!curr->isDirty()) {
|
| - bool encounteredNewFloat = false;
|
| - bool dirtiedByFloat = false;
|
| - checkFloatsInCleanLine(curr, layoutState.floats(), floatIndex, encounteredNewFloat, dirtiedByFloat);
|
| - if (encounteredNewFloat)
|
| - return;
|
| - }
|
| if (curr->isDirty())
|
| last = 0;
|
| else if (!last)
|
|
|