Index: Source/core/rendering/RenderBlock.cpp |
diff --git a/Source/core/rendering/RenderBlock.cpp b/Source/core/rendering/RenderBlock.cpp |
index 5d873a83ff09aba10beb5d9a24e06d69d593c644..04427a39aba1aad42c6243c76bd9ff8829da066d 100644 |
--- a/Source/core/rendering/RenderBlock.cpp |
+++ b/Source/core/rendering/RenderBlock.cpp |
@@ -38,6 +38,7 @@ |
#include "core/frame/LocalFrame.h" |
#include "core/frame/Settings.h" |
#include "core/page/Page.h" |
+#include "core/paint/BlockPainter.h" |
#include "core/paint/BoxPainter.h" |
#include "core/rendering/GraphicsContextAnnotator.h" |
#include "core/rendering/HitTestLocation.h" |
@@ -1758,214 +1759,7 @@ void RenderBlock::markForPaginationRelayoutIfNeeded(SubtreeLayoutScope& layoutSc |
void RenderBlock::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset) |
{ |
- ANNOTATE_GRAPHICS_CONTEXT(paintInfo, this); |
- |
- LayoutPoint adjustedPaintOffset = paintOffset + location(); |
- |
- PaintPhase phase = paintInfo.phase; |
- |
- LayoutRect overflowBox; |
- // Check if we need to do anything at all. |
- // FIXME: Could eliminate the isDocumentElement() check if we fix background painting so that the RenderView |
- // paints the root's background. |
- if (!isDocumentElement()) { |
- overflowBox = overflowRectForPaintRejection(); |
- flipForWritingMode(overflowBox); |
- overflowBox.moveBy(adjustedPaintOffset); |
- if (!overflowBox.intersects(paintInfo.rect)) |
- return; |
- } |
- |
- // There are some cases where not all clipped visual overflow is accounted for. |
- // FIXME: reduce the number of such cases. |
- ContentsClipBehavior contentsClipBehavior = ForceContentsClip; |
- if (hasOverflowClip() && !hasControlClip() && !(shouldPaintSelectionGaps() && phase == PaintPhaseForeground) && !hasCaret()) |
- contentsClipBehavior = SkipContentsClipIfPossible; |
- |
- bool pushedClip = pushContentsClip(paintInfo, adjustedPaintOffset, contentsClipBehavior); |
- { |
- GraphicsContextCullSaver cullSaver(*paintInfo.context); |
- // Cull if we have more than one child and we didn't already clip. |
- bool shouldCull = document().settings()->containerCullingEnabled() && !pushedClip && !isDocumentElement() |
- && firstChild() && lastChild() && firstChild() != lastChild(); |
- if (shouldCull) |
- cullSaver.cull(overflowBox); |
- |
- paintObject(paintInfo, adjustedPaintOffset); |
- } |
- if (pushedClip) |
- popContentsClip(paintInfo, phase, adjustedPaintOffset); |
- |
- // Our scrollbar widgets paint exactly when we tell them to, so that they work properly with |
- // z-index. We paint after we painted the background/border, so that the scrollbars will |
- // sit above the background/border. |
- if (hasOverflowClip() && style()->visibility() == VISIBLE && (phase == PaintPhaseBlockBackground || phase == PaintPhaseChildBlockBackground) && paintInfo.shouldPaintWithinRoot(this) && !paintInfo.paintRootBackgroundOnly()) |
- layer()->scrollableArea()->paintOverflowControls(paintInfo.context, roundedIntPoint(adjustedPaintOffset), paintInfo.rect, false /* paintingOverlayControls */); |
-} |
- |
-void RenderBlock::paintColumnRules(PaintInfo& paintInfo, const LayoutPoint& paintOffset) |
-{ |
- const Color& ruleColor = resolveColor(CSSPropertyWebkitColumnRuleColor); |
- bool ruleTransparent = style()->columnRuleIsTransparent(); |
- EBorderStyle ruleStyle = style()->columnRuleStyle(); |
- LayoutUnit ruleThickness = style()->columnRuleWidth(); |
- LayoutUnit colGap = columnGap(); |
- bool renderRule = ruleStyle > BHIDDEN && !ruleTransparent; |
- if (!renderRule) |
- return; |
- |
- ColumnInfo* colInfo = columnInfo(); |
- unsigned colCount = columnCount(colInfo); |
- |
- bool antialias = BoxPainter::shouldAntialiasLines(paintInfo.context); |
- |
- if (colInfo->progressionAxis() == ColumnInfo::InlineAxis) { |
- bool leftToRight = style()->isLeftToRightDirection(); |
- LayoutUnit currLogicalLeftOffset = leftToRight ? LayoutUnit() : contentLogicalWidth(); |
- LayoutUnit ruleAdd = logicalLeftOffsetForContent(); |
- LayoutUnit ruleLogicalLeft = leftToRight ? LayoutUnit() : contentLogicalWidth(); |
- LayoutUnit inlineDirectionSize = colInfo->desiredColumnWidth(); |
- BoxSide boxSide = isHorizontalWritingMode() |
- ? leftToRight ? BSLeft : BSRight |
- : leftToRight ? BSTop : BSBottom; |
- |
- for (unsigned i = 0; i < colCount; i++) { |
- // Move to the next position. |
- if (leftToRight) { |
- ruleLogicalLeft += inlineDirectionSize + colGap / 2; |
- currLogicalLeftOffset += inlineDirectionSize + colGap; |
- } else { |
- ruleLogicalLeft -= (inlineDirectionSize + colGap / 2); |
- currLogicalLeftOffset -= (inlineDirectionSize + colGap); |
- } |
- |
- // Now paint the column rule. |
- if (i < colCount - 1) { |
- LayoutUnit ruleLeft = isHorizontalWritingMode() ? paintOffset.x() + ruleLogicalLeft - ruleThickness / 2 + ruleAdd : paintOffset.x() + borderLeft() + paddingLeft(); |
- LayoutUnit ruleRight = isHorizontalWritingMode() ? ruleLeft + ruleThickness : ruleLeft + contentWidth(); |
- LayoutUnit ruleTop = isHorizontalWritingMode() ? paintOffset.y() + borderTop() + paddingTop() : paintOffset.y() + ruleLogicalLeft - ruleThickness / 2 + ruleAdd; |
- LayoutUnit ruleBottom = isHorizontalWritingMode() ? ruleTop + contentHeight() : ruleTop + ruleThickness; |
- IntRect pixelSnappedRuleRect = pixelSnappedIntRectFromEdges(ruleLeft, ruleTop, ruleRight, ruleBottom); |
- drawLineForBoxSide(paintInfo.context, pixelSnappedRuleRect.x(), pixelSnappedRuleRect.y(), pixelSnappedRuleRect.maxX(), pixelSnappedRuleRect.maxY(), boxSide, ruleColor, ruleStyle, 0, 0, antialias); |
- } |
- |
- ruleLogicalLeft = currLogicalLeftOffset; |
- } |
- } else { |
- bool topToBottom = !style()->isFlippedBlocksWritingMode(); |
- LayoutUnit ruleLeft = isHorizontalWritingMode() |
- ? borderLeft() + paddingLeft() |
- : colGap / 2 - colGap - ruleThickness / 2 + borderBefore() + paddingBefore(); |
- LayoutUnit ruleWidth = isHorizontalWritingMode() ? contentWidth() : ruleThickness; |
- LayoutUnit ruleTop = isHorizontalWritingMode() |
- ? colGap / 2 - colGap - ruleThickness / 2 + borderBefore() + paddingBefore() |
- : borderStart() + paddingStart(); |
- LayoutUnit ruleHeight = isHorizontalWritingMode() ? ruleThickness : contentHeight(); |
- LayoutRect ruleRect(ruleLeft, ruleTop, ruleWidth, ruleHeight); |
- |
- if (!topToBottom) { |
- if (isHorizontalWritingMode()) |
- ruleRect.setY(height() - ruleRect.maxY()); |
- else |
- ruleRect.setX(width() - ruleRect.maxX()); |
- } |
- |
- ruleRect.moveBy(paintOffset); |
- |
- BoxSide boxSide = isHorizontalWritingMode() |
- ? topToBottom ? BSTop : BSBottom |
- : topToBottom ? BSLeft : BSRight; |
- |
- LayoutSize step(0, topToBottom ? colInfo->columnHeight() + colGap : -(colInfo->columnHeight() + colGap)); |
- if (!isHorizontalWritingMode()) |
- step = step.transposedSize(); |
- |
- for (unsigned i = 1; i < colCount; i++) { |
- ruleRect.move(step); |
- IntRect pixelSnappedRuleRect = pixelSnappedIntRect(ruleRect); |
- drawLineForBoxSide(paintInfo.context, pixelSnappedRuleRect.x(), pixelSnappedRuleRect.y(), pixelSnappedRuleRect.maxX(), pixelSnappedRuleRect.maxY(), boxSide, ruleColor, ruleStyle, 0, 0, antialias); |
- } |
- } |
-} |
- |
-void RenderBlock::paintColumnContents(PaintInfo& paintInfo, const LayoutPoint& paintOffset, bool paintingFloats) |
-{ |
- // We need to do multiple passes, breaking up our child painting into strips. |
- GraphicsContext* context = paintInfo.context; |
- ColumnInfo* colInfo = columnInfo(); |
- unsigned colCount = columnCount(colInfo); |
- if (!colCount) |
- return; |
- LayoutUnit currLogicalTopOffset = 0; |
- LayoutUnit colGap = columnGap(); |
- for (unsigned i = 0; i < colCount; i++) { |
- // For each rect, we clip to the rect, and then we adjust our coords. |
- LayoutRect colRect = columnRectAt(colInfo, i); |
- flipForWritingMode(colRect); |
- LayoutUnit logicalLeftOffset = (isHorizontalWritingMode() ? colRect.x() : colRect.y()) - logicalLeftOffsetForContent(); |
- LayoutSize offset = isHorizontalWritingMode() ? LayoutSize(logicalLeftOffset, currLogicalTopOffset) : LayoutSize(currLogicalTopOffset, logicalLeftOffset); |
- if (colInfo->progressionAxis() == ColumnInfo::BlockAxis) { |
- if (isHorizontalWritingMode()) |
- offset.expand(0, colRect.y() - borderTop() - paddingTop()); |
- else |
- offset.expand(colRect.x() - borderLeft() - paddingLeft(), 0); |
- } |
- colRect.moveBy(paintOffset); |
- PaintInfo info(paintInfo); |
- info.rect.intersect(enclosingIntRect(colRect)); |
- |
- if (!info.rect.isEmpty()) { |
- GraphicsContextStateSaver stateSaver(*context); |
- LayoutRect clipRect(colRect); |
- |
- if (i < colCount - 1) { |
- if (isHorizontalWritingMode()) |
- clipRect.expand(colGap / 2, 0); |
- else |
- clipRect.expand(0, colGap / 2); |
- } |
- // Each strip pushes a clip, since column boxes are specified as being |
- // like overflow:hidden. |
- // FIXME: Content and column rules that extend outside column boxes at the edges of the multi-column element |
- // are clipped according to the 'overflow' property. |
- context->clip(enclosingIntRect(clipRect)); |
- |
- // Adjust our x and y when painting. |
- LayoutPoint adjustedPaintOffset = paintOffset + offset; |
- if (paintingFloats) |
- paintFloats(info, adjustedPaintOffset, paintInfo.phase == PaintPhaseSelection || paintInfo.phase == PaintPhaseTextClip); |
- else |
- paintContents(info, adjustedPaintOffset); |
- } |
- |
- LayoutUnit blockDelta = (isHorizontalWritingMode() ? colRect.height() : colRect.width()); |
- if (style()->isFlippedBlocksWritingMode()) |
- currLogicalTopOffset += blockDelta; |
- else |
- currLogicalTopOffset -= blockDelta; |
- } |
-} |
- |
-void RenderBlock::paintContents(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, styleResolverChanged() on the Document |
- // will do a full paint invalidation. |
- if (document().didLayoutWithPendingStylesheets() && !isRenderView()) |
- return; |
- |
- if (childrenInline()) |
- m_lineBoxes.paint(this, paintInfo, paintOffset); |
- else { |
- PaintPhase newPhase = (paintInfo.phase == PaintPhaseChildOutlines) ? PaintPhaseOutline : paintInfo.phase; |
- newPhase = (newPhase == PaintPhaseChildBlockBackgrounds) ? PaintPhaseChildBlockBackground : newPhase; |
- |
- // We don't paint our own background, but we do let the kids paint their backgrounds. |
- PaintInfo paintInfoForChild(paintInfo); |
- paintInfoForChild.phase = newPhase; |
- paintInfoForChild.updatePaintingRootForChildren(this); |
- paintChildren(paintInfoForChild, paintOffset); |
- } |
+ BlockPainter(*this).paint(paintInfo, paintOffset); |
} |
void RenderBlock::paintChildren(PaintInfo& paintInfo, const LayoutPoint& paintOffset) |
@@ -2013,114 +1807,9 @@ void RenderBlock::paintAsInlineBlock(RenderObject* renderer, PaintInfo& paintInf |
} |
} |
-static inline bool caretBrowsingEnabled(const Frame* frame) |
-{ |
- Settings* settings = frame->settings(); |
- return settings && settings->caretBrowsingEnabled(); |
-} |
- |
-static inline bool hasCursorCaret(const FrameSelection& selection, const RenderBlock* block, bool caretBrowsing) |
-{ |
- return selection.caretRenderer() == block && (selection.hasEditableStyle() || caretBrowsing); |
-} |
- |
-static inline bool hasDragCaret(const DragCaretController& dragCaretController, const RenderBlock* block, bool caretBrowsing) |
-{ |
- return dragCaretController.caretRenderer() == block && (dragCaretController.isContentEditable() || caretBrowsing); |
-} |
- |
-bool RenderBlock::hasCaret() const |
-{ |
- bool caretBrowsing = caretBrowsingEnabled(frame()); |
- return hasCursorCaret(frame()->selection(), this, caretBrowsing) |
- || hasDragCaret(frame()->page()->dragCaretController(), this, caretBrowsing); |
-} |
- |
-void RenderBlock::paintCarets(PaintInfo& paintInfo, const LayoutPoint& paintOffset) |
-{ |
- bool caretBrowsing = caretBrowsingEnabled(frame()); |
- |
- FrameSelection& selection = frame()->selection(); |
- if (hasCursorCaret(selection, this, caretBrowsing)) { |
- selection.paintCaret(paintInfo.context, paintOffset, paintInfo.rect); |
- } |
- |
- DragCaretController& dragCaretController = frame()->page()->dragCaretController(); |
- if (hasDragCaret(dragCaretController, this, caretBrowsing)) { |
- dragCaretController.paintDragCaret(frame(), paintInfo.context, paintOffset, paintInfo.rect); |
- } |
-} |
- |
void RenderBlock::paintObject(PaintInfo& paintInfo, const LayoutPoint& paintOffset) |
{ |
- PaintPhase paintPhase = paintInfo.phase; |
- |
- // Adjust our painting position if we're inside a scrolled layer (e.g., an overflow:auto div). |
- LayoutPoint scrolledOffset = paintOffset; |
- if (hasOverflowClip()) |
- scrolledOffset.move(-scrolledContentOffset()); |
- |
- // 1. paint background, borders etc |
- if ((paintPhase == PaintPhaseBlockBackground || paintPhase == PaintPhaseChildBlockBackground) && style()->visibility() == VISIBLE) { |
- if (hasBoxDecorationBackground()) |
- paintBoxDecorationBackground(paintInfo, paintOffset); |
- if (hasColumns() && !paintInfo.paintRootBackgroundOnly()) |
- paintColumnRules(paintInfo, scrolledOffset); |
- } |
- |
- if (paintPhase == PaintPhaseMask && style()->visibility() == VISIBLE) { |
- paintMask(paintInfo, paintOffset); |
- return; |
- } |
- |
- if (paintPhase == PaintPhaseClippingMask && style()->visibility() == VISIBLE) { |
- paintClippingMask(paintInfo, paintOffset); |
- return; |
- } |
- |
- // We're done. We don't bother painting any children. |
- if (paintPhase == PaintPhaseBlockBackground || paintInfo.paintRootBackgroundOnly()) |
- return; |
- |
- // 2. paint contents |
- if (paintPhase != PaintPhaseSelfOutline) { |
- if (hasColumns()) |
- paintColumnContents(paintInfo, scrolledOffset); |
- else |
- paintContents(paintInfo, scrolledOffset); |
- } |
- |
- // 3. paint selection |
- // FIXME: Make this work with multi column layouts. For now don't fill gaps. |
- bool isPrinting = document().printing(); |
- if (!isPrinting && !hasColumns()) |
- paintSelection(paintInfo, scrolledOffset); // Fill in gaps in selection on lines and between blocks. |
- |
- // 4. paint floats. |
- if (paintPhase == PaintPhaseFloat || paintPhase == PaintPhaseSelection || paintPhase == PaintPhaseTextClip) { |
- if (hasColumns()) |
- paintColumnContents(paintInfo, scrolledOffset, true); |
- else |
- paintFloats(paintInfo, scrolledOffset, paintPhase == PaintPhaseSelection || paintPhase == PaintPhaseTextClip); |
- } |
- |
- // 5. paint outline. |
- if ((paintPhase == PaintPhaseOutline || paintPhase == PaintPhaseSelfOutline) && style()->hasOutline() && style()->visibility() == VISIBLE) { |
- // Don't paint focus ring for anonymous block continuation because the |
- // inline element having outline-style:auto paints the whole focus ring. |
- if (!style()->outlineStyleIsAuto() || !isAnonymousBlockContinuation()) |
- paintOutline(paintInfo, LayoutRect(paintOffset, size())); |
- } |
- |
- // 6. paint continuation outlines. |
- if ((paintPhase == PaintPhaseOutline || paintPhase == PaintPhaseChildOutlines)) |
- paintContinuationOutlines(paintInfo, paintOffset); |
- |
- // 7. paint caret. |
- // If the caret's node's render object's containing block is this block, and the paint action is PaintPhaseForeground, |
- // then paint the caret. |
- if (paintPhase == PaintPhaseForeground) |
- paintCarets(paintInfo, paintOffset); |
+ BlockPainter(*this).paintObject(paintInfo, paintOffset); |
} |
RenderInline* RenderBlock::inlineElementContinuation() const |