Bug 852754 - Part 1: Share the code for limiting scale factors to all image types. r=mstange

This commit is contained in:
Matt Woodrow 2016-04-07 18:52:35 +12:00
Родитель 8232d31724
Коммит 46ff4c4fc7
10 изменённых файлов: 151 добавлений и 192 удалений

Просмотреть файл

@ -5404,21 +5404,6 @@ nsImageRenderer::IsAnimatedImage()
return false; return false;
} }
bool
nsImageRenderer::IsContainerAvailable(LayerManager* aManager,
nsDisplayListBuilder* aBuilder)
{
if (mType != eStyleImageType_Image || !mImageContainer) {
return false;
}
uint32_t flags = aBuilder->ShouldSyncDecodeImages()
? imgIContainer::FLAG_SYNC_DECODE
: imgIContainer::FLAG_NONE;
return mImageContainer->IsImageContainerAvailable(aManager, flags);
}
already_AddRefed<imgIContainer> already_AddRefed<imgIContainer>
nsImageRenderer::GetImage() nsImageRenderer::GetImage()
{ {

Просмотреть файл

@ -251,16 +251,6 @@ public:
bool IsRasterImage(); bool IsRasterImage();
bool IsAnimatedImage(); bool IsAnimatedImage();
/**
* @return true if this nsImageRenderer wraps an image which has an
* ImageContainer available.
*
* If IsContainerAvailable() returns true, GetImage() will return a non-null
* imgIContainer which callers can use to retrieve the ImageContainer.
*/
bool IsContainerAvailable(LayerManager* aManager,
nsDisplayListBuilder* aBuilder);
/// Retrieves the image associated with this nsImageRenderer, if there is one. /// Retrieves the image associated with this nsImageRenderer, if there is one.
already_AddRefed<imgIContainer> GetImage(); already_AddRefed<imgIContainer> GetImage();

Просмотреть файл

@ -2309,32 +2309,33 @@ nsDisplayBackgroundImage::nsDisplayBackgroundImage(nsDisplayListBuilder* aBuilde
: nsDisplayImageContainer(aBuilder, aFrame) : nsDisplayImageContainer(aBuilder, aFrame)
, mBackgroundStyle(aBackgroundStyle) , mBackgroundStyle(aBackgroundStyle)
, mLayer(aLayer) , mLayer(aLayer)
, mIsRasterImage(false)
{ {
MOZ_COUNT_CTOR(nsDisplayBackgroundImage); MOZ_COUNT_CTOR(nsDisplayBackgroundImage);
mBounds = GetBoundsInternal(aBuilder); mBounds = GetBoundsInternal(aBuilder);
mDestArea = GetDestAreaInternal(aBuilder);
if (ShouldFixToViewport(aBuilder)) { if (ShouldFixToViewport(aBuilder)) {
mAnimatedGeometryRoot = aBuilder->FindAnimatedGeometryRootFor(this); mAnimatedGeometryRoot = aBuilder->FindAnimatedGeometryRootFor(this);
} }
}
nsRect
nsDisplayBackgroundImage::GetDestAreaInternal(nsDisplayListBuilder* aBuilder)
{
if (!mBackgroundStyle) {
return nsRect();
}
nsPresContext* presContext = mFrame->PresContext(); nsPresContext* presContext = mFrame->PresContext();
uint32_t flags = aBuilder->GetBackgroundPaintFlags(); uint32_t flags = aBuilder->GetBackgroundPaintFlags();
nsRect borderArea = nsRect(ToReferenceFrame(), mFrame->GetSize()); nsRect borderArea = nsRect(ToReferenceFrame(), mFrame->GetSize());
const nsStyleImageLayers::Layer& layer = mBackgroundStyle->mImage.mLayers[mLayer]; const nsStyleImageLayers::Layer &layer = mBackgroundStyle->mImage.mLayers[mLayer];
nsBackgroundLayerState state = nsBackgroundLayerState state =
nsCSSRendering::PrepareImageLayer(presContext, mFrame, flags, nsCSSRendering::PrepareImageLayer(presContext, mFrame, flags,
borderArea, borderArea, layer); borderArea, borderArea, layer);
return state.mDestArea;
mFillRect = state.mFillArea;
mDestRect = state.mDestArea;
nsImageRenderer* imageRenderer = &state.mImageRenderer;
// We only care about images here, not gradients.
if (imageRenderer->IsRasterImage()) {
mIsRasterImage = true;
mImage = imageRenderer->GetImage();
}
} }
nsDisplayBackgroundImage::~nsDisplayBackgroundImage() nsDisplayBackgroundImage::~nsDisplayBackgroundImage()
@ -2566,24 +2567,16 @@ nsDisplayBackgroundImage::IsSingleFixedPositionImage(nsDisplayListBuilder* aBuil
if (mBackgroundStyle->mImage.mLayers.Length() != 1) if (mBackgroundStyle->mImage.mLayers.Length() != 1)
return false; return false;
nsPresContext* presContext = mFrame->PresContext();
uint32_t flags = aBuilder->GetBackgroundPaintFlags();
nsRect borderArea = nsRect(ToReferenceFrame(), mFrame->GetSize());
const nsStyleImageLayers::Layer &layer = mBackgroundStyle->mImage.mLayers[mLayer]; const nsStyleImageLayers::Layer &layer = mBackgroundStyle->mImage.mLayers[mLayer];
if (layer.mAttachment != NS_STYLE_IMAGELAYER_ATTACHMENT_FIXED) if (layer.mAttachment != NS_STYLE_IMAGELAYER_ATTACHMENT_FIXED)
return false; return false;
nsBackgroundLayerState state =
nsCSSRendering::PrepareImageLayer(presContext, mFrame, flags,
borderArea, aClipRect, layer);
nsImageRenderer* imageRenderer = &state.mImageRenderer;
// We only care about images here, not gradients. // We only care about images here, not gradients.
if (!imageRenderer->IsRasterImage()) if (!mIsRasterImage)
return false; return false;
int32_t appUnitsPerDevPixel = presContext->AppUnitsPerDevPixel(); int32_t appUnitsPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel();
*aDestRect = nsLayoutUtils::RectToGfxRect(state.mFillArea, appUnitsPerDevPixel); *aDestRect = nsLayoutUtils::RectToGfxRect(mFillRect, appUnitsPerDevPixel);
return true; return true;
} }
@ -2618,51 +2611,35 @@ nsDisplayBackgroundImage::CanOptimizeToImageLayer(LayerManager* aManager,
return false; return false;
} }
nsPresContext* presContext = mFrame->PresContext();
uint32_t flags = aBuilder->GetBackgroundPaintFlags();
nsRect borderArea = nsRect(ToReferenceFrame(), mFrame->GetSize());
const nsStyleImageLayers::Layer &layer = mBackgroundStyle->mImage.mLayers[mLayer];
nsBackgroundLayerState state =
nsCSSRendering::PrepareImageLayer(presContext, mFrame, flags,
borderArea, borderArea, layer);
nsImageRenderer* imageRenderer = &state.mImageRenderer;
// We only care about images here, not gradients.
if (!imageRenderer->IsRasterImage()) {
return false;
}
if (!imageRenderer->IsContainerAvailable(aManager, aBuilder)) {
// The image is not ready to be made into a layer yet.
return false;
}
// We currently can't handle tiled backgrounds. // We currently can't handle tiled backgrounds.
if (!state.mDestArea.Contains(state.mFillArea)) { if (!mDestRect.Contains(mFillRect)) {
return false; return false;
} }
// For 'contain' and 'cover', we allow any pixel of the image to be sampled // For 'contain' and 'cover', we allow any pixel of the image to be sampled
// because there isn't going to be any spriting/atlasing going on. // because there isn't going to be any spriting/atlasing going on.
const nsStyleImageLayers::Layer &layer = mBackgroundStyle->mImage.mLayers[mLayer];
bool allowPartialImages = bool allowPartialImages =
(layer.mSize.mWidthType == nsStyleImageLayers::Size::eContain || (layer.mSize.mWidthType == nsStyleImageLayers::Size::eContain ||
layer.mSize.mWidthType == nsStyleImageLayers::Size::eCover); layer.mSize.mWidthType == nsStyleImageLayers::Size::eCover);
if (!allowPartialImages && !state.mFillArea.Contains(state.mDestArea)) { if (!allowPartialImages && !mFillRect.Contains(mDestRect)) {
return false; return false;
} }
// XXX Ignoring state.mAnchor. ImageLayer drawing snaps mDestArea edges to return nsDisplayImageContainer::CanOptimizeToImageLayer(aManager, aBuilder);
// layer pixel boundaries. This should be OK for now. }
int32_t appUnitsPerDevPixel = presContext->AppUnitsPerDevPixel(); nsRect
mImageLayerDestRect = nsDisplayBackgroundImage::GetDestRect()
LayoutDeviceRect::FromAppUnits(state.mDestArea, appUnitsPerDevPixel); {
return mDestRect;
}
// Ok, we can turn this into a layer if needed. already_AddRefed<imgIContainer>
mImage = imageRenderer->GetImage(); nsDisplayBackgroundImage::GetImage()
MOZ_ASSERT(mImage); {
nsCOMPtr<imgIContainer> image = mImage;
return true; return image.forget();
} }
already_AddRefed<ImageContainer> already_AddRefed<ImageContainer>
@ -2747,8 +2724,11 @@ nsDisplayBackgroundImage::GetLayerState(nsDisplayListBuilder* aBuilder,
mImage->GetWidth(&imageWidth); mImage->GetWidth(&imageWidth);
mImage->GetHeight(&imageHeight); mImage->GetHeight(&imageHeight);
NS_ASSERTION(imageWidth != 0 && imageHeight != 0, "Invalid image size!"); NS_ASSERTION(imageWidth != 0 && imageHeight != 0, "Invalid image size!");
int32_t appUnitsPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel();
LayoutDeviceRect destRect = LayoutDeviceRect::FromAppUnits(GetDestRect(), appUnitsPerDevPixel);
const LayerRect destLayerRect = mImageLayerDestRect * aParameters.Scale(); const LayerRect destLayerRect = destRect * aParameters.Scale();
// Calculate the scaling factor for the frame. // Calculate the scaling factor for the frame.
const gfxSize scale = gfxSize(destLayerRect.width / imageWidth, const gfxSize scale = gfxSize(destLayerRect.width / imageWidth,
@ -2821,11 +2801,15 @@ nsDisplayBackgroundImage::ConfigureLayer(ImageLayer* aLayer,
IntSize containerSize = aLayer->GetContainer() IntSize containerSize = aLayer->GetContainer()
? aLayer->GetContainer()->GetCurrentSize() ? aLayer->GetContainer()->GetCurrentSize()
: IntSize(imageWidth, imageHeight); : IntSize(imageWidth, imageHeight);
const int32_t factor = mFrame->PresContext()->AppUnitsPerDevPixel();
const LayoutDeviceRect destRect =
LayoutDeviceRect::FromAppUnits(GetDestRect(), factor);
const LayoutDevicePoint p = mImageLayerDestRect.TopLeft(); const LayoutDevicePoint p = destRect.TopLeft();
Matrix transform = Matrix::Translation(p.x, p.y); Matrix transform = Matrix::Translation(p.x, p.y);
transform.PreScale(mImageLayerDestRect.width / containerSize.width, transform.PreScale(destRect.width / containerSize.width,
mImageLayerDestRect.height / containerSize.height); destRect.height / containerSize.height);
aLayer->SetBaseTransform(gfx::Matrix4x4::From2D(transform)); aLayer->SetBaseTransform(gfx::Matrix4x4::From2D(transform));
} }
@ -3022,7 +3006,7 @@ void nsDisplayBackgroundImage::ComputeInvalidationRegion(nsDisplayListBuilder* a
} }
return; return;
} }
if (!mDestArea.IsEqualInterior(geometry->mDestArea)) { if (!mDestRect.IsEqualInterior(geometry->mDestRect)) {
// Dest area changed in a way that could cause everything to change, // Dest area changed in a way that could cause everything to change,
// so invalidate everything (both old and new painting areas). // so invalidate everything (both old and new painting areas).
aInvalidRegion->Or(bounds, geometry->mBounds); aInvalidRegion->Or(bounds, geometry->mBounds);
@ -3248,6 +3232,50 @@ nsDisplayThemedBackground::GetBoundsInternal() {
return r + ToReferenceFrame(); return r + ToReferenceFrame();
} }
bool
nsDisplayImageContainer::CanOptimizeToImageLayer(LayerManager* aManager,
nsDisplayListBuilder* aBuilder)
{
uint32_t flags = aBuilder->ShouldSyncDecodeImages()
? imgIContainer::FLAG_SYNC_DECODE
: imgIContainer::FLAG_NONE;
nsCOMPtr<imgIContainer> image = GetImage();
if (!image) {
return false;
}
if (!image->IsImageContainerAvailable(aManager, flags)) {
return false;
}
int32_t imageWidth;
int32_t imageHeight;
image->GetWidth(&imageWidth);
image->GetHeight(&imageHeight);
if (imageWidth == 0 || imageHeight == 0) {
NS_ASSERTION(false, "invalid image size");
return false;
}
const int32_t factor = mFrame->PresContext()->AppUnitsPerDevPixel();
const LayoutDeviceRect destRect =
LayoutDeviceRect::FromAppUnits(GetDestRect(), factor);
// Calculate the scaling factor for the frame.
const gfxSize scale = gfxSize(destRect.width / imageWidth,
destRect.height / imageHeight);
if (scale.width < 0.2 || scale.height < 0.2) {
// This would look awful as long as we can't use high-quality downscaling
// for image layers (bug 803703), so don't turn this into an image layer.
return false;
}
return true;
}
void void
nsDisplayBackgroundColor::ApplyOpacity(nsDisplayListBuilder* aBuilder, nsDisplayBackgroundColor::ApplyOpacity(nsDisplayListBuilder* aBuilder,
float aOpacity, float aOpacity,

Просмотреть файл

@ -2323,13 +2323,17 @@ public:
* CanOptimizeToImageLayer() first and it returned true. * CanOptimizeToImageLayer() first and it returned true.
*/ */
virtual bool CanOptimizeToImageLayer(LayerManager* aManager, virtual bool CanOptimizeToImageLayer(LayerManager* aManager,
nsDisplayListBuilder* aBuilder) = 0; nsDisplayListBuilder* aBuilder);
virtual already_AddRefed<ImageContainer> GetContainer(LayerManager* aManager, virtual already_AddRefed<ImageContainer> GetContainer(LayerManager* aManager,
nsDisplayListBuilder* aBuilder) = 0; nsDisplayListBuilder* aBuilder) = 0;
virtual void ConfigureLayer(ImageLayer* aLayer, virtual void ConfigureLayer(ImageLayer* aLayer,
const ContainerLayerParameters& aParameters) = 0; const ContainerLayerParameters& aParameters) = 0;
virtual already_AddRefed<imgIContainer> GetImage() = 0;
virtual nsRect GetDestRect() = 0;
virtual bool SupportsOptimizingToImage() override { return true; } virtual bool SupportsOptimizingToImage() override { return true; }
}; };
@ -2698,11 +2702,6 @@ public:
*/ */
nsRect GetPositioningArea(); nsRect GetPositioningArea();
/**
* Return the destination area of one instance of the image.
*/
nsRect GetDestArea() const { return mDestArea; }
/** /**
* Returns true if existing rendered pixels of this display item may need * Returns true if existing rendered pixels of this display item may need
* to be redrawn if the positioning area size changes but its position does * to be redrawn if the positioning area size changes but its position does
@ -2723,6 +2722,8 @@ public:
virtual bool CanOptimizeToImageLayer(LayerManager* aManager, virtual bool CanOptimizeToImageLayer(LayerManager* aManager,
nsDisplayListBuilder* aBuilder) override; nsDisplayListBuilder* aBuilder) override;
virtual already_AddRefed<imgIContainer> GetImage() override;
virtual nsRect GetDestRect() override;
virtual already_AddRefed<ImageContainer> GetContainer(LayerManager* aManager, virtual already_AddRefed<ImageContainer> GetContainer(LayerManager* aManager,
nsDisplayListBuilder *aBuilder) override; nsDisplayListBuilder *aBuilder) override;
virtual void ConfigureLayer(ImageLayer* aLayer, virtual void ConfigureLayer(ImageLayer* aLayer,
@ -2743,7 +2744,6 @@ protected:
gfxRect* aDestRect); gfxRect* aDestRect);
bool IsNonEmptyFixedImage() const; bool IsNonEmptyFixedImage() const;
nsRect GetBoundsInternal(nsDisplayListBuilder* aBuilder); nsRect GetBoundsInternal(nsDisplayListBuilder* aBuilder);
nsRect GetDestAreaInternal(nsDisplayListBuilder* aBuilder);
void PaintInternal(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx, void PaintInternal(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx,
const nsRect& aBounds, nsRect* aClipRect); const nsRect& aBounds, nsRect* aClipRect);
@ -2763,11 +2763,12 @@ protected:
const nsStyleBackground* mBackgroundStyle; const nsStyleBackground* mBackgroundStyle;
nsCOMPtr<imgIContainer> mImage; nsCOMPtr<imgIContainer> mImage;
RefPtr<ImageContainer> mImageContainer; RefPtr<ImageContainer> mImageContainer;
LayoutDeviceRect mImageLayerDestRect; nsRect mFillRect;
nsRect mDestRect;
/* Bounds of this display item */ /* Bounds of this display item */
nsRect mBounds; nsRect mBounds;
nsRect mDestArea;
uint32_t mLayer; uint32_t mLayer;
bool mIsRasterImage;
}; };

Просмотреть файл

@ -63,7 +63,7 @@ nsDisplayBackgroundGeometry::nsDisplayBackgroundGeometry(nsDisplayBackgroundImag
: nsDisplayItemGeometry(aItem, aBuilder) : nsDisplayItemGeometry(aItem, aBuilder)
, nsImageGeometryMixin(aItem, aBuilder) , nsImageGeometryMixin(aItem, aBuilder)
, mPositioningArea(aItem->GetPositioningArea()) , mPositioningArea(aItem->GetPositioningArea())
, mDestArea(aItem->GetDestArea()) , mDestRect(aItem->GetDestRect())
{} {}
void void
@ -71,7 +71,7 @@ nsDisplayBackgroundGeometry::MoveBy(const nsPoint& aOffset)
{ {
nsDisplayItemGeometry::MoveBy(aOffset); nsDisplayItemGeometry::MoveBy(aOffset);
mPositioningArea.MoveBy(aOffset); mPositioningArea.MoveBy(aOffset);
mDestArea.MoveBy(aOffset); mDestRect.MoveBy(aOffset);
} }
nsDisplayThemedBackgroundGeometry::nsDisplayThemedBackgroundGeometry(nsDisplayThemedBackground* aItem, nsDisplayThemedBackgroundGeometry::nsDisplayThemedBackgroundGeometry(nsDisplayThemedBackground* aItem,

Просмотреть файл

@ -194,7 +194,7 @@ public:
virtual void MoveBy(const nsPoint& aOffset) override; virtual void MoveBy(const nsPoint& aOffset) override;
nsRect mPositioningArea; nsRect mPositioningArea;
nsRect mDestArea; nsRect mDestRect;
}; };
class nsDisplayThemedBackgroundGeometry : public nsDisplayItemGeometry class nsDisplayThemedBackgroundGeometry : public nsDisplayItemGeometry

Просмотреть файл

@ -1524,45 +1524,6 @@ nsDisplayImage::ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
nsDisplayImageContainer::ComputeInvalidationRegion(aBuilder, aGeometry, aInvalidRegion); nsDisplayImageContainer::ComputeInvalidationRegion(aBuilder, aGeometry, aInvalidRegion);
} }
bool
nsDisplayImage::CanOptimizeToImageLayer(LayerManager* aManager,
nsDisplayListBuilder* aBuilder)
{
uint32_t flags = aBuilder->ShouldSyncDecodeImages()
? imgIContainer::FLAG_SYNC_DECODE
: imgIContainer::FLAG_NONE;
if (!mImage->IsImageContainerAvailable(aManager, flags)) {
return false;
}
int32_t imageWidth;
int32_t imageHeight;
mImage->GetWidth(&imageWidth);
mImage->GetHeight(&imageHeight);
if (imageWidth == 0 || imageHeight == 0) {
NS_ASSERTION(false, "invalid image size");
return false;
}
const int32_t factor = mFrame->PresContext()->AppUnitsPerDevPixel();
const LayoutDeviceRect destRect =
LayoutDeviceRect::FromAppUnits(GetDestRect(), factor);
// Calculate the scaling factor for the frame.
const gfxSize scale = gfxSize(destRect.width / imageWidth,
destRect.height / imageHeight);
if (scale.width < 0.2 || scale.height < 0.2) {
// This would look awful as long as we can't use high-quality downscaling
// for image layers (bug 803703), so don't turn this into an image layer.
return false;
}
return true;
}
already_AddRefed<ImageContainer> already_AddRefed<ImageContainer>
nsDisplayImage::GetContainer(LayerManager* aManager, nsDisplayImage::GetContainer(LayerManager* aManager,
nsDisplayListBuilder* aBuilder) nsDisplayListBuilder* aBuilder)
@ -1574,14 +1535,18 @@ nsDisplayImage::GetContainer(LayerManager* aManager,
return mImage->GetImageContainer(aManager, flags); return mImage->GetImageContainer(aManager, flags);
} }
already_AddRefed<imgIContainer>
nsDisplayImage::GetImage()
{
nsCOMPtr<imgIContainer> image = mImage;
return image.forget();
}
nsRect nsRect
nsDisplayImage::GetDestRect(bool* aSnap) nsDisplayImage::GetDestRect()
{ {
bool snap = true; bool snap = true;
const nsRect frameContentBox = GetBounds(&snap); const nsRect frameContentBox = GetBounds(&snap);
if (aSnap) {
*aSnap = snap;
}
nsImageFrame* imageFrame = static_cast<nsImageFrame*>(mFrame); nsImageFrame* imageFrame = static_cast<nsImageFrame*>(mFrame);
return imageFrame->PredictedDestRect(frameContentBox); return imageFrame->PredictedDestRect(frameContentBox);

Просмотреть файл

@ -428,8 +428,7 @@ public:
virtual void Paint(nsDisplayListBuilder* aBuilder, virtual void Paint(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aCtx) override; nsRenderingContext* aCtx) override;
virtual bool CanOptimizeToImageLayer(LayerManager* aManager, virtual already_AddRefed<imgIContainer> GetImage() override;
nsDisplayListBuilder* aBuilder) override;
/** /**
* Returns an ImageContainer for this image if the image type * Returns an ImageContainer for this image if the image type
@ -442,7 +441,7 @@ public:
* @return The dest rect we'll use when drawing this image, in app units. * @return The dest rect we'll use when drawing this image, in app units.
* Not necessarily contained in this item's bounds. * Not necessarily contained in this item's bounds.
*/ */
nsRect GetDestRect(bool* aSnap = nullptr); virtual nsRect GetDestRect() override;
virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder, virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
LayerManager* aManager, LayerManager* aManager,

Просмотреть файл

@ -450,17 +450,10 @@ nsDisplayXULImage::ConfigureLayer(ImageLayer* aLayer,
{ {
aLayer->SetFilter(nsLayoutUtils::GetGraphicsFilterForFrame(mFrame)); aLayer->SetFilter(nsLayoutUtils::GetGraphicsFilterForFrame(mFrame));
nsImageBoxFrame* imageFrame = static_cast<nsImageBoxFrame*>(mFrame);
nsRect clientRect;
imageFrame->GetClientRect(clientRect);
const int32_t factor = mFrame->PresContext()->AppUnitsPerDevPixel(); const int32_t factor = mFrame->PresContext()->AppUnitsPerDevPixel();
const LayoutDeviceRect destRect = LayoutDeviceRect destRect = LayoutDeviceRect::FromAppUnits(GetDestRect(), factor);
LayoutDeviceRect::FromAppUnits(clientRect + ToReferenceFrame(), factor);
nsCOMPtr<imgIContainer> imgCon; nsCOMPtr<imgIContainer> imgCon = GetImage();
imageFrame->mImageRequest->GetImage(getter_AddRefs(imgCon));
int32_t imageWidth; int32_t imageWidth;
int32_t imageHeight; int32_t imageHeight;
imgCon->GetWidth(&imageWidth); imgCon->GetWidth(&imageWidth);
@ -503,30 +496,47 @@ bool
nsDisplayXULImage::CanOptimizeToImageLayer(LayerManager* aManager, nsDisplayXULImage::CanOptimizeToImageLayer(LayerManager* aManager,
nsDisplayListBuilder* aBuilder) nsDisplayListBuilder* aBuilder)
{ {
uint32_t flags = aBuilder->ShouldSyncDecodeImages() nsImageBoxFrame* imageFrame = static_cast<nsImageBoxFrame*>(mFrame);
? imgIContainer::FLAG_SYNC_DECODE if (!imageFrame->CanOptimizeToImageLayer()) {
: imgIContainer::FLAG_NONE; return false;
}
return static_cast<nsImageBoxFrame*>(mFrame) return nsDisplayImageContainer::CanOptimizeToImageLayer(aManager, aBuilder);
->IsImageContainerAvailable(aManager, flags);
} }
bool already_AddRefed<imgIContainer>
nsImageBoxFrame::IsImageContainerAvailable(LayerManager* aManager, nsDisplayXULImage::GetImage()
uint32_t aFlags)
{ {
bool hasSubRect = !mUseSrcAttr && (mSubRect.width > 0 || mSubRect.height > 0); nsImageBoxFrame* imageFrame = static_cast<nsImageBoxFrame*>(mFrame);
if (hasSubRect || !mImageRequest) { if (!imageFrame->mImageRequest) {
return false; return nullptr;
} }
nsCOMPtr<imgIContainer> imgCon; nsCOMPtr<imgIContainer> imgCon;
mImageRequest->GetImage(getter_AddRefs(imgCon)); imageFrame->mImageRequest->GetImage(getter_AddRefs(imgCon));
if (!imgCon) {
return imgCon.forget();
}
nsRect
nsDisplayXULImage::GetDestRect()
{
nsImageBoxFrame* imageFrame = static_cast<nsImageBoxFrame*>(mFrame);
nsRect clientRect;
imageFrame->GetClientRect(clientRect);
return clientRect + ToReferenceFrame();
}
bool
nsImageBoxFrame::CanOptimizeToImageLayer()
{
bool hasSubRect = !mUseSrcAttr && (mSubRect.width > 0 || mSubRect.height > 0);
if (hasSubRect) {
return false; return false;
} }
return true;
return imgCon->IsImageContainerAvailable(aManager, aFlags);
} }
already_AddRefed<ImageContainer> already_AddRefed<ImageContainer>
@ -537,30 +547,11 @@ nsDisplayXULImage::GetContainer(LayerManager* aManager,
? imgIContainer::FLAG_SYNC_DECODE ? imgIContainer::FLAG_SYNC_DECODE
: imgIContainer::FLAG_NONE; : imgIContainer::FLAG_NONE;
return static_cast<nsImageBoxFrame*>(mFrame)->GetContainer(aManager, flags); nsCOMPtr<imgIContainer> image = GetImage();
} if (image) {
return image->GetImageContainer(aManager, flags);
already_AddRefed<ImageContainer>
nsImageBoxFrame::GetContainer(LayerManager* aManager, uint32_t aFlags)
{
MOZ_ASSERT(IsImageContainerAvailable(aManager, aFlags),
"Should call IsImageContainerAvailable and get true before "
"calling GetContainer");
if (!mImageRequest) {
MOZ_ASSERT_UNREACHABLE("mImageRequest should be available if "
"IsImageContainerAvailable returned true");
return nullptr;
} }
return nullptr;
nsCOMPtr<imgIContainer> imgCon;
mImageRequest->GetImage(getter_AddRefs(imgCon));
if (!imgCon) {
MOZ_ASSERT_UNREACHABLE("An imgIContainer should be available if "
"IsImageContainerAvailable returned true");
return nullptr;
}
return imgCon->GetImageContainer(aManager, aFlags);
} }

Просмотреть файл

@ -96,9 +96,7 @@ public:
const nsRect& aDirtyRect, const nsRect& aDirtyRect,
nsPoint aPt, uint32_t aFlags); nsPoint aPt, uint32_t aFlags);
bool IsImageContainerAvailable(LayerManager* aManager, uint32_t aFlags); bool CanOptimizeToImageLayer();
already_AddRefed<ImageContainer> GetContainer(LayerManager* aManager,
uint32_t aFlags);
protected: protected:
explicit nsImageBoxFrame(nsStyleContext* aContext); explicit nsImageBoxFrame(nsStyleContext* aContext);
@ -146,6 +144,8 @@ public:
nsDisplayListBuilder* aBuilder) override; nsDisplayListBuilder* aBuilder) override;
virtual already_AddRefed<ImageContainer> GetContainer(LayerManager* aManager, virtual already_AddRefed<ImageContainer> GetContainer(LayerManager* aManager,
nsDisplayListBuilder* aBuilder) override; nsDisplayListBuilder* aBuilder) override;
virtual already_AddRefed<imgIContainer> GetImage() override;
virtual nsRect GetDestRect() override;
virtual void ConfigureLayer(ImageLayer* aLayer, virtual void ConfigureLayer(ImageLayer* aLayer,
const ContainerLayerParameters& aParameters) override; const ContainerLayerParameters& aParameters) override;
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) override virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) override