void RenderFrameSet::computeEdgeInfo() { m_rows.m_preventResize.fill(frameSetElement().noResize()); m_rows.m_allowBorder.fill(false); m_cols.m_preventResize.fill(frameSetElement().noResize()); m_cols.m_allowBorder.fill(false); RenderObject* child = firstChild(); if (!child) return; size_t rows = m_rows.m_sizes.size(); size_t cols = m_cols.m_sizes.size(); for (size_t r = 0; r < rows; ++r) { for (size_t c = 0; c < cols; ++c) { FrameEdgeInfo edgeInfo; if (child->isFrameSet()) edgeInfo = toRenderFrameSet(child)->edgeInfo(); else edgeInfo = toRenderFrame(child)->edgeInfo(); fillFromEdgeInfo(edgeInfo, r, c); child = child->nextSibling(); if (!child) return; } } }
void RenderFrameSet::layout() { StackStats::LayoutCheckPoint layoutCheckPoint; ASSERT(needsLayout()); bool doFullRepaint = selfNeedsLayout() && checkForRepaintDuringLayout(); LayoutRect oldBounds; RenderLayerModelObject* repaintContainer = 0; if (doFullRepaint) { repaintContainer = containerForRepaint(); oldBounds = clippedOverflowRectForRepaint(repaintContainer); } if (!parent()->isFrameSet() && !document().printing()) { setWidth(view().viewWidth()); setHeight(view().viewHeight()); } unsigned cols = frameSetElement().totalCols(); unsigned rows = frameSetElement().totalRows(); if (m_rows.m_sizes.size() != rows || m_cols.m_sizes.size() != cols) { m_rows.resize(rows); m_cols.resize(cols); } LayoutUnit borderThickness = frameSetElement().border(); layOutAxis(m_rows, frameSetElement().rowLengths(), height() - (rows - 1) * borderThickness); layOutAxis(m_cols, frameSetElement().colLengths(), width() - (cols - 1) * borderThickness); if (flattenFrameSet()) positionFramesWithFlattening(); else positionFrames(); RenderBox::layout(); computeEdgeInfo(); updateLayerTransform(); if (doFullRepaint) { repaintUsingContainer(repaintContainer, pixelSnappedIntRect(oldBounds)); LayoutRect newBounds = clippedOverflowRectForRepaint(repaintContainer); if (newBounds != oldBounds) repaintUsingContainer(repaintContainer, pixelSnappedIntRect(newBounds)); } clearNeedsLayout(); }
void RenderFrameSet::setIsResizing(bool isResizing) { m_isResizing = isResizing; for (auto& ancestor : ancestorsOfType<RenderFrameSet>(*this)) ancestor.m_isChildResizing = isResizing; frame().eventHandler().setResizingFrameSet(isResizing ? &frameSetElement() : nullptr); }
void RenderFrameSet::positionFrames() { RenderBox* child = firstChildBox(); if (!child) return; int rows = frameSetElement().totalRows(); int cols = frameSetElement().totalCols(); int yPos = 0; int borderThickness = frameSetElement().border(); for (int r = 0; r < rows; r++) { int xPos = 0; int height = m_rows.m_sizes[r]; for (int c = 0; c < cols; c++) { child->setLocation(IntPoint(xPos, yPos)); int width = m_cols.m_sizes[c]; // has to be resized and itself resize its contents if (width != child->width() || height != child->height()) { child->setWidth(width); child->setHeight(height); #if PLATFORM(IOS) // FIXME: Is this iOS-specific? child->setNeedsLayout(MarkOnlyThis); #else child->setNeedsLayout(); #endif child->layout(); } xPos += width + borderThickness; child = child->nextSiblingBox(); if (!child) return; } yPos += height + borderThickness; } // all the remaining frames are hidden to avoid ugly spurious unflowed frames for (; child; child = child->nextSiblingBox()) { child->setWidth(0); child->setHeight(0); child->clearNeedsLayout(); } }
void RenderFrameSet::setIsResizing(bool isResizing) { m_isResizing = isResizing; for (auto ancestor = parent(); ancestor; ancestor = ancestor->parent()) { if (ancestor->isFrameSet()) toRenderFrameSet(ancestor)->m_isChildResizing = isResizing; } frame().eventHandler().setResizingFrameSet(isResizing ? &frameSetElement() : 0); }
FrameEdgeInfo RenderFrameSet::edgeInfo() const { FrameEdgeInfo result(frameSetElement().noResize(), true); int rows = frameSetElement().totalRows(); int cols = frameSetElement().totalCols(); if (rows && cols) { result.setPreventResize(LeftFrameEdge, m_cols.m_preventResize[0]); result.setAllowBorder(LeftFrameEdge, m_cols.m_allowBorder[0]); result.setPreventResize(RightFrameEdge, m_cols.m_preventResize[cols]); result.setAllowBorder(RightFrameEdge, m_cols.m_allowBorder[cols]); result.setPreventResize(TopFrameEdge, m_rows.m_preventResize[0]); result.setAllowBorder(TopFrameEdge, m_rows.m_allowBorder[0]); result.setPreventResize(BottomFrameEdge, m_rows.m_preventResize[rows]); result.setAllowBorder(BottomFrameEdge, m_rows.m_allowBorder[rows]); } return result; }
int RenderFrameSet::splitPosition(const GridAxis& axis, int split) const { if (needsLayout()) return 0; int borderThickness = frameSetElement().border(); int size = axis.m_sizes.size(); if (!size) return 0; int position = 0; for (int i = 0; i < split && i < size; ++i) position += axis.m_sizes[i] + borderThickness; return position - borderThickness; }
void RenderFrameSet::paintColumnBorder(const PaintInfo& paintInfo, const IntRect& borderRect) { if (!paintInfo.rect.intersects(borderRect)) return; // FIXME: We should do something clever when borders from distinct framesets meet at a join. // Fill first. GraphicsContext* context = paintInfo.context; ColorSpace colorSpace = style().colorSpace(); context->fillRect(borderRect, frameSetElement().hasBorderColor() ? style().visitedDependentColor(CSSPropertyBorderLeftColor) : borderFillColor(), colorSpace); // Now stroke the edges but only if we have enough room to paint both edges with a little // bit of the fill color showing through. if (borderRect.width() >= 3) { context->fillRect(IntRect(borderRect.location(), IntSize(1, height())), borderStartEdgeColor(), colorSpace); context->fillRect(IntRect(IntPoint(borderRect.maxX() - 1, borderRect.y()), IntSize(1, height())), borderEndEdgeColor(), colorSpace); } }
int RenderFrameSet::hitTestSplit(const GridAxis& axis, int position) const { if (needsLayout()) return noSplit; int borderThickness = frameSetElement().border(); if (borderThickness <= 0) return noSplit; size_t size = axis.m_sizes.size(); if (!size) return noSplit; int splitPosition = axis.m_sizes[0]; for (size_t i = 1; i < size; ++i) { if (position >= splitPosition && position < splitPosition + borderThickness) return i; splitPosition += borderThickness + axis.m_sizes[i]; } return noSplit; }
void RenderFrameSet::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset) { if (paintInfo.phase != PaintPhaseForeground) return; RenderObject* child = firstChild(); if (!child) return; LayoutPoint adjustedPaintOffset = paintOffset + location(); size_t rows = m_rows.m_sizes.size(); size_t cols = m_cols.m_sizes.size(); LayoutUnit borderThickness = frameSetElement().border(); LayoutUnit yPos = 0; for (size_t r = 0; r < rows; r++) { LayoutUnit xPos = 0; for (size_t c = 0; c < cols; c++) { toRenderElement(child)->paint(paintInfo, adjustedPaintOffset); xPos += m_cols.m_sizes[c]; if (borderThickness && m_cols.m_allowBorder[c + 1]) { paintColumnBorder(paintInfo, pixelSnappedIntRect(LayoutRect(adjustedPaintOffset.x() + xPos, adjustedPaintOffset.y() + yPos, borderThickness, height()))); xPos += borderThickness; } child = child->nextSibling(); if (!child) return; } yPos += m_rows.m_sizes[r]; if (borderThickness && m_rows.m_allowBorder[r + 1]) { paintRowBorder(paintInfo, pixelSnappedIntRect(LayoutRect(adjustedPaintOffset.x(), adjustedPaintOffset.y() + yPos, width(), borderThickness))); yPos += borderThickness; } } }
void RenderFrameSet::positionFramesWithFlattening() { RenderBox* child = firstChildBox(); if (!child) return; int rows = frameSetElement().totalRows(); int cols = frameSetElement().totalCols(); int borderThickness = frameSetElement().border(); bool repaintNeeded = false; // calculate frameset height based on actual content height to eliminate scrolling bool out = false; for (int r = 0; r < rows && !out; r++) { int extra = 0; int height = m_rows.m_sizes[r]; for (int c = 0; c < cols; c++) { IntRect oldFrameRect = pixelSnappedIntRect(child->frameRect()); int width = m_cols.m_sizes[c]; bool fixedWidth = frameSetElement().colLengths() && frameSetElement().colLengths()[c].isFixed(); bool fixedHeight = frameSetElement().rowLengths() && frameSetElement().rowLengths()[r].isFixed(); // has to be resized and itself resize its contents if (!fixedWidth) child->setWidth(width ? width + extra / (cols - c) : 0); else child->setWidth(width); child->setHeight(height); child->setNeedsLayout(); if (child->isFrameSet()) toRenderFrameSet(child)->layout(); else toRenderFrame(child)->layoutWithFlattening(fixedWidth, fixedHeight); if (child->height() > m_rows.m_sizes[r]) m_rows.m_sizes[r] = child->height(); if (child->width() > m_cols.m_sizes[c]) m_cols.m_sizes[c] = child->width(); if (child->frameRect() != oldFrameRect) repaintNeeded = true; // difference between calculated frame width and the width it actually decides to have extra += width - m_cols.m_sizes[c]; child = child->nextSiblingBox(); if (!child) { out = true; break; } } } int xPos = 0; int yPos = 0; out = false; child = firstChildBox(); for (int r = 0; r < rows && !out; r++) { xPos = 0; for (int c = 0; c < cols; c++) { // ensure the rows and columns are filled IntRect oldRect = pixelSnappedIntRect(child->frameRect()); child->setLocation(IntPoint(xPos, yPos)); child->setHeight(m_rows.m_sizes[r]); child->setWidth(m_cols.m_sizes[c]); if (child->frameRect() != oldRect) { repaintNeeded = true; // update to final size child->setNeedsLayout(); if (child->isFrameSet()) toRenderFrameSet(child)->layout(); else toRenderFrame(child)->layoutWithFlattening(true, true); } xPos += m_cols.m_sizes[c] + borderThickness; child = child->nextSiblingBox(); if (!child) { out = true; break; } } yPos += m_rows.m_sizes[r] + borderThickness; } setWidth(xPos - borderThickness); setHeight(yPos - borderThickness); if (repaintNeeded) repaint(); // all the remaining frames are hidden to avoid ugly spurious unflowed frames for (; child; child = child->nextSiblingBox()) { child->setWidth(0); child->setHeight(0); child->clearNeedsLayout(); } }