Title: [139701] trunk/Source/WebCore
Revision
139701
Author
[email protected]
Date
2013-01-14 18:44:55 -0800 (Mon, 14 Jan 2013)

Log Message

Blur the label background of a snapshotted plugin
https://bugs.webkit.org/show_bug.cgi?id=106630

Reviewed by Simon Fraser.

When we are showing a label indicating the plugin has been snapshotted,
slightly blur the snapshot behind the label so that it is more clear. I expect
that if/when other ports pick up this code, we'll need to separate the
UI treatment somewhat, but this is ok for a first step.

* rendering/RenderSnapshottedPlugIn.cpp:
(RenderSnapshottedPlugInBlurFilter): Private class to use FEGaussianBlur to blur an image.
(WebCore::RenderSnapshottedPlugInBlurFilter::create):
(WebCore::RenderSnapshottedPlugInBlurFilter::setSourceImageRect):
(WebCore::RenderSnapshottedPlugInBlurFilter::sourceImageRect):
(WebCore::RenderSnapshottedPlugInBlurFilter::filterRegion):
(WebCore::RenderSnapshottedPlugInBlurFilter::output):
(WebCore::RenderSnapshottedPlugInBlurFilter::RenderSnapshottedPlugInBlurFilter):
(WebCore::RenderSnapshottedPlugInBlurFilter::apply):
(WebCore::RenderSnapshottedPlugIn::RenderSnapshottedPlugIn): New member variable to hold a cached version of a preblurred snapshot.
(WebCore::RenderSnapshottedPlugIn::~RenderSnapshottedPlugIn): Remember to remove the preblurred image from the cache.
(WebCore::RenderSnapshottedPlugIn::updateSnapshot): Zero the preblurred version if it exists.
(WebCore::RenderSnapshottedPlugIn::paintReplaced): Either paint snapshot or blurred snapshot with label.
(WebCore::RenderSnapshottedPlugIn::paintSnapshot): New method to paint a full sized snapshot.
(WebCore::RenderSnapshottedPlugIn::paintReplacedSnapshot):
(WebCore::snapshottedPluginImageForLabelDisplay): Static function to produce the blurred snapshot.
(WebCore::RenderSnapshottedPlugIn::paintReplacedSnapshotWithLabel): Calls paintSnapshot with the blurred snapshot on Mac.
* rendering/RenderSnapshottedPlugIn.h:

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (139700 => 139701)


--- trunk/Source/WebCore/ChangeLog	2013-01-15 02:08:38 UTC (rev 139700)
+++ trunk/Source/WebCore/ChangeLog	2013-01-15 02:44:55 UTC (rev 139701)
@@ -1,3 +1,34 @@
+2013-01-14  Dean Jackson  <[email protected]>
+
+        Blur the label background of a snapshotted plugin
+        https://bugs.webkit.org/show_bug.cgi?id=106630
+
+        Reviewed by Simon Fraser.
+
+        When we are showing a label indicating the plugin has been snapshotted,
+        slightly blur the snapshot behind the label so that it is more clear. I expect
+        that if/when other ports pick up this code, we'll need to separate the
+        UI treatment somewhat, but this is ok for a first step.
+
+        * rendering/RenderSnapshottedPlugIn.cpp:
+        (RenderSnapshottedPlugInBlurFilter): Private class to use FEGaussianBlur to blur an image.
+        (WebCore::RenderSnapshottedPlugInBlurFilter::create):
+        (WebCore::RenderSnapshottedPlugInBlurFilter::setSourceImageRect):
+        (WebCore::RenderSnapshottedPlugInBlurFilter::sourceImageRect):
+        (WebCore::RenderSnapshottedPlugInBlurFilter::filterRegion):
+        (WebCore::RenderSnapshottedPlugInBlurFilter::output):
+        (WebCore::RenderSnapshottedPlugInBlurFilter::RenderSnapshottedPlugInBlurFilter):
+        (WebCore::RenderSnapshottedPlugInBlurFilter::apply):
+        (WebCore::RenderSnapshottedPlugIn::RenderSnapshottedPlugIn): New member variable to hold a cached version of a preblurred snapshot.
+        (WebCore::RenderSnapshottedPlugIn::~RenderSnapshottedPlugIn): Remember to remove the preblurred image from the cache.
+        (WebCore::RenderSnapshottedPlugIn::updateSnapshot): Zero the preblurred version if it exists.
+        (WebCore::RenderSnapshottedPlugIn::paintReplaced): Either paint snapshot or blurred snapshot with label.
+        (WebCore::RenderSnapshottedPlugIn::paintSnapshot): New method to paint a full sized snapshot.
+        (WebCore::RenderSnapshottedPlugIn::paintReplacedSnapshot):
+        (WebCore::snapshottedPluginImageForLabelDisplay): Static function to produce the blurred snapshot.
+        (WebCore::RenderSnapshottedPlugIn::paintReplacedSnapshotWithLabel): Calls paintSnapshot with the blurred snapshot on Mac.
+        * rendering/RenderSnapshottedPlugIn.h:
+
 2013-01-14  Mark Pilgrim  <[email protected]>
 
         [Chromium] Move BlobRegistryProxy into WebCore

Modified: trunk/Source/WebCore/rendering/RenderSnapshottedPlugIn.cpp (139700 => 139701)


--- trunk/Source/WebCore/rendering/RenderSnapshottedPlugIn.cpp	2013-01-15 02:08:38 UTC (rev 139700)
+++ trunk/Source/WebCore/rendering/RenderSnapshottedPlugIn.cpp	2013-01-15 02:44:55 UTC (rev 139701)
@@ -29,14 +29,18 @@
 #include "Chrome.h"
 #include "ChromeClient.h"
 #include "Cursor.h"
+#include "FEGaussianBlur.h"
+#include "Filter.h"
 #include "FrameLoaderClient.h"
 #include "FrameView.h"
 #include "Gradient.h"
 #include "HTMLPlugInImageElement.h"
+#include "ImageBuffer.h"
 #include "MouseEvent.h"
 #include "Page.h"
 #include "PaintInfo.h"
 #include "Path.h"
+#include "SourceGraphic.h"
 
 namespace WebCore {
 
@@ -46,7 +50,53 @@
 static const int startLabelInset = 20; // But the label is inset from its box also. FIXME: This will be removed when we go to a ShadowDOM approach.
 static const double showLabelAfterMouseOverDelay = 1;
 static const double showLabelAutomaticallyDelay = 3;
+static const int snapshotLabelBlurRadius = 5;
 
+class RenderSnapshottedPlugInBlurFilter : public Filter {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    static PassRefPtr<RenderSnapshottedPlugInBlurFilter> create(int radius)
+    {
+        return adoptRef(new RenderSnapshottedPlugInBlurFilter(radius));
+    }
+
+    void setSourceImageRect(const FloatRect& r)
+    {
+        m_sourceImageRect = r;
+        m_filterRegion = r;
+        m_sourceGraphic->setMaxEffectRect(r);
+        m_blur->setMaxEffectRect(r);
+    }
+    virtual FloatRect sourceImageRect() const { return m_sourceImageRect; }
+    virtual FloatRect filterRegion() const { return m_filterRegion; }
+
+    void apply();
+    ImageBuffer* output() const { return m_blur->asImageBuffer(); }
+
+private:
+    RenderSnapshottedPlugInBlurFilter(int radius);
+
+    FloatRect m_sourceImageRect;
+    FloatRect m_filterRegion;
+    RefPtr<SourceGraphic> m_sourceGraphic;
+    RefPtr<FEGaussianBlur> m_blur;
+};
+
+RenderSnapshottedPlugInBlurFilter::RenderSnapshottedPlugInBlurFilter(int radius)
+{
+    setFilterResolution(FloatSize(1, 1));
+    m_sourceGraphic = SourceGraphic::create(this);
+    m_blur = FEGaussianBlur::create(this, radius, radius);
+    m_blur->inputEffects().append(m_sourceGraphic);
+}
+
+void RenderSnapshottedPlugInBlurFilter::apply()
+{
+    m_sourceGraphic->clearResult();
+    m_blur->clearResult();
+    m_blur->apply();
+}
+
 RenderSnapshottedPlugIn::RenderSnapshottedPlugIn(HTMLPlugInImageElement* element)
     : RenderEmbeddedObject(element)
     , m_snapshotResource(RenderImageResource::create())
@@ -55,14 +105,18 @@
     , m_showedLabelOnce(false)
     , m_showReason(UserMousedOver)
     , m_showLabelDelayTimer(this, &RenderSnapshottedPlugIn::showLabelDelayTimerFired)
+    , m_snapshotResourceForLabel(RenderImageResource::create())
 {
     m_snapshotResource->initialize(this);
+    m_snapshotResourceForLabel->initialize(this);
 }
 
 RenderSnapshottedPlugIn::~RenderSnapshottedPlugIn()
 {
     ASSERT(m_snapshotResource);
     m_snapshotResource->shutdown();
+    ASSERT(m_snapshotResourceForLabel);
+    m_snapshotResourceForLabel->shutdown();
 }
 
 HTMLPlugInImageElement* RenderSnapshottedPlugIn::plugInImageElement() const
@@ -76,6 +130,11 @@
     if (!image)
         return;
 
+    // We may have stored a version of this snapshot to use when showing the
+    // label. Invalidate it now and it will be regenerated later.
+    if (m_snapshotResourceForLabel->hasImage())
+        m_snapshotResourceForLabel->setCachedImage(0);
+
     m_snapshotResource->setCachedImage(new CachedImage(image.get()));
     repaint();
     if (m_shouldShowLabelAutomatically)
@@ -95,27 +154,23 @@
 void RenderSnapshottedPlugIn::paintReplaced(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
 {
     if (plugInImageElement()->displayState() < HTMLPlugInElement::PlayingWithPendingMouseClick) {
-        paintReplacedSnapshot(paintInfo, paintOffset);
         if (m_shouldShowLabel)
-            paintLabel(paintInfo, paintOffset);
+            paintReplacedSnapshotWithLabel(paintInfo, paintOffset);
+        else
+            paintReplacedSnapshot(paintInfo, paintOffset);
         return;
     }
 
     RenderEmbeddedObject::paintReplaced(paintInfo, paintOffset);
 }
 
-void RenderSnapshottedPlugIn::paintReplacedSnapshot(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
+void RenderSnapshottedPlugIn::paintSnapshot(Image* image, PaintInfo& paintInfo, const LayoutPoint& paintOffset)
 {
-    // This code should be similar to RenderImage::paintReplaced() and RenderImage::paintIntoRect().
     LayoutUnit cWidth = contentWidth();
     LayoutUnit cHeight = contentHeight();
     if (!cWidth || !cHeight)
         return;
 
-    RefPtr<Image> image = m_snapshotResource->image();
-    if (!image || image->isNull())
-        return;
-
     GraphicsContext* context = paintInfo.context;
 #if PLATFORM(MAC)
     if (style()->highlight() != nullAtom && !context->paintingDisabled())
@@ -131,10 +186,19 @@
     if (alignedRect.width() <= 0 || alignedRect.height() <= 0)
         return;
 
-    bool useLowQualityScaling = shouldPaintAtLowQuality(context, image.get(), image.get(), alignedRect.size());
-    context->drawImage(image.get(), style()->colorSpace(), alignedRect, CompositeSourceOver, shouldRespectImageOrientation(), useLowQualityScaling);
+    bool useLowQualityScaling = shouldPaintAtLowQuality(context, image, image, alignedRect.size());
+    context->drawImage(image, style()->colorSpace(), alignedRect, CompositeSourceOver, shouldRespectImageOrientation(), useLowQualityScaling);
 }
 
+void RenderSnapshottedPlugIn::paintReplacedSnapshot(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
+{
+    RefPtr<Image> image = m_snapshotResource->image();
+    if (!image || image->isNull())
+        return;
+
+    paintSnapshot(image.get(), paintInfo, paintOffset);
+}
+
 Image* RenderSnapshottedPlugIn::startLabelImage(LabelSize size) const
 {
     static Image* labelImages[2] = { 0, 0 };
@@ -153,8 +217,25 @@
     return labelImages[arrayIndex];
 }
 
-void RenderSnapshottedPlugIn::paintLabel(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
+static PassRefPtr<Image> snapshottedPluginImageForLabelDisplay(PassRefPtr<Image> snapshot, const LayoutRect& blurRegion)
 {
+    OwnPtr<ImageBuffer> snapshotBuffer = ImageBuffer::create(snapshot->size());
+    snapshotBuffer->context()->drawImage(snapshot.get(), ColorSpaceDeviceRGB, IntPoint(0, 0));
+
+    OwnPtr<ImageBuffer> blurBuffer = ImageBuffer::create(roundedIntSize(blurRegion.size()));
+    blurBuffer->context()->drawImage(snapshot.get(), ColorSpaceDeviceRGB, IntPoint(-blurRegion.x(), -blurRegion.y()));
+
+    RefPtr<RenderSnapshottedPlugInBlurFilter> blurFilter = RenderSnapshottedPlugInBlurFilter::create(snapshotLabelBlurRadius);
+    blurFilter->setSourceImage(blurBuffer.release());
+    blurFilter->setSourceImageRect(FloatRect(FloatPoint(), blurRegion.size()));
+    blurFilter->apply();
+
+    snapshotBuffer->context()->drawImageBuffer(blurFilter->output(), ColorSpaceDeviceRGB, roundedIntPoint(blurRegion.location()));
+    return snapshotBuffer->copyImage();
+}
+
+void RenderSnapshottedPlugIn::paintReplacedSnapshotWithLabel(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
+{
     if (contentBoxRect().isEmpty())
         return;
 
@@ -179,6 +260,19 @@
     if (!labelImage)
         return;
 
+    RefPtr<Image> snapshotImage = m_snapshotResource->image();
+    if (!snapshotImage || snapshotImage->isNull())
+        return;
+
+    RefPtr<Image> blurredSnapshotImage = m_snapshotResourceForLabel->image();
+    if (!blurredSnapshotImage || blurredSnapshotImage->isNull()) {
+        blurredSnapshotImage = snapshottedPluginImageForLabelDisplay(snapshotImage, labelRect);
+        m_snapshotResourceForLabel->setCachedImage(new CachedImage(blurredSnapshotImage.get()));
+    }
+    snapshotImage = blurredSnapshotImage;
+
+    paintSnapshot(snapshotImage.get(), paintInfo, paintOffset);
+
     // Remember that the labelRect includes the label inset, so we need to adjust for it.
     paintInfo.context->drawImage(labelImage, ColorSpaceDeviceRGB,
                                  IntRect(roundedIntPoint(paintOffset + labelRect.location() - IntSize(startLabelInset, startLabelInset)),

Modified: trunk/Source/WebCore/rendering/RenderSnapshottedPlugIn.h (139700 => 139701)


--- trunk/Source/WebCore/rendering/RenderSnapshottedPlugIn.h	2013-01-15 02:08:38 UTC (rev 139700)
+++ trunk/Source/WebCore/rendering/RenderSnapshottedPlugIn.h	2013-01-15 02:44:55 UTC (rev 139701)
@@ -63,7 +63,8 @@
     virtual void paintReplaced(PaintInfo&, const LayoutPoint&) OVERRIDE;
 
     void paintReplacedSnapshot(PaintInfo&, const LayoutPoint&);
-    void paintLabel(PaintInfo&, const LayoutPoint&);
+    void paintReplacedSnapshotWithLabel(PaintInfo&, const LayoutPoint&);
+    void paintSnapshot(Image*, PaintInfo&, const LayoutPoint&);
     void repaintLabel();
 
     LayoutRect tryToFitStartLabel(LabelSize, const LayoutRect& contentBox) const;
@@ -82,6 +83,7 @@
     bool m_showedLabelOnce;
     ShowReason m_showReason;
     Timer<RenderSnapshottedPlugIn> m_showLabelDelayTimer;
+    OwnPtr<RenderImageResource> m_snapshotResourceForLabel;
 };
 
 inline RenderSnapshottedPlugIn* toRenderSnapshottedPlugIn(RenderObject* object)
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to