void RenderFlowThread::pushFlowThreadLayoutState(const RenderObject& object) { if (const RenderBox* currentBoxDescendant = currentStatePusherRenderBox()) { LayoutState* layoutState = currentBoxDescendant->view()->layoutState(); if (layoutState && layoutState->isPaginated()) { ASSERT(layoutState->renderer() == currentBoxDescendant); LayoutSize offsetDelta = layoutState->layoutOffset() - layoutState->pageOffset(); setOffsetFromLogicalTopOfFirstRegion(currentBoxDescendant, currentBoxDescendant->isHorizontalWritingMode() ? offsetDelta.height() : offsetDelta.width()); } } m_statePusherObjectsStack.add(&object); }
void RenderMultiColumnFlowThread::computeLineGridPaginationOrigin(LayoutState& layoutState) const { if (!progressionIsInline()) return; // We need to cache a line grid pagination origin so that we understand how to reset the line grid // at the top of each column. // Get the current line grid and offset. const auto lineGrid = layoutState.lineGrid(); if (!lineGrid) return; // Get the hypothetical line box used to establish the grid. auto lineGridBox = lineGrid->lineGridBox(); if (!lineGridBox) return; bool isHorizontalWritingMode = lineGrid->isHorizontalWritingMode(); LayoutUnit lineGridBlockOffset = isHorizontalWritingMode ? layoutState.lineGridOffset().height() : layoutState.lineGridOffset().width(); // Now determine our position on the grid. Our baseline needs to be adjusted to the nearest baseline multiple // as established by the line box. // FIXME: Need to handle crazy line-box-contain values that cause the root line box to not be considered. I assume // the grid should honor line-box-contain. LayoutUnit gridLineHeight = lineGridBox->lineBottomWithLeading() - lineGridBox->lineTopWithLeading(); if (!gridLineHeight) return; LayoutUnit firstLineTopWithLeading = lineGridBlockOffset + lineGridBox->lineTopWithLeading(); if (layoutState.isPaginated() && layoutState.pageLogicalHeight()) { LayoutUnit pageLogicalTop = isHorizontalWritingMode ? layoutState.pageOffset().height() : layoutState.pageOffset().width(); if (pageLogicalTop > firstLineTopWithLeading) { // Shift to the next highest line grid multiple past the page logical top. Cache the delta // between this new value and the page logical top as the pagination origin. LayoutUnit remainder = roundToInt(pageLogicalTop - firstLineTopWithLeading) % roundToInt(gridLineHeight); LayoutUnit paginationDelta = gridLineHeight - remainder; if (isHorizontalWritingMode) layoutState.setLineGridPaginationOrigin(LayoutSize(layoutState.lineGridPaginationOrigin().width(), paginationDelta)); else layoutState.setLineGridPaginationOrigin(LayoutSize(paginationDelta, layoutState.lineGridPaginationOrigin().height())); } } }
LayoutUnit RenderFlowThread::offsetFromLogicalTopOfFirstRegion(const RenderBlock* currentBlock) const { // First check if we cached the offset for the block if it's an ancestor containing block of the box // being currently laid out. LayoutUnit offset; if (cachedOffsetFromLogicalTopOfFirstRegion(currentBlock, offset)) return offset; // If it's the current box being laid out, use the layout state. const RenderBox* currentBoxDescendant = currentStatePusherRenderBox(); if (currentBlock == currentBoxDescendant) { LayoutState* layoutState = view()->layoutState(); ASSERT(layoutState->renderer() == currentBlock); ASSERT(layoutState && layoutState->isPaginated()); LayoutSize offsetDelta = layoutState->layoutOffset() - layoutState->pageOffset(); return currentBoxDescendant->isHorizontalWritingMode() ? offsetDelta.height() : offsetDelta.width(); } // As a last resort, take the slow path. LayoutRect blockRect(0, 0, currentBlock->width(), currentBlock->height()); while (currentBlock && !currentBlock->isRenderFlowThread()) { RenderBlock* containerBlock = currentBlock->containingBlock(); ASSERT(containerBlock); if (!containerBlock) return 0; LayoutPoint currentBlockLocation = currentBlock->location(); if (containerBlock->style()->writingMode() != currentBlock->style()->writingMode()) { // We have to put the block rect in container coordinates // and we have to take into account both the container and current block flipping modes if (containerBlock->style()->isFlippedBlocksWritingMode()) { if (containerBlock->isHorizontalWritingMode()) blockRect.setY(currentBlock->height() - blockRect.maxY()); else blockRect.setX(currentBlock->width() - blockRect.maxX()); } currentBlock->flipForWritingMode(blockRect); } blockRect.moveBy(currentBlockLocation); currentBlock = containerBlock; } return currentBlock->isHorizontalWritingMode() ? blockRect.y() : blockRect.x(); }