Bug 781053 - Part 1 - Allow conversion of nsImageBoxFrame to an ImageLayer. r=roc

This commit is contained in:
Matt Woodrow 2012-09-25 08:29:14 +12:00
parent a4458b8728
commit addff1531c
5 changed files with 121 additions and 40 deletions

View File

@ -14,7 +14,6 @@
#include "nsCSSRendering.h"
#include "nsCSSFrameConstructor.h"
#include "gfxUtils.h"
#include "nsImageFrame.h"
#include "nsRenderingContext.h"
#include "MaskLayerImageCache.h"
#include "nsIScrollableFrame.h"
@ -347,7 +346,7 @@ protected:
* Stores the pointer to the nsDisplayImage if we want to
* convert this to an ImageLayer.
*/
nsDisplayImage* mImage;
nsDisplayImageContainer* mImage;
/**
* Stores the clip that we need to apply to the image or, if there is no
* image, a clip for SOME item in the layer. There is no guarantee which
@ -1548,8 +1547,10 @@ ContainerState::ThebesLayerData::Accumulate(ContainerState* aState,
/* Mark as available for conversion to image layer if this is a nsDisplayImage and
* we are the first visible item in the ThebesLayerData object.
*/
if (mVisibleRegion.IsEmpty() && aItem->GetType() == nsDisplayItem::TYPE_IMAGE) {
mImage = static_cast<nsDisplayImage*>(aItem);
if (mVisibleRegion.IsEmpty() &&
(aItem->GetType() == nsDisplayItem::TYPE_IMAGE ||
aItem->GetType() == nsDisplayItem::TYPE_XUL_IMAGE)) {
mImage = static_cast<nsDisplayImageContainer*>(aItem);
} else {
mImage = nullptr;
}

View File

@ -2577,4 +2577,17 @@ public:
nscoord mRightEdge; // length from the right side
};
class nsDisplayImageContainer : public nsDisplayItem {
public:
typedef mozilla::layers::ImageContainer ImageContainer;
typedef mozilla::layers::ImageLayer ImageLayer;
nsDisplayImageContainer(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
: nsDisplayItem(aBuilder, aFrame)
{}
virtual already_AddRefed<ImageContainer> GetContainer() = 0;
virtual void ConfigureLayer(ImageLayer* aLayer, const nsIntPoint& aOffset) = 0;
};
#endif /*NSDISPLAYLIST_H_*/

View File

@ -362,15 +362,13 @@ public:
* image itself, and hence receive events just as if the image itself
* received events.
*/
class nsDisplayImage : public nsDisplayItem {
class nsDisplayImage : public nsDisplayImageContainer {
public:
typedef mozilla::layers::ImageContainer ImageContainer;
typedef mozilla::layers::ImageLayer ImageLayer;
typedef mozilla::layers::LayerManager LayerManager;
nsDisplayImage(nsDisplayListBuilder* aBuilder, nsImageFrame* aFrame,
imgIContainer* aImage)
: nsDisplayItem(aBuilder, aFrame), mImage(aImage) {
: nsDisplayImageContainer(aBuilder, aFrame), mImage(aImage) {
MOZ_COUNT_CTOR(nsDisplayImage);
}
virtual ~nsDisplayImage() {
@ -383,7 +381,7 @@ public:
* Returns an ImageContainer for this image if the image type
* supports it (TYPE_RASTER only).
*/
already_AddRefed<ImageContainer> GetContainer();
virtual already_AddRefed<ImageContainer> GetContainer() MOZ_OVERRIDE;
gfxRect GetDestRect();
@ -399,7 +397,7 @@ public:
* Configure an ImageLayer for this display item.
* Set the required filter and scaling transform.
*/
void ConfigureLayer(ImageLayer* aLayer, const nsIntPoint& aOffset);
virtual void ConfigureLayer(ImageLayer* aLayer, const nsIntPoint& aOffset) MOZ_OVERRIDE;
NS_DISPLAY_DECL_NAME("Image", TYPE_IMAGE)
private:

View File

@ -44,11 +44,15 @@
#include "nsGUIEvent.h"
#include "nsEventDispatcher.h"
#include "nsDisplayList.h"
#include "ImageLayers.h"
#include "ImageContainer.h"
#include "nsContentUtils.h"
#define ONLOAD_CALLED_TOO_EARLY 1
using namespace mozilla::layers;
class nsImageBoxFrameEvent : public nsRunnable
{
public:
@ -282,36 +286,6 @@ nsImageBoxFrame::UpdateLoadFlags()
}
}
class nsDisplayXULImage : public nsDisplayItem {
public:
nsDisplayXULImage(nsDisplayListBuilder* aBuilder,
nsImageBoxFrame* aFrame) :
nsDisplayItem(aBuilder, aFrame) {
MOZ_COUNT_CTOR(nsDisplayXULImage);
}
#ifdef NS_BUILD_REFCNT_LOGGING
virtual ~nsDisplayXULImage() {
MOZ_COUNT_DTOR(nsDisplayXULImage);
}
#endif
// Doesn't handle HitTest because nsLeafBoxFrame already creates an
// event receiver for us
virtual void Paint(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aCtx);
NS_DISPLAY_DECL_NAME("XULImage", TYPE_XUL_IMAGE)
};
void nsDisplayXULImage::Paint(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aCtx)
{
static_cast<nsImageBoxFrame*>(mFrame)->
PaintImage(*aCtx, mVisibleRect, ToReferenceFrame(),
aBuilder->ShouldSyncDecodeImages()
? (uint32_t) imgIContainer::FLAG_SYNC_DECODE
: (uint32_t) imgIContainer::FLAG_NONE);
}
NS_IMETHODIMP
nsImageBoxFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
@ -363,6 +337,74 @@ nsImageBoxFrame::PaintImage(nsRenderingContext& aRenderingContext,
}
}
void nsDisplayXULImage::Paint(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aCtx)
{
static_cast<nsImageBoxFrame*>(mFrame)->
PaintImage(*aCtx, mVisibleRect, ToReferenceFrame(),
aBuilder->ShouldSyncDecodeImages()
? (PRUint32) imgIContainer::FLAG_SYNC_DECODE
: (PRUint32) imgIContainer::FLAG_NONE);
}
void
nsDisplayXULImage::ConfigureLayer(ImageLayer* aLayer, const nsIntPoint& aOffset)
{
aLayer->SetFilter(nsLayoutUtils::GetGraphicsFilterForFrame(mFrame));
PRInt32 factor = mFrame->PresContext()->AppUnitsPerDevPixel();
nsImageBoxFrame* imageFrame = static_cast<nsImageBoxFrame*>(mFrame);
nsRect dest;
imageFrame->GetClientRect(dest);
dest += ToReferenceFrame();
gfxRect destRect(dest.x, dest.y, dest.width, dest.height);
destRect.ScaleInverse(factor);
nsCOMPtr<imgIContainer> imgCon;
imageFrame->mImageRequest->GetImage(getter_AddRefs(imgCon));
PRInt32 imageWidth;
PRInt32 imageHeight;
imgCon->GetWidth(&imageWidth);
imgCon->GetHeight(&imageHeight);
NS_ASSERTION(imageWidth != 0 && imageHeight != 0, "Invalid image size!");
gfxMatrix transform;
transform.Translate(destRect.TopLeft() + aOffset);
transform.Scale(destRect.Width()/imageWidth,
destRect.Height()/imageHeight);
aLayer->SetBaseTransform(gfx3DMatrix::From2D(transform));
aLayer->SetVisibleRegion(nsIntRect(0, 0, imageWidth, imageHeight));
}
already_AddRefed<ImageContainer>
nsDisplayXULImage::GetContainer()
{
return static_cast<nsImageBoxFrame*>(mFrame)->GetContainer();
}
already_AddRefed<ImageContainer>
nsImageBoxFrame::GetContainer()
{
bool hasSubRect = !mUseSrcAttr && (mSubRect.width > 0 || mSubRect.height > 0);
if (hasSubRect || !mImageRequest) {
return nullptr;
}
nsCOMPtr<imgIContainer> imgCon;
mImageRequest->GetImage(getter_AddRefs(imgCon));
if (!imgCon) {
return nullptr;
}
nsRefPtr<ImageContainer> container;
nsresult rv = imgCon->GetImageContainer(getter_AddRefs(container));
NS_ENSURE_SUCCESS(rv, nullptr);
return container.forget();
}
//
// DidSetStyleContext

View File

@ -15,6 +15,8 @@
class nsImageBoxFrame;
class nsDisplayXULImage;
class nsImageBoxListener : public nsStubImageDecoderObserver
{
public:
@ -43,6 +45,7 @@ private:
class nsImageBoxFrame : public nsLeafBoxFrame
{
public:
friend class nsDisplayXULImage;
NS_DECL_FRAMEARENA_HELPERS
virtual nsSize GetPrefSize(nsBoxLayoutState& aBoxLayoutState);
@ -103,6 +106,7 @@ public:
const nsRect& aDirtyRect,
nsPoint aPt, uint32_t aFlags);
already_AddRefed<mozilla::layers::ImageContainer> GetContainer();
protected:
nsImageBoxFrame(nsIPresShell* aShell, nsStyleContext* aContext);
@ -127,4 +131,27 @@ private:
bool mSuppressStyleCheck;
}; // class nsImageBoxFrame
class nsDisplayXULImage : public nsDisplayImageContainer {
public:
nsDisplayXULImage(nsDisplayListBuilder* aBuilder,
nsImageBoxFrame* aFrame) :
nsDisplayImageContainer(aBuilder, aFrame) {
MOZ_COUNT_CTOR(nsDisplayXULImage);
}
#ifdef NS_BUILD_REFCNT_LOGGING
virtual ~nsDisplayXULImage() {
MOZ_COUNT_DTOR(nsDisplayXULImage);
}
#endif
virtual already_AddRefed<ImageContainer> GetContainer() MOZ_OVERRIDE;
virtual void ConfigureLayer(ImageLayer* aLayer, const nsIntPoint& aOffset) MOZ_OVERRIDE;
// Doesn't handle HitTest because nsLeafBoxFrame already creates an
// event receiver for us
virtual void Paint(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aCtx);
NS_DISPLAY_DECL_NAME("XULImage", TYPE_XUL_IMAGE)
};
#endif /* nsImageBoxFrame_h___ */