void LineWidth::shrinkAvailableWidthForNewFloatIfNeeded(FloatingObject* newFloat) { LayoutUnit height = m_block.logicalHeight(); if (height < m_block.logicalTopForFloat(newFloat) || height >= m_block.logicalBottomForFloat(newFloat)) return; #if ENABLE(CSS_SHAPES) // When floats with shape outside are stacked, the floats are positioned based on the margin box of the float, // not the shape's contour. Since we computed the width based on the shape contour when we added the float, // when we add a subsequent float on the same line, we need to undo the shape delta in order to position // based on the margin box. In order to do this, we need to walk back through the floating object list to find // the first previous float that is on the same side as our newFloat. ShapeOutsideInfo* previousShapeOutsideInfo = 0; const FloatingObjectSet& floatingObjectSet = m_block.m_floatingObjects->set(); auto it = floatingObjectSet.end(); auto begin = floatingObjectSet.begin(); LayoutUnit lineHeight = m_block.lineHeight(m_isFirstLine, m_block.isHorizontalWritingMode() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes); for (--it; it != begin; --it) { FloatingObject* previousFloat = it->get(); if (previousFloat != newFloat && previousFloat->type() == newFloat->type()) { previousShapeOutsideInfo = previousFloat->renderer().shapeOutsideInfo(); if (previousShapeOutsideInfo) previousShapeOutsideInfo->updateDeltasForContainingBlockLine(&m_block, previousFloat, m_block.logicalHeight(), lineHeight); break; } } ShapeOutsideInfo* shapeOutsideInfo = newFloat->renderer().shapeOutsideInfo(); if (shapeOutsideInfo) shapeOutsideInfo->updateDeltasForContainingBlockLine(&m_block, newFloat, m_block.logicalHeight(), lineHeight); #endif if (newFloat->type() == FloatingObject::FloatLeft) { float newLeft = m_block.logicalRightForFloat(newFloat); #if ENABLE(CSS_SHAPES) if (previousShapeOutsideInfo) newLeft -= previousShapeOutsideInfo->rightMarginBoxDelta(); if (shapeOutsideInfo) newLeft += shapeOutsideInfo->rightMarginBoxDelta(); #endif if (shouldIndentText() && m_block.style()->isLeftToRightDirection()) newLeft += floorToInt(m_block.textIndentOffset()); m_left = std::max<float>(m_left, newLeft); } else { float newRight = m_block.logicalLeftForFloat(newFloat); #if ENABLE(CSS_SHAPES) if (previousShapeOutsideInfo) newRight -= previousShapeOutsideInfo->leftMarginBoxDelta(); if (shapeOutsideInfo) newRight += shapeOutsideInfo->leftMarginBoxDelta(); #endif if (shouldIndentText() && !m_block.style()->isLeftToRightDirection()) newRight -= floorToInt(m_block.textIndentOffset()); m_right = std::min<float>(m_right, newRight); } computeAvailableWidthFromLeftAndRight(); }
void LineWidth::fitBelowFloats(bool isFirstLine) { ASSERT(!m_committedWidth); ASSERT(!fitsOnLine()); LayoutUnit floatLogicalBottom; LayoutUnit lastFloatLogicalBottom = m_block.logicalHeight(); float newLineWidth = m_availableWidth; float newLineLeft = m_left; float newLineRight = m_right; while (true) { floatLogicalBottom = lastFloatLogicalBottom; if (floatLogicalBottom <= lastFloatLogicalBottom) break; newLineLeft = m_block.logicalLeftOffsetForLine(shouldIndentText()).toFloat(); newLineRight = m_block.logicalRightOffsetForLine(shouldIndentText()).toFloat(); newLineWidth = std::max(0.0f, newLineRight - newLineLeft); lastFloatLogicalBottom = floatLogicalBottom; if (newLineWidth >= m_uncommittedWidth) break; } updateLineDimension(lastFloatLogicalBottom, newLineWidth, newLineLeft, newLineRight); }
void LineWidth::updateAvailableWidth(LayoutUnit replacedHeight) { LayoutUnit height = m_block.logicalHeight(); LayoutUnit logicalHeight = m_block.minLineHeightForReplacedRenderer(m_isFirstLine, replacedHeight); m_left = m_block.logicalLeftOffsetForLine(height, shouldIndentText(), logicalHeight).toFloat(); m_right = m_block.logicalRightOffsetForLine(height, shouldIndentText(), logicalHeight).toFloat(); computeAvailableWidthFromLeftAndRight(); }
void LineWidth::updateAvailableWidth(LayoutUnit replacedHeight) { LayoutUnit height = m_block.logicalHeight(); LayoutUnit logicalHeight = m_block.minLineHeightForReplacedRenderer(m_isFirstLine, replacedHeight); m_left = m_block.logicalLeftOffsetForLine(height, shouldIndentText(), logicalHeight); m_right = m_block.logicalRightOffsetForLine(height, shouldIndentText(), logicalHeight); #if ENABLE(CSS_SHAPES) if (m_segment) { m_left = std::max<float>(m_segment->logicalLeft, m_left); m_right = std::min<float>(m_segment->logicalRight, m_right); } #endif computeAvailableWidthFromLeftAndRight(); }
void LineWidth::fitBelowFloats(bool isFirstLine) { ASSERT(!m_committedWidth); ASSERT(!fitsOnLine()); LayoutUnit floatLogicalBottom; LayoutUnit lastFloatLogicalBottom = m_block.logicalHeight(); float newLineWidth = m_availableWidth; float newLineLeft = m_left; float newLineRight = m_right; FloatingObject* lastFloatFromPreviousLine = (m_block.containsFloats() ? m_block.m_floatingObjects->set().last().get() : 0); if (lastFloatFromPreviousLine && lastFloatFromPreviousLine->renderer()->shapeOutsideInfo()) return wrapNextToShapeOutside(isFirstLine); while (true) { floatLogicalBottom = m_block.nextFloatLogicalBottomBelow(lastFloatLogicalBottom, ShapeOutsideFloatShapeOffset); if (floatLogicalBottom <= lastFloatLogicalBottom) break; newLineWidth = availableWidthAtOffset(m_block, floatLogicalBottom, shouldIndentText(), newLineLeft, newLineRight); lastFloatLogicalBottom = floatLogicalBottom; if (newLineWidth >= m_uncommittedWidth) break; } updateLineDimension(lastFloatLogicalBottom, newLineWidth, newLineLeft, newLineRight); }
void LineWidth::shrinkAvailableWidthForNewFloatIfNeeded(FloatingObject* newFloat) { LayoutUnit height = m_block.logicalHeight(); if (height < m_block.logicalTopForFloat(newFloat) || height >= m_block.logicalBottomForFloat(newFloat)) return; #if ENABLE(CSS_SHAPES) ShapeOutsideDeltas shapeDeltas; if (ShapeOutsideInfo* shapeOutsideInfo = newFloat->renderer().shapeOutsideInfo()) { LayoutUnit lineHeight = m_block.lineHeight(m_isFirstLine, m_block.isHorizontalWritingMode() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes); shapeDeltas = shapeOutsideInfo->computeDeltasForContainingBlockLine(m_block, *newFloat, m_block.logicalHeight(), lineHeight); } #endif if (newFloat->type() == FloatingObject::FloatLeft) { float newLeft = m_block.logicalRightForFloat(newFloat); if (shouldIndentText() && m_block.style().isLeftToRightDirection()) newLeft += floorToInt(m_block.textIndentOffset()); #if ENABLE(CSS_SHAPES) if (shapeDeltas.isValid()) { if (shapeDeltas.lineOverlapsShape()) newLeft += shapeDeltas.rightMarginBoxDelta(); else // If the line doesn't overlap the shape, then we need to act as if this float didn't exist. newLeft = m_left; } #endif m_left = std::max<float>(m_left, newLeft); } else { float newRight = m_block.logicalLeftForFloat(newFloat); if (shouldIndentText() && !m_block.style().isLeftToRightDirection()) newRight -= floorToInt(m_block.textIndentOffset()); #if ENABLE(CSS_SHAPES) if (shapeDeltas.isValid()) { if (shapeDeltas.lineOverlapsShape()) newRight += shapeDeltas.leftMarginBoxDelta(); else // If the line doesn't overlap the shape, then we need to act as if this float didn't exist. newRight = m_right; } #endif m_right = std::min<float>(m_right, newRight); } computeAvailableWidthFromLeftAndRight(); }
void LineWidth::fitBelowFloats() { ASSERT(!m_committedWidth); ASSERT(!fitsOnLine()); LayoutUnit floatLogicalBottom; LayoutUnit lastFloatLogicalBottom = m_block.logicalHeight(); float newLineWidth = m_availableWidth; float newLineLeft = m_left; float newLineRight = m_right; while (true) { floatLogicalBottom = m_block.nextFloatLogicalBottomBelow(lastFloatLogicalBottom, ShapeOutsideFloatShapeOffset); if (floatLogicalBottom <= lastFloatLogicalBottom) break; newLineLeft = m_block.logicalLeftOffsetForLine(floatLogicalBottom, shouldIndentText()); newLineRight = m_block.logicalRightOffsetForLine(floatLogicalBottom, shouldIndentText()); newLineWidth = max(0.0f, newLineRight - newLineLeft); lastFloatLogicalBottom = floatLogicalBottom; #if ENABLE(CSS_SHAPES) // FIXME: This code should be refactored to incorporate with the code above. ShapeInsideInfo* shapeInsideInfo = m_block.layoutShapeInsideInfo(); if (shapeInsideInfo) { LayoutUnit logicalOffsetFromShapeContainer = m_block.logicalOffsetFromShapeAncestorContainer(shapeInsideInfo->owner()).height(); LayoutUnit lineHeight = m_block.lineHeight(false, m_block.isHorizontalWritingMode() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes); shapeInsideInfo->updateSegmentsForLine(lastFloatLogicalBottom + logicalOffsetFromShapeContainer, lineHeight); updateCurrentShapeSegment(); updateAvailableWidth(); } #endif if (newLineWidth >= m_uncommittedWidth) break; } if (newLineWidth > m_availableWidth) { m_block.setLogicalHeight(lastFloatLogicalBottom); m_availableWidth = newLineWidth + m_overhangWidth; m_left = newLineLeft; m_right = newLineRight; } }
void LineWidth::shrinkAvailableWidthForNewFloatIfNeeded(FloatingObject* newFloat) { LayoutUnit height = m_block.logicalHeight(); if (height < m_block.logicalTopForFloat(newFloat) || height >= m_block.logicalBottomForFloat(newFloat)) return; ShapeOutsideInfo* shapeOutsideInfo = newFloat->renderer()->shapeOutsideInfo(); if (shapeOutsideInfo) { LayoutUnit lineHeight = m_block.lineHeight(m_isFirstLine, m_block.isHorizontalWritingMode() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes); shapeOutsideInfo->updateDeltasForContainingBlockLine(m_block, *newFloat, m_block.logicalHeight(), lineHeight); } if (newFloat->type() == FloatingObject::FloatLeft) { float newLeft = m_block.logicalRightForFloat(newFloat).toFloat(); if (shapeOutsideInfo) { if (shapeOutsideInfo->lineOverlapsShape()) newLeft += shapeOutsideInfo->rightMarginBoxDelta(); else // Per the CSS Shapes spec, If the line doesn't overlap the shape, then ignore this shape for this line. newLeft = m_left; } if (shouldIndentText() && m_block.style()->isLeftToRightDirection()) newLeft += floorToInt(m_block.textIndentOffset()); m_left = std::max<float>(m_left, newLeft); } else { float newRight = m_block.logicalLeftForFloat(newFloat).toFloat(); if (shapeOutsideInfo) { if (shapeOutsideInfo->lineOverlapsShape()) newRight += shapeOutsideInfo->leftMarginBoxDelta(); else // Per the CSS Shapes spec, If the line doesn't overlap the shape, then ignore this shape for this line. newRight = m_right; } if (shouldIndentText() && !m_block.style()->isLeftToRightDirection()) newRight -= floorToInt(m_block.textIndentOffset()); m_right = std::min<float>(m_right, newRight); } computeAvailableWidthFromLeftAndRight(); }
void LineWidth::wrapNextToShapeOutside(bool isFirstLine) { LayoutUnit lineHeight = m_block.lineHeight(isFirstLine, m_block.isHorizontalWritingMode() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes); LayoutUnit lineLogicalTop = m_block.logicalHeight(); LayoutUnit newLineTop = lineLogicalTop; LayoutUnit floatLogicalBottom = m_block.nextFloatLogicalBottomBelow(lineLogicalTop); float newLineWidth; float newLineLeft = m_left; float newLineRight = m_right; while (true) { newLineWidth = availableWidthAtOffset(m_block, newLineTop, shouldIndentText(), newLineLeft, newLineRight); if (newLineWidth >= m_uncommittedWidth && isWholeLineFit(m_block, newLineTop, lineHeight, m_uncommittedWidth, shouldIndentText())) break; if (newLineTop >= floatLogicalBottom) break; newLineTop++; } updateLineDimension(newLineTop, newLineWidth, newLineLeft, newLineRight); }
void LineWidth::updateAvailableWidth() { m_left = m_block.logicalLeftOffsetForLine(shouldIndentText()).toFloat(); m_right = m_block.logicalRightOffsetForLine(shouldIndentText()).toFloat(); computeAvailableWidthFromLeftAndRight(); }