void DetailsMarkerPainter::paint(const PaintInfo& paintInfo, const LayoutPoint& paintOffset) { if (paintInfo.phase != PaintPhaseForeground || m_layoutDetailsMarker.style()->visibility() != VISIBLE) { BlockPainter(m_layoutDetailsMarker).paint(paintInfo, paintOffset); return; } if (LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(paintInfo.context, m_layoutDetailsMarker, paintInfo.phase, paintOffset)) return; LayoutPoint boxOrigin(paintOffset + m_layoutDetailsMarker.location()); LayoutRect overflowRect(m_layoutDetailsMarker.visualOverflowRect()); overflowRect.moveBy(boxOrigin); if (!paintInfo.cullRect().intersectsCullRect(overflowRect)) return; LayoutObjectDrawingRecorder layoutDrawingRecorder(paintInfo.context, m_layoutDetailsMarker, paintInfo.phase, overflowRect, paintOffset); const Color color(m_layoutDetailsMarker.resolveColor(CSSPropertyColor)); paintInfo.context.setStrokeColor(color); paintInfo.context.setStrokeStyle(SolidStroke); paintInfo.context.setStrokeThickness(1.0f); paintInfo.context.setFillColor(color); boxOrigin.move(m_layoutDetailsMarker.borderLeft() + m_layoutDetailsMarker.paddingLeft(), m_layoutDetailsMarker.borderTop() + m_layoutDetailsMarker.paddingTop()); paintInfo.context.fillPath(getPath(boxOrigin)); }
void BlockPainter::paintChildrenOfFlexibleBox( const LayoutFlexibleBox& layoutFlexibleBox, const PaintInfo& paintInfo, const LayoutPoint& paintOffset) { for (const LayoutBox* child = layoutFlexibleBox.orderIterator().first(); child; child = layoutFlexibleBox.orderIterator().next()) BlockPainter(layoutFlexibleBox) .paintAllChildPhasesAtomically(*child, paintInfo, paintOffset); }
void SVGTextPainter::paint(const PaintInfo& paintInfo) { if (paintInfo.phase != PaintPhaseForeground && paintInfo.phase != PaintPhaseSelection) return; PaintInfo blockInfo(paintInfo); TransformRecorder transformRecorder(*blockInfo.context, m_renderSVGText.displayItemClient(), m_renderSVGText.localToParentTransform()); // When transitioning from SVG to block painters we need to keep the PaintInfo rect up-to-date // because it can be used for clipping. m_renderSVGText.updatePaintInfoRect(blockInfo.rect); BlockPainter(m_renderSVGText).paint(blockInfo, LayoutPoint()); // Paint the outlines, if any if (paintInfo.phase == PaintPhaseForeground) { blockInfo.phase = PaintPhaseSelfOutline; BlockPainter(m_renderSVGText).paint(blockInfo, LayoutPoint()); } }
void ViewPainter::paint(const PaintInfo& paintInfo, const LayoutPoint& paintOffset) { // If we ever require layout but receive a paint anyway, something has gone horribly wrong. ASSERT(!m_layoutView.needsLayout()); // LayoutViews should never be called to paint with an offset not on device pixels. ASSERT(LayoutPoint(IntPoint(paintOffset.x(), paintOffset.y())) == paintOffset); const FrameView* frameView = m_layoutView.frameView(); if (frameView->shouldThrottleRendering()) return; m_layoutView.paintObject(paintInfo, paintOffset); BlockPainter(m_layoutView).paintOverflowControlsIfNeeded(paintInfo, paintOffset); }
void SVGForeignObjectPainter::paint(PaintInfo& paintInfo) { if (paintInfo.phase != PaintPhaseForeground && paintInfo.phase != PaintPhaseSelection) return; PaintInfo childPaintInfo(paintInfo); GraphicsContextStateSaver stateSaver(*childPaintInfo.context); childPaintInfo.applyTransform(m_renderSVGForeignObject.localTransform()); if (SVGRenderSupport::isOverflowHidden(&m_renderSVGForeignObject)) childPaintInfo.context->clip(m_renderSVGForeignObject.viewportRect()); SVGRenderingContext renderingContext; bool continueRendering = true; if (paintInfo.phase == PaintPhaseForeground) { renderingContext.prepareToRenderSVGContent(&m_renderSVGForeignObject, childPaintInfo); continueRendering = renderingContext.isRenderingPrepared(); } if (continueRendering) { // Paint all phases of FO elements atomically as though the FO element established its own stacking context. bool preservePhase = paintInfo.phase == PaintPhaseSelection || paintInfo.phase == PaintPhaseTextClip; const LayoutPoint childPoint = IntPoint(); childPaintInfo.phase = preservePhase ? paintInfo.phase : PaintPhaseBlockBackground; BlockPainter(m_renderSVGForeignObject).paint(childPaintInfo, childPoint); if (!preservePhase) { childPaintInfo.phase = PaintPhaseChildBlockBackgrounds; BlockPainter(m_renderSVGForeignObject).paint(childPaintInfo, childPoint); childPaintInfo.phase = PaintPhaseFloat; BlockPainter(m_renderSVGForeignObject).paint(childPaintInfo, childPoint); childPaintInfo.phase = PaintPhaseForeground; BlockPainter(m_renderSVGForeignObject).paint(childPaintInfo, childPoint); childPaintInfo.phase = PaintPhaseOutline; BlockPainter(m_renderSVGForeignObject).paint(childPaintInfo, childPoint); } } }
void SVGForeignObjectPainter::paint(const PaintInfo& paintInfo) { if (paintInfo.phase != PaintPhaseForeground && paintInfo.phase != PaintPhaseSelection) return; PaintInfo paintInfoBeforeFiltering(paintInfo); paintInfoBeforeFiltering.updateCullRect(m_layoutSVGForeignObject.localTransform()); TransformRecorder transformRecorder(paintInfoBeforeFiltering.context, m_layoutSVGForeignObject, m_layoutSVGForeignObject.localTransform()); Optional<FloatClipRecorder> clipRecorder; if (SVGLayoutSupport::isOverflowHidden(&m_layoutSVGForeignObject)) clipRecorder.emplace(paintInfoBeforeFiltering.context, m_layoutSVGForeignObject, paintInfoBeforeFiltering.phase, m_layoutSVGForeignObject.viewportRect()); SVGPaintContext paintContext(m_layoutSVGForeignObject, paintInfoBeforeFiltering); bool continueRendering = true; if (paintContext.paintInfo().phase == PaintPhaseForeground) continueRendering = paintContext.applyClipMaskAndFilterIfNecessary(); if (continueRendering) { // Paint all phases of FO elements atomically as though the FO element established its own stacking context. bool preservePhase = paintContext.paintInfo().phase == PaintPhaseSelection || paintContext.paintInfo().phase == PaintPhaseTextClip; const LayoutPoint childPoint = IntPoint(); paintContext.paintInfo().phase = preservePhase ? paintContext.paintInfo().phase : PaintPhaseBlockBackground; BlockPainter(m_layoutSVGForeignObject).paint(paintContext.paintInfo(), childPoint); if (!preservePhase) { paintContext.paintInfo().phase = PaintPhaseChildBlockBackgrounds; BlockPainter(m_layoutSVGForeignObject).paint(paintContext.paintInfo(), childPoint); paintContext.paintInfo().phase = PaintPhaseFloat; BlockPainter(m_layoutSVGForeignObject).paint(paintContext.paintInfo(), childPoint); paintContext.paintInfo().phase = PaintPhaseForeground; BlockPainter(m_layoutSVGForeignObject).paint(paintContext.paintInfo(), childPoint); paintContext.paintInfo().phase = PaintPhaseOutline; BlockPainter(m_layoutSVGForeignObject).paint(paintContext.paintInfo(), childPoint); } } }
void TableSectionPainter::paintCell(LayoutTableCell* cell, const PaintInfo& paintInfo, const LayoutPoint& paintOffset) { LayoutPoint cellPoint = m_layoutTableSection.flipForWritingModeForChild(cell, paintOffset); PaintPhase paintPhase = paintInfo.phase; LayoutTableRow* row = toLayoutTableRow(cell->parent()); if ((paintPhase == PaintPhaseBlockBackground || paintPhase == PaintPhaseChildBlockBackground) && BlockPainter(*cell).intersectsPaintRect(paintInfo, paintOffset)) { // We need to handle painting a stack of backgrounds. This stack (from bottom to top) consists of // the column group, column, row group, row, and then the cell. LayoutTableCol* column = m_layoutTableSection.table()->colElement(cell->col()); LayoutTableCol* columnGroup = column ? column->enclosingColumnGroup() : 0; bool columnHasBackground = column && column->hasBackground(); bool columnGroupHasBackground = columnGroup && columnGroup->hasBackground(); bool sectionHasBackground = m_layoutTableSection.hasBackground(); bool rowHasBackground = row->hasBackground(); if (columnHasBackground || columnGroupHasBackground || sectionHasBackground || rowHasBackground) { TableCellPainter tableCellPainter(*cell); if (!LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(*paintInfo.context, *cell, DisplayItem::TableCellBackgroundFromContainers, paintOffset)) { LayoutObjectDrawingRecorder recorder(*paintInfo.context, *cell, DisplayItem::TableCellBackgroundFromContainers, tableCellPainter.paintBounds(cellPoint, TableCellPainter::AddOffsetFromParent), paintOffset); // Column groups and columns first. // FIXME: Columns and column groups do not currently support opacity, and they are being painted "too late" in // the stack, since we have already opened a transparency layer (potentially) for the table row group. // Note that we deliberately ignore whether or not the cell has a layer, since these backgrounds paint "behind" the // cell. if (columnGroupHasBackground) tableCellPainter.paintBackgroundsBehindCell(paintInfo, cellPoint, columnGroup); if (columnHasBackground) tableCellPainter.paintBackgroundsBehindCell(paintInfo, cellPoint, column); // Paint the row group next. if (sectionHasBackground) tableCellPainter.paintBackgroundsBehindCell(paintInfo, cellPoint, &m_layoutTableSection); // Paint the row next, but only if it doesn't have a layer. If a row has a layer, it will be responsible for // painting the row background for the cell. if (rowHasBackground && !row->hasSelfPaintingLayer()) tableCellPainter.paintBackgroundsBehindCell(paintInfo, cellPoint, row); } } } if ((!cell->hasSelfPaintingLayer() && !row->hasSelfPaintingLayer())) cell->paint(paintInfo, cellPoint); }
void MultiColumnSetPainter::paintObject(PaintInfo& paintInfo, const LayoutPoint& paintOffset) { if (m_renderMultiColumnSet.style()->visibility() != VISIBLE) return; BlockPainter(m_renderMultiColumnSet).paintObject(paintInfo, paintOffset); // FIXME: Right now we're only painting in the foreground phase. // Columns should technically respect phases and allow for background/float/foreground overlap etc., just like // RenderBlocks do. Note this is a pretty minor issue, since the old column implementation clipped columns // anyway, thus making it impossible for them to overlap one another. It's also really unlikely that the columns // would overlap another block. if (!m_renderMultiColumnSet.flowThread() || !m_renderMultiColumnSet.isValid() || (paintInfo.phase != PaintPhaseForeground && paintInfo.phase != PaintPhaseSelection)) return; paintColumnRules(paintInfo, paintOffset); }
void BlockFlowPainter::paintContents(const PaintInfo& paintInfo, const LayoutPoint& paintOffset) { // Avoid painting descendants of the root element when stylesheets haven't // loaded. This eliminates FOUC. It's ok not to draw, because later on, when // all the stylesheets do load, styleResolverMayHaveChanged() on Document will // trigger a full paint invalidation. if (m_layoutBlockFlow.document().didLayoutWithPendingStylesheets() && !m_layoutBlockFlow.isLayoutView()) return; if (!m_layoutBlockFlow.childrenInline()) { BlockPainter(m_layoutBlockFlow).paintContents(paintInfo, paintOffset); return; } if (shouldPaintDescendantOutlines(paintInfo.phase)) ObjectPainter(m_layoutBlockFlow) .paintInlineChildrenOutlines(paintInfo, paintOffset); else LineBoxListPainter(m_layoutBlockFlow.lineBoxes()) .paint(m_layoutBlockFlow, paintInfo, paintOffset); }
void TableSectionPainter::paintCell(const LayoutTableCell& cell, const PaintInfo& paintInfo, const LayoutPoint& paintOffset) { LayoutPoint cellPoint = m_layoutTableSection.flipForWritingModeForChild(&cell, paintOffset); PaintPhase paintPhase = paintInfo.phase; const LayoutTableRow* row = toLayoutTableRow(cell.parent()); if ((paintPhase == PaintPhaseSelfBlockBackground || paintPhase == PaintPhaseBlockBackground) && BlockPainter(cell).intersectsPaintRect(paintInfo, paintOffset)) { // We need to handle painting a stack of backgrounds. This stack (from bottom to top) consists of // the column group, column, row group, row, and then the cell. LayoutTable::ColAndColGroup colAndColGroup = m_layoutTableSection.table()->colElement(cell.col()); LayoutTableCol* column = colAndColGroup.col; LayoutTableCol* columnGroup = colAndColGroup.colgroup; TableCellPainter tableCellPainter(cell); // Column groups and columns first. // FIXME: Columns and column groups do not currently support opacity, and they are being painted "too late" in // the stack, since we have already opened a transparency layer (potentially) for the table row group. // Note that we deliberately ignore whether or not the cell has a layer, since these backgrounds paint "behind" the // cell. if (columnGroup && columnGroup->hasBackground()) tableCellPainter.paintBackgroundsBehindCell(paintInfo, cellPoint, columnGroup, DisplayItem::TableCellBackgroundFromColumnGroup); if (column && column->hasBackground()) tableCellPainter.paintBackgroundsBehindCell(paintInfo, cellPoint, column, DisplayItem::TableCellBackgroundFromColumn); // Paint the row group next. if (m_layoutTableSection.hasBackground()) tableCellPainter.paintBackgroundsBehindCell(paintInfo, cellPoint, &m_layoutTableSection, DisplayItem::TableCellBackgroundFromSection); // Paint the row next, but only if it doesn't have a layer. If a row has a layer, it will be responsible for // painting the row background for the cell. if (row->hasBackground() && !row->hasSelfPaintingLayer()) tableCellPainter.paintBackgroundsBehindCell(paintInfo, cellPoint, row, DisplayItem::TableCellBackgroundFromRow); } if ((!cell.hasSelfPaintingLayer() && !row->hasSelfPaintingLayer())) cell.paint(paintInfo, cellPoint); }
void BlockPainter::paintChildrenOfFlexibleBox(LayoutFlexibleBox& layoutFlexibleBox, const PaintInfo& paintInfo, const LayoutPoint& paintOffset) { for (LayoutBox* child = layoutFlexibleBox.orderIterator().first(); child; child = layoutFlexibleBox.orderIterator().next()) BlockPainter(layoutFlexibleBox).paintChildAsInlineBlock(*child, paintInfo, paintOffset); }
void GridPainter::paintChildren(const PaintInfo& paintInfo, const LayoutPoint& paintOffset) { DCHECK(!m_layoutGrid.needsLayout()); LayoutRect localVisualRect = LayoutRect(paintInfo.cullRect().m_rect); localVisualRect.moveBy(-paintOffset); Vector<LayoutUnit> columnPositions = m_layoutGrid.columnPositions(); if (!m_layoutGrid.styleRef().isLeftToRightDirection()) { // Translate columnPositions in RTL as we need the physical coordinates of // the columns in order to call dirtiedGridAreas(). for (size_t i = 0; i < columnPositions.size(); i++) columnPositions[i] = m_layoutGrid.translateRTLCoordinate(columnPositions[i]); // We change the order of tracks in columnPositions, as in RTL the leftmost // track will be the last one. std::sort(columnPositions.begin(), columnPositions.end()); } GridSpan dirtiedColumns = dirtiedGridAreas( columnPositions, localVisualRect.x(), localVisualRect.maxX()); GridSpan dirtiedRows = dirtiedGridAreas( m_layoutGrid.rowPositions(), localVisualRect.y(), localVisualRect.maxY()); if (!m_layoutGrid.styleRef().isLeftToRightDirection()) { // As we changed the order of tracks previously, we need to swap the dirtied // columns in RTL. size_t lastLine = columnPositions.size() - 1; dirtiedColumns = GridSpan::translatedDefiniteGridSpan( lastLine - dirtiedColumns.endLine(), lastLine - dirtiedColumns.startLine()); } Vector<std::pair<LayoutBox*, size_t>> gridItemsToBePainted; for (const auto& row : dirtiedRows) { for (const auto& column : dirtiedColumns) { const Vector<LayoutBox*, 1>& children = m_layoutGrid.gridCell(row, column); for (auto* child : children) gridItemsToBePainted.append( std::make_pair(child, m_layoutGrid.paintIndexForGridItem(child))); } } for (auto* item : m_layoutGrid.itemsOverflowingGridArea()) { if (item->frameRect().intersects(localVisualRect)) gridItemsToBePainted.append( std::make_pair(item, m_layoutGrid.paintIndexForGridItem(item))); } std::stable_sort(gridItemsToBePainted.begin(), gridItemsToBePainted.end(), compareOrderModifiedDocumentOrder); LayoutBox* previous = 0; for (const auto& gridItemAndPaintIndex : gridItemsToBePainted) { // We might have duplicates because of spanning children are included in all // cells they span. Skip them here to avoid painting items several times. LayoutBox* current = gridItemAndPaintIndex.first; if (current == previous) continue; BlockPainter(m_layoutGrid) .paintAllChildPhasesAtomically(*current, paintInfo, paintOffset); previous = current; } }
void TableCellPainter::paint(const PaintInfo& paintInfo, const LayoutPoint& paintOffset) { BlockPainter(m_layoutTableCell).paint(paintInfo, paintOffset); }
void TableCellPainter::paint(const PaintInfo& paintInfo, const LayoutPoint& paintOffset) { ASSERT(paintInfo.phase != PaintPhaseCollapsedTableBorders); BlockPainter(m_layoutTableCell).paint(paintInfo, paintOffset); }