Commit 04283387 authored by jbroman@chromium.org's avatar jbroman@chromium.org

Simplify InlineFlowBox::paintBoxDecorations.

This change:
* simplifies the paintPhase checks in InlineFlowBox::paint
* clarifies and moves the "should paint box decorations" check above
  other work, including the roundedFrameRect computation
* makes some internal painting methods private
* fixes the name of "adjustedPaintOffset"
* resolves lint errors that arose during the above

3% reduction in record time on desktop Wikipedia.
Negligible impact on N7 key_silk_cases.

BUG=388946

Review URL: https://codereview.chromium.org/352903002

git-svn-id: svn://svn.chromium.org/blink/trunk@177180 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent 5a38d268
...@@ -1095,59 +1095,52 @@ void InlineFlowBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset, ...@@ -1095,59 +1095,52 @@ void InlineFlowBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset,
if (!paintInfo.rect.intersects(pixelSnappedIntRect(overflowRect))) if (!paintInfo.rect.intersects(pixelSnappedIntRect(overflowRect)))
return; return;
if (paintInfo.phase != PaintPhaseChildOutlines) { if (paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline) {
if (paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline) { // Add ourselves to the paint info struct's list of inlines that need to paint their
// Add ourselves to the paint info struct's list of inlines that need to paint their // outlines.
// outlines. if (renderer().style()->visibility() == VISIBLE && renderer().hasOutline() && !isRootInlineBox()) {
if (renderer().style()->visibility() == VISIBLE && renderer().hasOutline() && !isRootInlineBox()) { RenderInline& inlineFlow = toRenderInline(renderer());
RenderInline& inlineFlow = toRenderInline(renderer());
RenderBlock* cb = 0;
RenderBlock* cb = 0; bool containingBlockPaintsContinuationOutline = inlineFlow.continuation() || inlineFlow.isInlineElementContinuation();
bool containingBlockPaintsContinuationOutline = inlineFlow.continuation() || inlineFlow.isInlineElementContinuation(); if (containingBlockPaintsContinuationOutline) {
if (containingBlockPaintsContinuationOutline) { // FIXME: See https://bugs.webkit.org/show_bug.cgi?id=54690. We currently don't reconnect inline continuations
// FIXME: See https://bugs.webkit.org/show_bug.cgi?id=54690. We currently don't reconnect inline continuations // after a child removal. As a result, those merged inlines do not get seperated and hence not get enclosed by
// after a child removal. As a result, those merged inlines do not get seperated and hence not get enclosed by // anonymous blocks. In this case, it is better to bail out and paint it ourself.
// anonymous blocks. In this case, it is better to bail out and paint it ourself. RenderBlock* enclosingAnonymousBlock = renderer().containingBlock();
RenderBlock* enclosingAnonymousBlock = renderer().containingBlock(); if (!enclosingAnonymousBlock->isAnonymousBlock()) {
if (!enclosingAnonymousBlock->isAnonymousBlock()) containingBlockPaintsContinuationOutline = false;
containingBlockPaintsContinuationOutline = false; } else {
else { cb = enclosingAnonymousBlock->containingBlock();
cb = enclosingAnonymousBlock->containingBlock(); for (RenderBoxModelObject* box = boxModelObject(); box != cb; box = box->parent()->enclosingBoxModelObject()) {
for (RenderBoxModelObject* box = boxModelObject(); box != cb; box = box->parent()->enclosingBoxModelObject()) { if (box->hasSelfPaintingLayer()) {
if (box->hasSelfPaintingLayer()) { containingBlockPaintsContinuationOutline = false;
containingBlockPaintsContinuationOutline = false; break;
break;
}
} }
} }
} }
}
if (containingBlockPaintsContinuationOutline) { if (containingBlockPaintsContinuationOutline) {
// Add ourselves to the containing block of the entire continuation so that it can // Add ourselves to the containing block of the entire continuation so that it can
// paint us atomically. // paint us atomically.
cb->addContinuationWithOutline(toRenderInline(renderer().node()->renderer())); cb->addContinuationWithOutline(toRenderInline(renderer().node()->renderer()));
} else if (!inlineFlow.isInlineElementContinuation()) { } else if (!inlineFlow.isInlineElementContinuation()) {
paintInfo.outlineObjects()->add(&inlineFlow); paintInfo.outlineObjects()->add(&inlineFlow);
}
} }
} else if (paintInfo.phase == PaintPhaseMask) {
paintMask(paintInfo, paintOffset);
return;
} else {
// Paint our background, border and box-shadow.
paintBoxDecorations(paintInfo, paintOffset);
} }
} } else if (paintInfo.phase == PaintPhaseMask) {
paintMask(paintInfo, paintOffset);
if (paintInfo.phase == PaintPhaseMask)
return; return;
} else if (paintInfo.phase == PaintPhaseForeground) {
PaintPhase paintPhase = paintInfo.phase == PaintPhaseChildOutlines ? PaintPhaseOutline : paintInfo.phase; // Paint our background, border and box-shadow.
paintBoxDecorations(paintInfo, paintOffset);
}
// Paint our children. // Paint our children.
if (paintPhase != PaintPhaseSelfOutline) { if (paintInfo.phase != PaintPhaseSelfOutline) {
PaintInfo childInfo(paintInfo); PaintInfo childInfo(paintInfo);
childInfo.phase = paintPhase; childInfo.phase = paintInfo.phase == PaintPhaseChildOutlines ? PaintPhaseOutline : paintInfo.phase;
if (childInfo.paintingRoot && childInfo.paintingRoot->isDescendantOf(&renderer())) if (childInfo.paintingRoot && childInfo.paintingRoot->isDescendantOf(&renderer()))
childInfo.paintingRoot = 0; childInfo.paintingRoot = 0;
...@@ -1281,72 +1274,78 @@ static LayoutRect clipRectForNinePieceImageStrip(InlineFlowBox* box, const NineP ...@@ -1281,72 +1274,78 @@ static LayoutRect clipRectForNinePieceImageStrip(InlineFlowBox* box, const NineP
void InlineFlowBox::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint& paintOffset) void InlineFlowBox::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{ {
if (!paintInfo.shouldPaintWithinRoot(&renderer()) || renderer().style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseForeground) ASSERT(paintInfo.phase == PaintPhaseForeground);
if (!paintInfo.shouldPaintWithinRoot(&renderer()) || renderer().style()->visibility() != VISIBLE)
return;
// You can use p::first-line to specify a background. If so, the root line boxes for
// a line may actually have to paint a background.
RenderStyle* styleToUse = renderer().style(isFirstLineStyle());
bool shouldPaintBoxDecorations;
if (parent())
shouldPaintBoxDecorations = renderer().hasBoxDecorations();
else
shouldPaintBoxDecorations = isFirstLineStyle() && styleToUse != renderer().style();
if (!shouldPaintBoxDecorations)
return; return;
// Pixel snap background/border painting. // Pixel snap background/border painting.
LayoutRect frameRect = roundedFrameRect(); LayoutRect frameRect = roundedFrameRect();
constrainToLineTopAndBottomIfNeeded(frameRect); constrainToLineTopAndBottomIfNeeded(frameRect);
// Move x/y to our coordinates. // Move x/y to our coordinates.
LayoutRect localRect(frameRect); LayoutRect localRect(frameRect);
flipForWritingMode(localRect); flipForWritingMode(localRect);
LayoutPoint adjustedPaintoffset = paintOffset + localRect.location(); LayoutPoint adjustedPaintOffset = paintOffset + localRect.location();
GraphicsContext* context = paintInfo.context; LayoutRect paintRect = LayoutRect(adjustedPaintOffset, frameRect.size());
// You can use p::first-line to specify a background. If so, the root line boxes for // Shadow comes first and is behind the background and border.
// a line may actually have to paint a background. if (!boxModelObject()->boxShadowShouldBeAppliedToBackground(BackgroundBleedNone, this))
RenderStyle* styleToUse = renderer().style(isFirstLineStyle()); paintBoxShadow(paintInfo, styleToUse, Normal, paintRect);
if ((!parent() && isFirstLineStyle() && styleToUse != renderer().style()) || (parent() && renderer().hasBoxDecorations())) {
LayoutRect paintRect = LayoutRect(adjustedPaintoffset, frameRect.size()); Color backgroundColor = renderer().resolveColor(styleToUse, CSSPropertyBackgroundColor);
// Shadow comes first and is behind the background and border. paintFillLayers(paintInfo, backgroundColor, styleToUse->backgroundLayers(), paintRect);
if (!boxModelObject()->boxShadowShouldBeAppliedToBackground(BackgroundBleedNone, this)) paintBoxShadow(paintInfo, styleToUse, Inset, paintRect);
paintBoxShadow(paintInfo, styleToUse, Normal, paintRect);
// :first-line cannot be used to put borders on a line. Always paint borders with our
Color c = renderer().resolveColor(styleToUse, CSSPropertyBackgroundColor); // non-first-line style.
paintFillLayers(paintInfo, c, styleToUse->backgroundLayers(), paintRect); if (parent() && renderer().style()->hasBorder()) {
paintBoxShadow(paintInfo, styleToUse, Inset, paintRect); const NinePieceImage& borderImage = renderer().style()->borderImage();
StyleImage* borderImageSource = borderImage.image();
// :first-line cannot be used to put borders on a line. Always paint borders with our bool hasBorderImage = borderImageSource && borderImageSource->canRender(renderer(), styleToUse->effectiveZoom());
// non-first-line style. if (hasBorderImage && !borderImageSource->isLoaded())
if (parent() && renderer().style()->hasBorder()) { return; // Don't paint anything while we wait for the image to load.
const NinePieceImage& borderImage = renderer().style()->borderImage();
StyleImage* borderImageSource = borderImage.image(); // The simple case is where we either have no border image or we are the only box for this object.
bool hasBorderImage = borderImageSource && borderImageSource->canRender(renderer(), styleToUse->effectiveZoom()); // In those cases only a single call to draw is required.
if (hasBorderImage && !borderImageSource->isLoaded()) if (!hasBorderImage || (!prevLineBox() && !nextLineBox())) {
return; // Don't paint anything while we wait for the image to load. boxModelObject()->paintBorder(paintInfo, paintRect, renderer().style(isFirstLineStyle()), BackgroundBleedNone, includeLogicalLeftEdge(), includeLogicalRightEdge());
} else {
// The simple case is where we either have no border image or we are the only box for this object. In those // We have a border image that spans multiple lines.
// cases only a single call to draw is required. // We need to adjust tx and ty by the width of all previous lines.
if (!hasBorderImage || (!prevLineBox() && !nextLineBox())) // Think of border image painting on inlines as though you had one long line, a single continuous
boxModelObject()->paintBorder(paintInfo, paintRect, renderer().style(isFirstLineStyle()), BackgroundBleedNone, includeLogicalLeftEdge(), includeLogicalRightEdge()); // strip. Even though that strip has been broken up across multiple lines, you still paint it
else { // as though you had one single line. This means each line has to pick up the image where
// We have a border image that spans multiple lines. // the previous line left off.
// We need to adjust tx and ty by the width of all previous lines. // FIXME: What the heck do we do with RTL here? The math we're using is obviously not right,
// Think of border image painting on inlines as though you had one long line, a single continuous // but it isn't even clear how this should work at all.
// strip. Even though that strip has been broken up across multiple lines, you still paint it LayoutUnit logicalOffsetOnLine = 0;
// as though you had one single line. This means each line has to pick up the image where for (InlineFlowBox* curr = prevLineBox(); curr; curr = curr->prevLineBox())
// the previous line left off. logicalOffsetOnLine += curr->logicalWidth();
// FIXME: What the heck do we do with RTL here? The math we're using is obviously not right, LayoutUnit totalLogicalWidth = logicalOffsetOnLine;
// but it isn't even clear how this should work at all. for (InlineFlowBox* curr = this; curr; curr = curr->nextLineBox())
LayoutUnit logicalOffsetOnLine = 0; totalLogicalWidth += curr->logicalWidth();
for (InlineFlowBox* curr = prevLineBox(); curr; curr = curr->prevLineBox()) LayoutUnit stripX = adjustedPaintOffset.x() - (isHorizontal() ? logicalOffsetOnLine : LayoutUnit());
logicalOffsetOnLine += curr->logicalWidth(); LayoutUnit stripY = adjustedPaintOffset.y() - (isHorizontal() ? LayoutUnit() : logicalOffsetOnLine);
LayoutUnit totalLogicalWidth = logicalOffsetOnLine; LayoutUnit stripWidth = isHorizontal() ? totalLogicalWidth : frameRect.width();
for (InlineFlowBox* curr = this; curr; curr = curr->nextLineBox()) LayoutUnit stripHeight = isHorizontal() ? frameRect.height() : totalLogicalWidth;
totalLogicalWidth += curr->logicalWidth();
LayoutUnit stripX = adjustedPaintoffset.x() - (isHorizontal() ? logicalOffsetOnLine : LayoutUnit()); LayoutRect clipRect = clipRectForNinePieceImageStrip(this, borderImage, paintRect);
LayoutUnit stripY = adjustedPaintoffset.y() - (isHorizontal() ? LayoutUnit() : logicalOffsetOnLine); GraphicsContextStateSaver stateSaver(*paintInfo.context);
LayoutUnit stripWidth = isHorizontal() ? totalLogicalWidth : frameRect.width(); paintInfo.context->clip(clipRect);
LayoutUnit stripHeight = isHorizontal() ? frameRect.height() : totalLogicalWidth; boxModelObject()->paintBorder(paintInfo, LayoutRect(stripX, stripY, stripWidth, stripHeight), renderer().style(isFirstLineStyle()));
LayoutRect clipRect = clipRectForNinePieceImageStrip(this, borderImage, paintRect);
GraphicsContextStateSaver stateSaver(*context);
context->clip(clipRect);
boxModelObject()->paintBorder(paintInfo, LayoutRect(stripX, stripY, stripWidth, stripHeight), renderer().style(isFirstLineStyle()));
}
} }
} }
} }
......
...@@ -112,11 +112,6 @@ public: ...@@ -112,11 +112,6 @@ public:
IntRect roundedFrameRect() const; IntRect roundedFrameRect() const;
void paintBoxDecorations(PaintInfo&, const LayoutPoint&);
void paintMask(PaintInfo&, const LayoutPoint&);
void paintFillLayers(const PaintInfo&, const Color&, const FillLayer*, const LayoutRect&, CompositeOperator = CompositeSourceOver);
void paintFillLayer(const PaintInfo&, const Color&, const FillLayer*, const LayoutRect&, CompositeOperator = CompositeSourceOver);
void paintBoxShadow(const PaintInfo&, RenderStyle*, ShadowStyle, const LayoutRect&);
virtual void paint(PaintInfo&, const LayoutPoint&, LayoutUnit lineTop, LayoutUnit lineBottom) OVERRIDE; virtual void paint(PaintInfo&, const LayoutPoint&, LayoutUnit lineTop, LayoutUnit lineBottom) OVERRIDE;
virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit lineTop, LayoutUnit lineBottom) OVERRIDE; virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit lineTop, LayoutUnit lineBottom) OVERRIDE;
...@@ -301,6 +296,12 @@ public: ...@@ -301,6 +296,12 @@ public:
} }
private: private:
void paintBoxDecorations(PaintInfo&, const LayoutPoint&);
void paintMask(PaintInfo&, const LayoutPoint&);
void paintFillLayers(const PaintInfo&, const Color&, const FillLayer*, const LayoutRect&, CompositeOperator = CompositeSourceOver);
void paintFillLayer(const PaintInfo&, const Color&, const FillLayer*, const LayoutRect&, CompositeOperator = CompositeSourceOver);
void paintBoxShadow(const PaintInfo&, RenderStyle*, ShadowStyle, const LayoutRect&);
void addBoxShadowVisualOverflow(LayoutRect& logicalVisualOverflow); void addBoxShadowVisualOverflow(LayoutRect& logicalVisualOverflow);
void addBorderOutsetVisualOverflow(LayoutRect& logicalVisualOverflow); void addBorderOutsetVisualOverflow(LayoutRect& logicalVisualOverflow);
void addOutlineVisualOverflow(LayoutRect& logicalVisualOverflow); void addOutlineVisualOverflow(LayoutRect& logicalVisualOverflow);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment