ShapeOutsideDeltas ShapeOutsideInfo::computeDeltasForContainingBlockLine(const LineLayoutBlockFlow& containingBlock, const FloatingObject& floatingObject, LayoutUnit lineTop, LayoutUnit lineHeight) { ASSERT(lineHeight >= 0); LayoutUnit borderBoxTop = containingBlock.logicalTopForFloat(floatingObject) + containingBlock.marginBeforeForChild(m_layoutBox); LayoutUnit borderBoxLineTop = lineTop - borderBoxTop; if (isShapeDirty() || !m_shapeOutsideDeltas.isForLine(borderBoxLineTop, lineHeight)) { LayoutUnit referenceBoxLineTop = borderBoxLineTop - logicalTopOffset(); LayoutUnit floatMarginBoxWidth = std::max(containingBlock.logicalWidthForFloat(floatingObject), LayoutUnit()); if (computedShape().lineOverlapsShapeMarginBounds(referenceBoxLineTop, lineHeight)) { LineSegment segment = computedShape().getExcludedInterval((borderBoxLineTop - logicalTopOffset()), std::min(lineHeight, shapeLogicalBottom() - borderBoxLineTop)); if (segment.isValid) { LayoutUnit logicalLeftMargin = containingBlock.style()->isLeftToRightDirection() ? containingBlock.marginStartForChild(m_layoutBox) : containingBlock.marginEndForChild(m_layoutBox); LayoutUnit rawLeftMarginBoxDelta = segment.logicalLeft + logicalLeftOffset() + logicalLeftMargin; LayoutUnit leftMarginBoxDelta = clampTo<LayoutUnit>(rawLeftMarginBoxDelta, LayoutUnit(), floatMarginBoxWidth); LayoutUnit logicalRightMargin = containingBlock.style()->isLeftToRightDirection() ? containingBlock.marginEndForChild(m_layoutBox) : containingBlock.marginStartForChild(m_layoutBox); LayoutUnit rawRightMarginBoxDelta = segment.logicalRight + logicalLeftOffset() - containingBlock.logicalWidthForChild(m_layoutBox) - logicalRightMargin; LayoutUnit rightMarginBoxDelta = clampTo<LayoutUnit>(rawRightMarginBoxDelta, -floatMarginBoxWidth, LayoutUnit()); m_shapeOutsideDeltas = ShapeOutsideDeltas(leftMarginBoxDelta, rightMarginBoxDelta, true, borderBoxLineTop, lineHeight); return m_shapeOutsideDeltas; } } // Lines that do not overlap the shape should act as if the float // wasn't there for layout purposes. So we set the deltas to remove the // entire width of the float. m_shapeOutsideDeltas = ShapeOutsideDeltas(floatMarginBoxWidth, -floatMarginBoxWidth, false, borderBoxLineTop, lineHeight); } return m_shapeOutsideDeltas; }
LayoutUnit ShapeInsideInfo::computeFirstFitPositionForFloat(const FloatSize& floatSize) const { if (!computedShape() || !floatSize.width() || shapeLogicalBottom() < logicalLineTop()) return 0; LayoutUnit firstFitPosition = 0; if (computedShape()->firstIncludedIntervalLogicalTop(m_shapeLineTop, floatSize, firstFitPosition) && (m_shapeLineTop <= firstFitPosition)) return firstFitPosition; return 0; }
void ShapeOutsideInfo::updateDeltasForContainingBlockLine(const RenderBlockFlow& containingBlock, const FloatingObject& floatingObject, LayoutUnit lineTop, LayoutUnit lineHeight) { LayoutUnit borderBoxTop = containingBlock.logicalTopForFloat(&floatingObject) + containingBlock.marginBeforeForChild(m_renderer); LayoutUnit borderBoxLineTop = lineTop - borderBoxTop; if (isShapeDirty() || m_borderBoxLineTop != borderBoxLineTop || m_lineHeight != lineHeight) { m_borderBoxLineTop = borderBoxLineTop; m_referenceBoxLineTop = borderBoxLineTop - logicalTopOffset(); m_lineHeight = lineHeight; LayoutUnit floatMarginBoxWidth = containingBlock.logicalWidthForFloat(&floatingObject); if (computedShape().lineOverlapsShapeMarginBounds(m_referenceBoxLineTop, m_lineHeight)) { SegmentList segments = computeSegmentsForLine(borderBoxLineTop, lineHeight); if (segments.size()) { LayoutUnit logicalLeftMargin = containingBlock.style().isLeftToRightDirection() ? containingBlock.marginStartForChild(m_renderer) : containingBlock.marginEndForChild(m_renderer); LayoutUnit rawLeftMarginBoxDelta = segments.first().logicalLeft + logicalLeftMargin; m_leftMarginBoxDelta = clampTo<LayoutUnit>(rawLeftMarginBoxDelta, LayoutUnit(), floatMarginBoxWidth); LayoutUnit logicalRightMargin = containingBlock.style().isLeftToRightDirection() ? containingBlock.marginEndForChild(m_renderer) : containingBlock.marginStartForChild(m_renderer); LayoutUnit rawRightMarginBoxDelta = segments.last().logicalRight - containingBlock.logicalWidthForChild(m_renderer) - logicalRightMargin; m_rightMarginBoxDelta = clampTo<LayoutUnit>(rawRightMarginBoxDelta, -floatMarginBoxWidth, LayoutUnit()); m_lineOverlapsShape = true; return; } } // Lines that do not overlap the shape should act as if the float // wasn't there for layout purposes. So we set the deltas to remove the // entire width of the float m_leftMarginBoxDelta = floatMarginBoxWidth; m_rightMarginBoxDelta = -floatMarginBoxWidth; m_lineOverlapsShape = false; } }
LayoutRect ShapeOutsideInfo::computedShapePhysicalBoundingBox() const { LayoutRect physicalBoundingBox = computedShape().shapeMarginLogicalBoundingBox(); physicalBoundingBox.setX(physicalBoundingBox.x() + logicalLeftOffset()); physicalBoundingBox.setY(physicalBoundingBox.y() + logicalTopOffset()); if (m_renderer.style().isFlippedBlocksWritingMode()) physicalBoundingBox.setY(m_renderer.logicalHeight() - physicalBoundingBox.maxY()); if (!m_renderer.style().isHorizontalWritingMode()) physicalBoundingBox = physicalBoundingBox.transposedRect(); return physicalBoundingBox; }
SegmentList ShapeOutsideInfo::computeSegmentsForLine(LayoutUnit lineTop, LayoutUnit lineHeight) const { ASSERT(lineHeight >= 0); SegmentList segments; computedShape().getExcludedIntervals((lineTop - logicalTopOffset()), std::min(lineHeight, shapeLogicalBottom() - lineTop), segments); for (size_t i = 0; i < segments.size(); i++) { segments[i].logicalLeft += logicalLeftOffset(); segments[i].logicalRight += logicalLeftOffset(); } return segments; }
bool ExclusionShapeInsideInfo::adjustLogicalLineTop(float minSegmentWidth) { const ExclusionShape* shape = computedShape(); if (!shape || m_lineHeight <= 0 || logicalLineTop() > shapeLogicalBottom()) return false; LayoutUnit newLineTop; if (shape->firstIncludedIntervalLogicalTop(m_shapeLineTop, LayoutSize(minSegmentWidth, m_lineHeight), newLineTop)) { if (newLineTop > m_shapeLineTop) { m_shapeLineTop = newLineTop; return true; } } return false; }
bool ShapeInfo<RenderType, shapeGetter, intervalGetter>::computeSegmentsForLine(LayoutUnit lineTop, LayoutUnit lineHeight) { ASSERT(lineHeight >= 0); m_shapeLineTop = lineTop - logicalTopOffset(); m_lineHeight = lineHeight; m_segments.clear(); if (lineOverlapsShapeBounds()) (computedShape()->*intervalGetter)(m_shapeLineTop, std::min(m_lineHeight, shapeLogicalBottom() - lineTop), m_segments); LayoutUnit logicalLeftOffset = this->logicalLeftOffset(); for (size_t i = 0; i < m_segments.size(); i++) { m_segments[i].logicalLeft += logicalLeftOffset; m_segments[i].logicalRight += logicalLeftOffset; } return m_segments.size(); }