Diff
Modified: trunk/Source/WebCore/ChangeLog (107835 => 107836)
--- trunk/Source/WebCore/ChangeLog 2012-02-15 21:02:37 UTC (rev 107835)
+++ trunk/Source/WebCore/ChangeLog 2012-02-15 21:57:02 UTC (rev 107836)
@@ -1,3 +1,41 @@
+2012-02-15 Dan Bernstein <[email protected]>
+
+ <rdar://problem/10870238> Box shadow drawing takes an unnecessarily slow code path in some single-shadow, opaque-background cases
+ https://bugs.webkit.org/show_bug.cgi?id=78728
+
+ In some cases, when there is only one normal box shadow, and the box has an opaque background,
+ it is possible to draw the box shadow by having the background cast it directly. This appears
+ to be faster than the generic code path that uses a separate drawing pass to cast the shadow,
+ clipping out the border box and the shadow-casting box.
+
+ Reviewed by Dave Hyatt.
+
+ No new tests, because behavior is unchanged.
+
+ * rendering/InlineFlowBox.cpp:
+ (WebCore::InlineFlowBox::paintBoxDecorations): Changed to not paint normal box shadows if
+ they are going to be cast by the background.
+ * rendering/RenderBox.cpp:
+ (WebCore::RenderBox::paintBoxDecorations): Ditto.
+ * rendering/RenderBox.h: Made determineBackgroundBleedAvoidance() protected.
+ * rendering/RenderBoxModelObject.cpp:
+ (WebCore::applyBoxShadowForBackground): Added this helper function, which applies the first
+ normal shadow from the given RenderStyle to the given GraphicsContext.
+ (WebCore::RenderBoxModelObject::paintFillLayerExtended): Added calls to
+ applyBoxShadowForBackground() before drawing the background color when needed.
+ (WebCore::RenderBoxModelObject::boxShadowShouldBeAppliedToBackground): Added. Returns true
+ in some of the cases where the box shadow can be cast by the background directly.
+ * rendering/RenderBoxModelObject.h:
+ * rendering/RenderFieldset.cpp:
+ (WebCore::RenderFieldset::paintBoxDecorations): Changed to not paint normal box shadows if
+ they are going to be cast by the background.
+ * rendering/RenderTable.cpp:
+ (WebCore::RenderTable::paintBoxDecorations): Ditto.
+ * rendering/RenderTableCell.cpp:
+ (WebCore::RenderTableCell::boxShadowShouldBeAppliedToBackground): Added this override that
+ always returns false, because table cells sometimes apply a clip before drawing the background.
+ * rendering/RenderTableCell.h:
+
2012-02-15 Ojan Vafai <[email protected]>
getComputedStyle of flex-item-align:auto should resolve to it's parent's flex-align value
Modified: trunk/Source/WebCore/rendering/InlineFlowBox.cpp (107835 => 107836)
--- trunk/Source/WebCore/rendering/InlineFlowBox.cpp 2012-02-15 21:02:37 UTC (rev 107835)
+++ trunk/Source/WebCore/rendering/InlineFlowBox.cpp 2012-02-15 21:57:02 UTC (rev 107836)
@@ -1203,7 +1203,8 @@
if ((!parent() && m_firstLine && styleToUse != renderer()->style()) || (parent() && renderer()->hasBoxDecorations())) {
LayoutRect paintRect = LayoutRect(adjustedPaintoffset, frameRect.size());
// Shadow comes first and is behind the background and border.
- paintBoxShadow(paintInfo, styleToUse, Normal, paintRect);
+ if (!boxModelObject()->boxShadowShouldBeAppliedToBackground(BackgroundBleedNone))
+ paintBoxShadow(paintInfo, styleToUse, Normal, paintRect);
Color c = styleToUse->visitedDependentColor(CSSPropertyBackgroundColor);
paintFillLayers(paintInfo, c, styleToUse->backgroundLayers(), paintRect);
Modified: trunk/Source/WebCore/rendering/RenderBox.cpp (107835 => 107836)
--- trunk/Source/WebCore/rendering/RenderBox.cpp 2012-02-15 21:02:37 UTC (rev 107835)
+++ trunk/Source/WebCore/rendering/RenderBox.cpp 2012-02-15 21:57:02 UTC (rev 107836)
@@ -917,12 +917,13 @@
// balloon layout is an example of this).
borderFitAdjust(paintRect);
+ BackgroundBleedAvoidance bleedAvoidance = determineBackgroundBleedAvoidance(paintInfo.context);
+
// FIXME: Should eventually give the theme control over whether the box shadow should paint, since controls could have
// custom shadows of their own.
- paintBoxShadow(paintInfo, paintRect, style(), Normal);
+ if (!boxShadowShouldBeAppliedToBackground(bleedAvoidance))
+ paintBoxShadow(paintInfo, paintRect, style(), Normal);
- BackgroundBleedAvoidance bleedAvoidance = determineBackgroundBleedAvoidance(paintInfo.context);
-
GraphicsContextStateSaver stateSaver(*paintInfo.context, false);
if (bleedAvoidance == BackgroundBleedUseTransparencyLayer) {
// To avoid the background color bleeding out behind the border, we'll render background and border
Modified: trunk/Source/WebCore/rendering/RenderBox.h (107835 => 107836)
--- trunk/Source/WebCore/rendering/RenderBox.h 2012-02-15 21:02:37 UTC (rev 107835)
+++ trunk/Source/WebCore/rendering/RenderBox.h 2012-02-15 21:57:02 UTC (rev 107836)
@@ -460,6 +460,8 @@
void paintMaskImages(const PaintInfo&, const LayoutRect&);
+ BackgroundBleedAvoidance determineBackgroundBleedAvoidance(GraphicsContext*) const;
+
#if PLATFORM(MAC)
void paintCustomHighlight(const LayoutPoint&, const AtomicString& type, bool behindText);
#endif
@@ -504,8 +506,6 @@
// These include tables, positioned objects, floats and flexible boxes.
virtual void computePreferredLogicalWidths() { setPreferredLogicalWidthsDirty(false); }
- BackgroundBleedAvoidance determineBackgroundBleedAvoidance(GraphicsContext*) const;
-
private:
// The width/height of the contents + borders + padding. The x/y location is relative to our container (which is not always our parent).
LayoutRect m_frameRect;
Modified: trunk/Source/WebCore/rendering/RenderBoxModelObject.cpp (107835 => 107836)
--- trunk/Source/WebCore/rendering/RenderBoxModelObject.cpp 2012-02-15 21:02:37 UTC (rev 107835)
+++ trunk/Source/WebCore/rendering/RenderBoxModelObject.cpp 2012-02-15 21:57:02 UTC (rev 107836)
@@ -619,6 +619,19 @@
return adjustedRect;
}
+static void applyBoxShadowForBackground(GraphicsContext* context, RenderStyle* style)
+{
+ const ShadowData* boxShadow = style->boxShadow();
+ while (boxShadow->style() != Normal)
+ boxShadow = boxShadow->next();
+
+ FloatSize shadowOffset(boxShadow->x(), boxShadow->y());
+ if (!boxShadow->isWebkitBoxShadow())
+ context->setShadow(shadowOffset, boxShadow->blur(), boxShadow->color(), style->colorSpace());
+ else
+ context->setLegacyShadow(shadowOffset, boxShadow->blur(), boxShadow->color(), style->colorSpace());
+}
+
void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, const Color& color, const FillLayer* bgLayer, const LayoutRect& rect,
BackgroundBleedAvoidance bleedAvoidance, InlineFlowBox* box, const LayoutSize& boxSize, CompositeOperator op, RenderObject* backgroundObject)
{
@@ -669,6 +682,11 @@
if (!colorVisible)
return;
+ bool boxShadowShouldBeAppliedToBackground = this->boxShadowShouldBeAppliedToBackground(bleedAvoidance);
+ GraphicsContextStateSaver shadowStateSaver(*context, boxShadowShouldBeAppliedToBackground);
+ if (boxShadowShouldBeAppliedToBackground)
+ applyBoxShadowForBackground(context, style());
+
if (hasRoundedBorder && bleedAvoidance != BackgroundBleedUseTransparencyLayer) {
RoundedRect border = getBackgroundRoundedRect(backgroundRectAdjustedForBleedAvoidance(context, rect, bleedAvoidance), box, boxSize.width(), boxSize.height(), includeLeftEdge, includeRightEdge);
context->fillRoundedRect(border, bgColor, style()->colorSpace());
@@ -778,7 +796,10 @@
// Paint the color first underneath all images.
if (!bgLayer->next()) {
IntRect backgroundRect(pixelSnappedIntRect(scrolledPaintRect));
- backgroundRect.intersect(paintInfo.rect);
+ bool boxShadowShouldBeAppliedToBackground = this->boxShadowShouldBeAppliedToBackground(bleedAvoidance);
+ if (!boxShadowShouldBeAppliedToBackground)
+ backgroundRect.intersect(paintInfo.rect);
+
// If we have an alpha and we are painting the root element, go ahead and blend with the base background color.
Color baseColor;
bool shouldClearBackground = false;
@@ -788,6 +809,10 @@
shouldClearBackground = true;
}
+ GraphicsContextStateSaver shadowStateSaver(*context, boxShadowShouldBeAppliedToBackground);
+ if (boxShadowShouldBeAppliedToBackground)
+ applyBoxShadowForBackground(context, style());
+
if (baseColor.alpha()) {
if (bgColor.alpha())
baseColor = baseColor.blend(bgColor);
@@ -2556,6 +2581,44 @@
return true;
}
+bool RenderBoxModelObject::boxShadowShouldBeAppliedToBackground(BackgroundBleedAvoidance bleedAvoidance) const
+{
+ if (bleedAvoidance != BackgroundBleedNone)
+ return false;
+
+ if (style()->hasAppearance())
+ return false;
+
+ const ShadowData* boxShadow = style()->boxShadow();
+ bool hasOneNormalBoxShadow = false;
+ for (const ShadowData* currentShadow = boxShadow; currentShadow; currentShadow = currentShadow->next()) {
+ if (currentShadow->style() != Normal)
+ continue;
+ if (hasOneNormalBoxShadow)
+ return false;
+ hasOneNormalBoxShadow = true;
+ }
+
+ if (!hasOneNormalBoxShadow)
+ return false;
+
+ Color backgroundColor = style()->visitedDependentColor(CSSPropertyBackgroundColor);
+ if (!backgroundColor.isValid() || backgroundColor.alpha() < 255)
+ return false;
+
+ const FillLayer* lastBackgroundLayer = style()->backgroundLayers();
+ for (const FillLayer* next = lastBackgroundLayer->next(); next; )
+ lastBackgroundLayer = next;
+
+ if (lastBackgroundLayer->clip() != BorderFillBox)
+ return false;
+
+ if (hasOverflowClip() && lastBackgroundLayer->attachment() == LocalBackgroundAttachment)
+ return false;
+
+ return true;
+}
+
static inline LayoutRect areaCastingShadowInHole(const LayoutRect& holeRect, int shadowBlur, int shadowSpread, const LayoutSize& shadowOffset)
{
LayoutRect bounds(holeRect);
Modified: trunk/Source/WebCore/rendering/RenderBoxModelObject.h (107835 => 107836)
--- trunk/Source/WebCore/rendering/RenderBoxModelObject.h 2012-02-15 21:02:37 UTC (rev 107835)
+++ trunk/Source/WebCore/rendering/RenderBoxModelObject.h 2012-02-15 21:57:02 UTC (rev 107836)
@@ -127,6 +127,8 @@
void paintBoxShadow(const PaintInfo&, const LayoutRect&, const RenderStyle*, ShadowStyle, bool includeLogicalLeftEdge = true, bool includeLogicalRightEdge = true);
void paintFillLayerExtended(const PaintInfo&, const Color&, const FillLayer*, const LayoutRect&, BackgroundBleedAvoidance, InlineFlowBox* = 0, const LayoutSize& = LayoutSize(), CompositeOperator = CompositeSourceOver, RenderObject* backgroundObject = 0);
+ virtual bool boxShadowShouldBeAppliedToBackground(BackgroundBleedAvoidance) const;
+
// Overridden by subclasses to determine line height and baseline position.
virtual LayoutUnit lineHeight(bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const = 0;
virtual LayoutUnit baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const = 0;
Modified: trunk/Source/WebCore/rendering/RenderFieldset.cpp (107835 => 107836)
--- trunk/Source/WebCore/rendering/RenderFieldset.cpp 2012-02-15 21:02:37 UTC (rev 107835)
+++ trunk/Source/WebCore/rendering/RenderFieldset.cpp 2012-02-15 21:57:02 UTC (rev 107836)
@@ -140,8 +140,9 @@
paintRect.setWidth(paintRect.width() - xOff);
paintRect.setX(paintRect.x() + xOff);
}
-
- paintBoxShadow(paintInfo, paintRect, style(), Normal);
+
+ if (!boxShadowShouldBeAppliedToBackground(determineBackgroundBleedAvoidance(paintInfo.context)))
+ paintBoxShadow(paintInfo, paintRect, style(), Normal);
paintFillLayers(paintInfo, style()->visitedDependentColor(CSSPropertyBackgroundColor), style()->backgroundLayers(), paintRect);
paintBoxShadow(paintInfo, paintRect, style(), Inset);
Modified: trunk/Source/WebCore/rendering/RenderTable.cpp (107835 => 107836)
--- trunk/Source/WebCore/rendering/RenderTable.cpp 2012-02-15 21:02:37 UTC (rev 107835)
+++ trunk/Source/WebCore/rendering/RenderTable.cpp 2012-02-15 21:57:02 UTC (rev 107836)
@@ -617,7 +617,8 @@
LayoutRect rect(paintOffset, size());
subtractCaptionRect(rect);
- paintBoxShadow(paintInfo, rect, style(), Normal);
+ if (!boxShadowShouldBeAppliedToBackground(determineBackgroundBleedAvoidance(paintInfo.context)))
+ paintBoxShadow(paintInfo, rect, style(), Normal);
paintBackground(paintInfo, rect);
paintBoxShadow(paintInfo, rect, style(), Inset);
Modified: trunk/Source/WebCore/rendering/RenderTableCell.cpp (107835 => 107836)
--- trunk/Source/WebCore/rendering/RenderTableCell.cpp 2012-02-15 21:02:37 UTC (rev 107835)
+++ trunk/Source/WebCore/rendering/RenderTableCell.cpp 2012-02-15 21:57:02 UTC (rev 107836)
@@ -1068,6 +1068,11 @@
paintMaskImages(paintInfo, LayoutRect(paintOffset, size()));
}
+bool RenderTableCell::boxShadowShouldBeAppliedToBackground(BackgroundBleedAvoidance) const
+{
+ return false;
+}
+
void RenderTableCell::scrollbarsChanged(bool horizontalScrollbarChanged, bool verticalScrollbarChanged)
{
LayoutUnit scrollbarHeight = scrollbarLogicalHeight();
Modified: trunk/Source/WebCore/rendering/RenderTableCell.h (107835 => 107836)
--- trunk/Source/WebCore/rendering/RenderTableCell.h 2012-02-15 21:02:37 UTC (rev 107835)
+++ trunk/Source/WebCore/rendering/RenderTableCell.h 2012-02-15 21:57:02 UTC (rev 107836)
@@ -151,6 +151,8 @@
virtual void paintBoxDecorations(PaintInfo&, const LayoutPoint&);
virtual void paintMask(PaintInfo&, const LayoutPoint&);
+ virtual bool boxShadowShouldBeAppliedToBackground(BackgroundBleedAvoidance) const OVERRIDE;
+
virtual LayoutSize offsetFromContainer(RenderObject*, const LayoutPoint&) const;
virtual LayoutRect clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer) const;
virtual void computeRectForRepaint(RenderBoxModelObject* repaintContainer, LayoutRect&, bool fixed = false) const;