Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1408)

Unified Diff: Source/core/rendering/RenderBox.cpp

Issue 550363004: Factor painting code out of RenderBox into a new class called BoxPainter. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: fix Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « Source/core/rendering/RenderBox.h ('k') | Source/core/rendering/RenderBoxModelObject.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: Source/core/rendering/RenderBox.cpp
diff --git a/Source/core/rendering/RenderBox.cpp b/Source/core/rendering/RenderBox.cpp
index b806e2cf2df5a3e0ef3cacef92aae2d3646e6ae2..7fafa29ea302ac3326f9d2db3e4c2a0254b92f57 100644
--- a/Source/core/rendering/RenderBox.cpp
+++ b/Source/core/rendering/RenderBox.cpp
@@ -40,6 +40,7 @@
#include "core/page/AutoscrollController.h"
#include "core/page/EventHandler.h"
#include "core/page/Page.h"
+#include "core/paint/BoxPainter.h"
#include "core/rendering/HitTestResult.h"
#include "core/rendering/PaintInfo.h"
#include "core/rendering/RenderDeprecatedFlexibleBox.h"
@@ -51,13 +52,11 @@
#include "core/rendering/RenderListBox.h"
#include "core/rendering/RenderListMarker.h"
#include "core/rendering/RenderTableCell.h"
-#include "core/rendering/RenderTheme.h"
#include "core/rendering/RenderView.h"
#include "core/rendering/compositing/RenderLayerCompositor.h"
#include "platform/LengthFunctions.h"
#include "platform/geometry/FloatQuad.h"
#include "platform/geometry/TransformState.h"
-#include "platform/graphics/GraphicsContextStateSaver.h"
#include <algorithm>
#include <math.h>
@@ -1076,123 +1075,17 @@ bool RenderBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result
return false;
}
-// --------------------- painting stuff -------------------------------
-
void RenderBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
- LayoutPoint adjustedPaintOffset = paintOffset + location();
- // default implementation. Just pass paint through to the children
- PaintInfo childInfo(paintInfo);
- childInfo.updatePaintingRootForChildren(this);
- for (RenderObject* child = slowFirstChild(); child; child = child->nextSibling())
- child->paint(childInfo, adjustedPaintOffset);
-}
-
-void RenderBox::paintRootBoxFillLayers(const PaintInfo& paintInfo)
-{
- if (paintInfo.skipRootBackground())
- return;
-
- RenderObject* rootBackgroundRenderer = rendererForRootBackground();
-
- const FillLayer& bgLayer = rootBackgroundRenderer->style()->backgroundLayers();
- Color bgColor = rootBackgroundRenderer->resolveColor(CSSPropertyBackgroundColor);
-
- paintFillLayers(paintInfo, bgColor, bgLayer, view()->backgroundRect(this), BackgroundBleedNone, CompositeSourceOver, rootBackgroundRenderer);
+ BoxPainter(*this).paint(paintInfo, paintOffset);
}
-BackgroundBleedAvoidance RenderBox::determineBackgroundBleedAvoidance(GraphicsContext* context, const BoxDecorationData& boxDecorationData) const
-{
- if (!boxDecorationData.hasBackground || !boxDecorationData.hasBorder || !style()->hasBorderRadius() || canRenderBorderImage())
- return BackgroundBleedNone;
-
- // FIXME: See crbug.com/382491. getCTM does not accurately reflect the scale at the time content is
- // rasterized, and should not be relied on to make decisions about bleeding.
- AffineTransform ctm = context->getCTM();
- FloatSize contextScaling(static_cast<float>(ctm.xScale()), static_cast<float>(ctm.yScale()));
-
- // Because RoundedRect uses IntRect internally the inset applied by the
- // BackgroundBleedShrinkBackground strategy cannot be less than one integer
- // layout coordinate, even with subpixel layout enabled. To take that into
- // account, we clamp the contextScaling to 1.0 for the following test so
- // that borderObscuresBackgroundEdge can only return true if the border
- // widths are greater than 2 in both layout coordinates and screen
- // coordinates.
- // This precaution will become obsolete if RoundedRect is ever promoted to
- // a sub-pixel representation.
- if (contextScaling.width() > 1)
- contextScaling.setWidth(1);
- if (contextScaling.height() > 1)
- contextScaling.setHeight(1);
-
- if (borderObscuresBackgroundEdge(contextScaling))
- return BackgroundBleedShrinkBackground;
- if (!boxDecorationData.hasAppearance && borderObscuresBackground() && backgroundHasOpaqueTopLayer())
- return BackgroundBleedBackgroundOverBorder;
-
- return BackgroundBleedClipBackground;
-}
void RenderBox::paintBoxDecorationBackground(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
- if (!paintInfo.shouldPaintWithinRoot(this))
- return;
-
- LayoutRect paintRect = borderBoxRect();
- paintRect.moveBy(paintOffset);
- paintBoxDecorationBackgroundWithRect(paintInfo, paintOffset, paintRect);
+ BoxPainter(*this).paintBoxDecorationBackground(paintInfo, paintOffset);
}
-void RenderBox::paintBoxDecorationBackgroundWithRect(PaintInfo& paintInfo, const LayoutPoint& paintOffset, const LayoutRect& paintRect)
-{
- RenderStyle* style = this->style();
- BoxDecorationData boxDecorationData(*style);
- BackgroundBleedAvoidance bleedAvoidance = determineBackgroundBleedAvoidance(paintInfo.context, boxDecorationData);
-
- // FIXME: Should eventually give the theme control over whether the box shadow should paint, since controls could have
- // custom shadows of their own.
- if (!boxShadowShouldBeAppliedToBackground(bleedAvoidance))
- paintBoxShadow(paintInfo, paintRect, style, Normal);
-
- GraphicsContextStateSaver stateSaver(*paintInfo.context, false);
- if (bleedAvoidance == BackgroundBleedClipBackground) {
- stateSaver.save();
- RoundedRect border = style->getRoundedBorderFor(paintRect);
- paintInfo.context->clipRoundedRect(border);
- }
-
- // If we have a native theme appearance, paint that before painting our background.
- // The theme will tell us whether or not we should also paint the CSS background.
- IntRect snappedPaintRect(pixelSnappedIntRect(paintRect));
- bool themePainted = boxDecorationData.hasAppearance && !RenderTheme::theme().paint(this, paintInfo, snappedPaintRect);
- if (!themePainted) {
- if (bleedAvoidance == BackgroundBleedBackgroundOverBorder)
- paintBorder(paintInfo, paintRect, style, bleedAvoidance);
-
- paintBackground(paintInfo, paintRect, boxDecorationData.backgroundColor, bleedAvoidance);
-
- if (boxDecorationData.hasAppearance)
- RenderTheme::theme().paintDecorations(this, paintInfo, snappedPaintRect);
- }
- paintBoxShadow(paintInfo, paintRect, style, Inset);
-
- // The theme will tell us whether or not we should also paint the CSS border.
- if (boxDecorationData.hasBorder && bleedAvoidance != BackgroundBleedBackgroundOverBorder && (!boxDecorationData.hasAppearance || (!themePainted && RenderTheme::theme().paintBorderOnly(this, paintInfo, snappedPaintRect))) && !(isTable() && toRenderTable(this)->collapseBorders()))
- paintBorder(paintInfo, paintRect, style, bleedAvoidance);
-}
-
-void RenderBox::paintBackground(const PaintInfo& paintInfo, const LayoutRect& paintRect, const Color& backgroundColor, BackgroundBleedAvoidance bleedAvoidance)
-{
- if (isDocumentElement()) {
- paintRootBoxFillLayers(paintInfo);
- return;
- }
- if (isBody() && skipBodyBackground(this))
- return;
- if (boxDecorationBackgroundIsKnownToBeObscured())
- return;
- paintFillLayers(paintInfo, backgroundColor, style()->backgroundLayers(), paintRect, bleedAvoidance);
-}
bool RenderBox::getBackgroundPaintedExtent(LayoutRect& paintedExtent) const
{
@@ -1356,122 +1249,12 @@ bool RenderBox::backgroundHasOpaqueTopLayer() const
void RenderBox::paintMask(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
- if (!paintInfo.shouldPaintWithinRoot(this) || style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseMask)
- return;
-
- LayoutRect paintRect = LayoutRect(paintOffset, size());
- paintMaskImages(paintInfo, paintRect);
+ BoxPainter(*this).paintMask(paintInfo, paintOffset);
}
void RenderBox::paintClippingMask(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
- if (!paintInfo.shouldPaintWithinRoot(this) || style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseClippingMask)
- return;
-
- if (!layer() || layer()->compositingState() != PaintsIntoOwnBacking)
- return;
-
- // We should never have this state in this function. A layer with a mask
- // should have always created its own backing if it became composited.
- ASSERT(layer()->compositingState() != HasOwnBackingButPaintsIntoAncestor);
-
- LayoutRect paintRect = LayoutRect(paintOffset, size());
- paintInfo.context->fillRect(pixelSnappedIntRect(paintRect), Color::black);
-}
-
-void RenderBox::paintMaskImages(const PaintInfo& paintInfo, const LayoutRect& paintRect)
-{
- // Figure out if we need to push a transparency layer to render our mask.
- bool pushTransparencyLayer = false;
- bool compositedMask = hasLayer() && layer()->hasCompositedMask();
- bool flattenCompositingLayers = view()->frameView() && view()->frameView()->paintBehavior() & PaintBehaviorFlattenCompositingLayers;
- CompositeOperator compositeOp = CompositeSourceOver;
-
- bool allMaskImagesLoaded = true;
-
- if (!compositedMask || flattenCompositingLayers) {
- pushTransparencyLayer = true;
- StyleImage* maskBoxImage = style()->maskBoxImage().image();
- const FillLayer& maskLayers = style()->maskLayers();
-
- // Don't render a masked element until all the mask images have loaded, to prevent a flash of unmasked content.
- if (maskBoxImage)
- allMaskImagesLoaded &= maskBoxImage->isLoaded();
-
- allMaskImagesLoaded &= maskLayers.imagesAreLoaded();
-
- paintInfo.context->setCompositeOperation(CompositeDestinationIn);
- paintInfo.context->beginTransparencyLayer(1);
- compositeOp = CompositeSourceOver;
- }
-
- if (allMaskImagesLoaded) {
- paintFillLayers(paintInfo, Color::transparent, style()->maskLayers(), paintRect, BackgroundBleedNone, compositeOp);
- paintNinePieceImage(paintInfo.context, paintRect, style(), style()->maskBoxImage(), compositeOp);
- }
-
- if (pushTransparencyLayer)
- paintInfo.context->endLayer();
-}
-
-void RenderBox::paintFillLayers(const PaintInfo& paintInfo, const Color& c, const FillLayer& fillLayer, const LayoutRect& rect,
- BackgroundBleedAvoidance bleedAvoidance, CompositeOperator op, RenderObject* backgroundObject)
-{
- Vector<const FillLayer*, 8> layers;
- const FillLayer* curLayer = &fillLayer;
- bool shouldDrawBackgroundInSeparateBuffer = false;
- bool isBottomLayerOccluded = false;
- while (curLayer) {
- layers.append(curLayer);
- // Stop traversal when an opaque layer is encountered.
- // FIXME : It would be possible for the following occlusion culling test to be more aggressive
- // on layers with no repeat by testing whether the image covers the layout rect.
- // Testing that here would imply duplicating a lot of calculations that are currently done in
- // RenderBoxModelObject::paintFillLayerExtended. A more efficient solution might be to move
- // the layer recursion into paintFillLayerExtended, or to compute the layer geometry here
- // and pass it down.
-
- if (!shouldDrawBackgroundInSeparateBuffer && curLayer->blendMode() != WebBlendModeNormal)
- shouldDrawBackgroundInSeparateBuffer = true;
-
- // The clipOccludesNextLayers condition must be evaluated first to avoid short-circuiting.
- if (curLayer->clipOccludesNextLayers(curLayer == &fillLayer) && curLayer->hasOpaqueImage(this) && curLayer->image()->canRender(*this, style()->effectiveZoom()) && curLayer->hasRepeatXY() && curLayer->blendMode() == WebBlendModeNormal && !boxShadowShouldBeAppliedToBackground(bleedAvoidance))
- break;
- curLayer = curLayer->next();
- }
-
- if (layers.size() > 0 && (**layers.rbegin()).next())
- isBottomLayerOccluded = true;
-
- GraphicsContext* context = paintInfo.context;
- if (!context)
- shouldDrawBackgroundInSeparateBuffer = false;
-
- bool skipBaseColor = false;
- if (shouldDrawBackgroundInSeparateBuffer) {
- bool isBaseColorVisible = !isBottomLayerOccluded && c.hasAlpha();
-
- // Paint the document's base background color outside the transparency layer,
- // so that the background images don't blend with this color: http://crbug.com/389039.
- if (isBaseColorVisible && isDocumentElementWithOpaqueBackground()) {
- paintRootBackgroundColor(paintInfo, rect, Color());
- skipBaseColor = true;
- }
- context->beginTransparencyLayer(1);
- }
-
- Vector<const FillLayer*>::const_reverse_iterator topLayer = layers.rend();
- for (Vector<const FillLayer*>::const_reverse_iterator it = layers.rbegin(); it != topLayer; ++it)
- paintFillLayer(paintInfo, c, **it, rect, bleedAvoidance, op, backgroundObject, skipBaseColor);
-
- if (shouldDrawBackgroundInSeparateBuffer)
- context->endLayer();
-}
-
-void RenderBox::paintFillLayer(const PaintInfo& paintInfo, const Color& c, const FillLayer& fillLayer, const LayoutRect& rect,
- BackgroundBleedAvoidance bleedAvoidance, CompositeOperator op, RenderObject* backgroundObject, bool skipBaseColor)
-{
- paintFillLayerExtended(paintInfo, c, fillLayer, rect, bleedAvoidance, 0, LayoutSize(), op, backgroundObject, skipBaseColor);
+ BoxPainter(*this).paintClippingMask(paintInfo, paintOffset);
}
void RenderBox::imageChanged(WrappedImagePtr image, const IntRect*)
@@ -4743,13 +4526,4 @@ LayoutSize RenderBox::computePreviousBorderBoxSize(const LayoutSize& previousBou
return previousBoundsSize;
}
-RenderBox::BoxDecorationData::BoxDecorationData(const RenderStyle& style)
-{
- backgroundColor = style.visitedDependentColor(CSSPropertyBackgroundColor);
- hasBackground = backgroundColor.alpha() || style.hasBackgroundImage();
- ASSERT(hasBackground == style.hasBackground());
- hasBorder = style.hasBorder();
- hasAppearance = style.hasAppearance();
-}
-
} // namespace blink
« no previous file with comments | « Source/core/rendering/RenderBox.h ('k') | Source/core/rendering/RenderBoxModelObject.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698