Changeset 91628 in webkit


Ignore:
Timestamp:
Jul 22, 2011 5:39:54 PM (13 years ago)
Author:
Simon Fraser
Message:

2011-07-22 Simon Fraser <Simon Fraser>

Avoiding painting backgrounds if they are fully obscures by an object's foreground
https://bugs.webkit.org/show_bug.cgi?id=65030

Reviewed by Dan Bernstein.

Some pages use animated loading GIFs as the background of <img>,
but WebKit keeps animating these after the <img> has loaded.

Thwart this by avoiding the painting of such backgrounds, if we can
determine that they are completely obscured by the border and content
of the element.

  • platform/graphics/BitmapImage.h: (WebCore::BitmapImage::currentFrameHasAlpha): Utility method, since currentFrame() is protected.
  • rendering/RenderBox.cpp: (WebCore::RenderBox::paintBoxDecorations): Call paintBackground(). (WebCore::RenderBox::paintBackground): New wrapper for the paintFillLayers() which paints the background layers, plus some code we call in a couple of places. This checks the new backgroundIsObscured() method before doing any painting.
  • rendering/RenderBox.h: (WebCore::RenderBox::backgroundIsObscured): New virtual method that determines whether any of the background is visible.
  • rendering/RenderBoxModelObject.h:
  • rendering/RenderBoxModelObject.cpp: (WebCore::BorderEdge::obscuresBackground): Returns true if this edge will entirely hide the background under it. (WebCore::RenderBoxModelObject::borderObscuresBackground): Determine whether the border hides the background.
  • rendering/RenderImage.cpp: (WebCore::RenderImage::backgroundIsObscured): Override the RenderBox method and return true if the image is a loaded, opaque bitmap image, and the background won't show in the border or padding areas.
  • rendering/RenderImage.h:
  • rendering/RenderTable.cpp: (WebCore::RenderTable::paintBoxDecorations): Use paintBackground().
Location:
trunk/Source/WebCore
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r91626 r91628  
     12011-07-22  Simon Fraser  <simon.fraser@apple.com>
     2
     3        Avoiding painting backgrounds if they are fully obscures by an object's foreground
     4        https://bugs.webkit.org/show_bug.cgi?id=65030
     5
     6        Reviewed by Dan Bernstein.
     7
     8        Some pages use animated loading GIFs as the background of <img>,
     9        but WebKit keeps animating these after the <img> has loaded.
     10       
     11        Thwart this by avoiding the painting of such backgrounds, if we can
     12        determine that they are completely obscured by the border and content
     13        of the element.
     14
     15        * platform/graphics/BitmapImage.h:
     16        (WebCore::BitmapImage::currentFrameHasAlpha): Utility method, since currentFrame()
     17        is protected.
     18        * rendering/RenderBox.cpp:
     19        (WebCore::RenderBox::paintBoxDecorations): Call paintBackground().
     20        (WebCore::RenderBox::paintBackground): New wrapper for the paintFillLayers() which
     21        paints the background layers, plus some code we call in a couple of places. This
     22        checks the new backgroundIsObscured() method before doing any painting.
     23        * rendering/RenderBox.h:
     24        (WebCore::RenderBox::backgroundIsObscured): New virtual method that determines
     25        whether any of the background is visible.
     26        * rendering/RenderBoxModelObject.h:
     27        * rendering/RenderBoxModelObject.cpp:
     28        (WebCore::BorderEdge::obscuresBackground): Returns true if this edge will
     29        entirely hide the background under it.
     30        (WebCore::RenderBoxModelObject::borderObscuresBackground): Determine whether
     31        the border hides the background.
     32        * rendering/RenderImage.cpp:
     33        (WebCore::RenderImage::backgroundIsObscured): Override the RenderBox method
     34        and return true if the image is a loaded, opaque bitmap image, and the background
     35        won't show in the border or padding areas.
     36        * rendering/RenderImage.h:
     37        * rendering/RenderTable.cpp:
     38        (WebCore::RenderTable::paintBoxDecorations): Use paintBackground().
     39
    1402011-07-22  Kenneth Russell  <kbr@google.com>
    241
  • trunk/Source/WebCore/platform/graphics/BitmapImage.h

    r85697 r91628  
    159159
    160160    virtual NativeImagePtr nativeImageForCurrentFrame() { return frameAtIndex(currentFrame()); }
    161     bool frameHasAlphaAtIndex(size_t);
     161    bool frameHasAlphaAtIndex(size_t);
     162    bool currentFrameHasAlpha() { return frameHasAlphaAtIndex(currentFrame()); }
    162163
    163164#if !ASSERT_DISABLED
  • trunk/Source/WebCore/rendering/RenderBox.cpp

    r91533 r91628  
    863863    bool themePainted = style()->hasAppearance() && !theme()->paint(this, paintInfo, paintRect);
    864864    if (!themePainted) {
    865         if (isRoot())
    866             paintRootBoxFillLayers(paintInfo);
    867         else if (!isBody() || document()->documentElement()->renderer()->hasBackground()) {
    868             // The <body> only paints its background if the root element has defined a background
    869             // independent of the body.
    870             paintFillLayers(paintInfo, style()->visitedDependentColor(CSSPropertyBackgroundColor), style()->backgroundLayers(), paintRect, bleedAvoidance);
    871         }
     865        paintBackground(paintInfo, paintRect, bleedAvoidance);
     866
    872867        if (style()->hasAppearance())
    873868            theme()->paintDecorations(this, paintInfo, paintRect);
     
    881876    if (bleedAvoidance == BackgroundBleedUseTransparencyLayer)
    882877        paintInfo.context->endTransparencyLayer();
     878}
     879
     880void RenderBox::paintBackground(const PaintInfo& paintInfo, const LayoutRect& paintRect, BackgroundBleedAvoidance bleedAvoidance)
     881{
     882    if (isRoot())
     883        paintRootBoxFillLayers(paintInfo);
     884    else if (!isBody() || document()->documentElement()->renderer()->hasBackground()) {
     885        // The <body> only paints its background if the root element has defined a background
     886        // independent of the body.
     887        if (!backgroundIsObscured())
     888            paintFillLayers(paintInfo, style()->visitedDependentColor(CSSPropertyBackgroundColor), style()->backgroundLayers(), paintRect, bleedAvoidance);
     889    }
    883890}
    884891
  • trunk/Source/WebCore/rendering/RenderBox.h

    r91386 r91628  
    418418    virtual void updateBoxModelInfoFromStyle();
    419419
     420    virtual bool backgroundIsObscured() const { return false; }
     421    void paintBackground(const PaintInfo&, const LayoutRect&, BackgroundBleedAvoidance = BackgroundBleedNone);
     422   
    420423    void paintFillLayer(const PaintInfo&, const Color&, const FillLayer*, const LayoutRect&, BackgroundBleedAvoidance, CompositeOperator, RenderObject* backgroundObject);
    421424    void paintFillLayers(const PaintInfo&, const Color&, const FillLayer*, const LayoutRect&, BackgroundBleedAvoidance = BackgroundBleedNone, CompositeOperator = CompositeSourceOver, RenderObject* backgroundObject = 0);
  • trunk/Source/WebCore/rendering/RenderBoxModelObject.cpp

    r91190 r91628  
    10961096        return true;
    10971097    }
     1098    bool obscuresBackground() const
     1099    {
     1100        if (!isPresent || isTransparent || color.hasAlpha() || style == BHIDDEN)
     1101            return false;
     1102
     1103        if (style == DOTTED || style == DASHED || style == DOUBLE)
     1104            return false;
     1105
     1106        return true;
     1107    }
    10981108
    10991109    int usedWidth() const { return isPresent ? width : 0; }
     
    21462156}
    21472157
     2158bool RenderBoxModelObject::borderObscuresBackground() const
     2159{
     2160    if (!style()->hasBorder())
     2161        return false;
     2162
     2163    // Bail if we have any border-image for now. We could look at the image alpha to improve this.
     2164    if (style()->borderImage().image())
     2165        return false;
     2166
     2167    BorderEdge edges[4];
     2168    getBorderEdgeInfo(edges);
     2169
     2170    for (int i = BSTop; i <= BSLeft; ++i) {
     2171        const BorderEdge& currEdge = edges[i];
     2172        if (!currEdge.obscuresBackground())
     2173            return false;
     2174    }
     2175
     2176    return true;
     2177}
     2178
    21482179static inline IntRect areaCastingShadowInHole(const IntRect& holeRect, int shadowBlur, int shadowSpread, const IntSize& shadowOffset)
    21492180{
  • trunk/Source/WebCore/rendering/RenderBoxModelObject.h

    r91090 r91628  
    184184    void getBorderEdgeInfo(class BorderEdge[], bool includeLogicalLeftEdge = true, bool includeLogicalRightEdge = true) const;
    185185    bool borderObscuresBackgroundEdge(const FloatSize& contextScale) const;
     186    bool borderObscuresBackground() const;
    186187
    187188    bool shouldPaintAtLowQuality(GraphicsContext*, Image*, const void*, const IntSize&);
  • trunk/Source/WebCore/rendering/RenderImage.cpp

    r90900 r91628  
    2828#include "RenderImage.h"
    2929
     30#include "BitmapImage.h"
    3031#include "FontCache.h"
    3132#include "Frame.h"
     
    388389}
    389390
     391bool RenderImage::backgroundIsObscured() const
     392{
     393    if (!m_imageResource->hasImage() || m_imageResource->errorOccurred())
     394        return false;
     395
     396    if (m_imageResource->cachedImage() && !m_imageResource->cachedImage()->isLoaded())
     397        return false;
     398
     399    EFillBox backgroundClip = style()->backgroundClip();
     400
     401    // Background paints under borders.
     402    if (backgroundClip == BorderFillBox && style()->hasBorder() && !borderObscuresBackground())
     403        return false;
     404
     405    // Background shows in padding area.
     406    if ((backgroundClip == BorderFillBox || backgroundClip == PaddingFillBox) && style()->hasPadding())
     407        return false;
     408
     409    // Check for bitmap image with alpha.
     410    Image* image = m_imageResource->image().get();
     411    if (!image || !image->isBitmapImage())
     412        return false;
     413       
     414    BitmapImage* bitmapImage = static_cast<BitmapImage*>(image);
     415    if (bitmapImage->currentFrameHasAlpha())
     416        return false;
     417
     418    return true;
     419}
     420
    390421int RenderImage::minimumReplacedHeight() const
    391422{
  • trunk/Source/WebCore/rendering/RenderImage.h

    r90900 r91628  
    7979    virtual void paintReplaced(PaintInfo&, const IntPoint&);
    8080
     81    virtual bool backgroundIsObscured() const;
     82
    8183    virtual int minimumReplacedHeight() const;
    8284
  • trunk/Source/WebCore/rendering/RenderTable.cpp

    r91417 r91628  
    559559
    560560    paintBoxShadow(paintInfo.context, rect, style(), Normal);
    561    
    562     if (isRoot())
    563         paintRootBoxFillLayers(paintInfo);
    564     else if (!isBody() || document()->documentElement()->renderer()->hasBackground())
    565         // The <body> only paints its background if the root element has defined a background
    566         // independent of the body.
    567         paintFillLayers(paintInfo, style()->visitedDependentColor(CSSPropertyBackgroundColor), style()->backgroundLayers(), rect);
    568 
     561    paintBackground(paintInfo, rect);
    569562    paintBoxShadow(paintInfo.context, rect, style(), Inset);
    570563
Note: See TracChangeset for help on using the changeset viewer.