Source code

Revision control

Copy as Markdown

Other Tools

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "DynamicImage.h"
#include "gfxContext.h"
#include "gfxPlatform.h"
#include "gfxUtils.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/gfx/Logging.h"
#include "mozilla/RefPtr.h"
#include "mozilla/SVGImageContext.h"
#include "ImageRegion.h"
#include "Orientation.h"
#include "mozilla/image/Resolution.h"
#include "mozilla/MemoryReporting.h"
using namespace mozilla;
using namespace mozilla::gfx;
namespace mozilla::image {
// Inherited methods from Image.
already_AddRefed<ProgressTracker> DynamicImage::GetProgressTracker() {
return nullptr;
}
size_t DynamicImage::SizeOfSourceWithComputedFallback(
SizeOfState& aState) const {
return 0;
}
void DynamicImage::CollectSizeOfSurfaces(
nsTArray<SurfaceMemoryCounter>& aCounters,
MallocSizeOf aMallocSizeOf) const {
// We can't report anything useful because gfxDrawable doesn't expose this
// information.
}
void DynamicImage::IncrementAnimationConsumers() {}
void DynamicImage::DecrementAnimationConsumers() {}
#ifdef DEBUG
uint32_t DynamicImage::GetAnimationConsumers() { return 0; }
#endif
nsresult DynamicImage::OnImageDataAvailable(nsIRequest* aRequest,
nsIInputStream* aInStr,
uint64_t aSourceOffset,
uint32_t aCount) {
return NS_OK;
}
nsresult DynamicImage::OnImageDataComplete(nsIRequest* aRequest,
nsresult aStatus, bool aLastPart) {
return NS_OK;
}
void DynamicImage::OnSurfaceDiscarded(const SurfaceKey& aSurfaceKey) {}
void DynamicImage::SetInnerWindowID(uint64_t aInnerWindowId) {}
uint64_t DynamicImage::InnerWindowID() const { return 0; }
bool DynamicImage::HasError() { return !mDrawable; }
void DynamicImage::SetHasError() {}
nsIURI* DynamicImage::GetURI() const { return nullptr; }
// Methods inherited from XPCOM interfaces.
NS_IMPL_ISUPPORTS(DynamicImage, imgIContainer)
NS_IMETHODIMP
DynamicImage::GetWidth(int32_t* aWidth) {
*aWidth = mDrawable->Size().width;
return NS_OK;
}
NS_IMETHODIMP
DynamicImage::GetHeight(int32_t* aHeight) {
*aHeight = mDrawable->Size().height;
return NS_OK;
}
void DynamicImage::MediaFeatureValuesChangedAllDocuments(
const mozilla::MediaFeatureChange& aChange) {}
nsresult DynamicImage::GetNativeSizes(nsTArray<IntSize>&) {
return NS_ERROR_NOT_IMPLEMENTED;
}
size_t DynamicImage::GetNativeSizesLength() { return 0; }
NS_IMETHODIMP
DynamicImage::GetIntrinsicSize(nsSize* aSize) {
IntSize intSize(mDrawable->Size());
*aSize = nsSize(intSize.width, intSize.height);
return NS_OK;
}
Maybe<AspectRatio> DynamicImage::GetIntrinsicRatio() {
auto size = mDrawable->Size();
return Some(AspectRatio::FromSize(size.width, size.height));
}
NS_IMETHODIMP_(Orientation)
DynamicImage::GetOrientation() { return Orientation(); }
NS_IMETHODIMP_(Resolution)
DynamicImage::GetResolution() { return {}; }
NS_IMETHODIMP
DynamicImage::GetType(uint16_t* aType) {
*aType = imgIContainer::TYPE_RASTER;
return NS_OK;
}
NS_IMETHODIMP
DynamicImage::GetProviderId(uint32_t* aId) {
*aId = 0;
return NS_OK;
}
NS_IMETHODIMP
DynamicImage::GetAnimated(bool* aAnimated) {
*aAnimated = false;
return NS_OK;
}
NS_IMETHODIMP_(already_AddRefed<SourceSurface>)
DynamicImage::GetFrame(uint32_t aWhichFrame, uint32_t aFlags) {
IntSize size(mDrawable->Size());
return GetFrameAtSize(IntSize(size.width, size.height), aWhichFrame, aFlags);
}
NS_IMETHODIMP_(already_AddRefed<SourceSurface>)
DynamicImage::GetFrameAtSize(const IntSize& aSize, uint32_t aWhichFrame,
uint32_t aFlags) {
RefPtr<DrawTarget> dt =
gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(
aSize, SurfaceFormat::OS_RGBA);
if (!dt || !dt->IsValid()) {
gfxWarning()
<< "DynamicImage::GetFrame failed in CreateOffscreenContentDrawTarget";
return nullptr;
}
gfxContext context(dt);
auto result = Draw(&context, aSize, ImageRegion::Create(aSize), aWhichFrame,
SamplingFilter::POINT, SVGImageContext(), aFlags, 1.0);
return result == ImgDrawResult::SUCCESS ? dt->Snapshot() : nullptr;
}
NS_IMETHODIMP_(bool)
DynamicImage::WillDrawOpaqueNow() { return false; }
NS_IMETHODIMP_(bool)
DynamicImage::IsImageContainerAvailable(WindowRenderer* aRenderer,
uint32_t aFlags) {
return false;
}
NS_IMETHODIMP_(ImgDrawResult)
DynamicImage::GetImageProvider(WindowRenderer* aRenderer,
const gfx::IntSize& aSize,
const SVGImageContext& aSVGContext,
const Maybe<ImageIntRegion>& aRegion,
uint32_t aFlags,
WebRenderImageProvider** aProvider) {
return ImgDrawResult::NOT_SUPPORTED;
}
NS_IMETHODIMP_(ImgDrawResult)
DynamicImage::Draw(gfxContext* aContext, const nsIntSize& aSize,
const ImageRegion& aRegion, uint32_t aWhichFrame,
SamplingFilter aSamplingFilter,
const SVGImageContext& aSVGContext, uint32_t aFlags,
float aOpacity) {
MOZ_ASSERT(!aSize.IsEmpty(), "Unexpected empty size");
IntSize drawableSize(mDrawable->Size());
if (aSize == drawableSize) {
gfxUtils::DrawPixelSnapped(aContext, mDrawable, SizeDouble(drawableSize),
aRegion, SurfaceFormat::OS_RGBA, aSamplingFilter,
aOpacity);
return ImgDrawResult::SUCCESS;
}
MatrixScalesDouble scale(double(aSize.width) / drawableSize.width,
double(aSize.height) / drawableSize.height);
ImageRegion region(aRegion);
region.Scale(1.0 / scale.xScale, 1.0 / scale.yScale);
gfxContextMatrixAutoSaveRestore saveMatrix(aContext);
aContext->Multiply(gfxMatrix::Scaling(scale));
gfxUtils::DrawPixelSnapped(aContext, mDrawable, SizeDouble(drawableSize),
region, SurfaceFormat::OS_RGBA, aSamplingFilter,
aOpacity);
return ImgDrawResult::SUCCESS;
}
NS_IMETHODIMP
DynamicImage::StartDecoding(uint32_t aFlags, uint32_t aWhichFrame) {
return NS_OK;
}
bool DynamicImage::StartDecodingWithResult(uint32_t aFlags,
uint32_t aWhichFrame) {
return true;
}
bool DynamicImage::HasDecodedPixels() { return true; }
imgIContainer::DecodeResult DynamicImage::RequestDecodeWithResult(
uint32_t aFlags, uint32_t aWhichFrame) {
return imgIContainer::DECODE_SURFACE_AVAILABLE;
}
NS_IMETHODIMP
DynamicImage::RequestDecodeForSize(const nsIntSize& aSize, uint32_t aFlags,
uint32_t aWhichFrame) {
return NS_OK;
}
NS_IMETHODIMP
DynamicImage::LockImage() { return NS_OK; }
NS_IMETHODIMP
DynamicImage::UnlockImage() { return NS_OK; }
NS_IMETHODIMP
DynamicImage::RequestDiscard() { return NS_OK; }
NS_IMETHODIMP_(void)
DynamicImage::RequestRefresh(const mozilla::TimeStamp& aTime) {}
NS_IMETHODIMP
DynamicImage::GetAnimationMode(uint16_t* aAnimationMode) {
*aAnimationMode = kNormalAnimMode;
return NS_OK;
}
NS_IMETHODIMP
DynamicImage::SetAnimationMode(uint16_t aAnimationMode) { return NS_OK; }
NS_IMETHODIMP
DynamicImage::ResetAnimation() { return NS_OK; }
NS_IMETHODIMP_(float)
DynamicImage::GetFrameIndex(uint32_t aWhichFrame) { return 0; }
NS_IMETHODIMP_(int32_t)
DynamicImage::GetFirstFrameDelay() { return 0; }
NS_IMETHODIMP_(void)
DynamicImage::SetAnimationStartTime(const mozilla::TimeStamp& aTime) {}
nsIntSize DynamicImage::OptimalImageSizeForDest(const gfxSize& aDest,
uint32_t aWhichFrame,
SamplingFilter aSamplingFilter,
uint32_t aFlags) {
IntSize size(mDrawable->Size());
return nsIntSize(size.width, size.height);
}
NS_IMETHODIMP_(nsIntRect)
DynamicImage::GetImageSpaceInvalidationRect(const nsIntRect& aRect) {
return aRect;
}
already_AddRefed<imgIContainer> DynamicImage::Unwrap() {
nsCOMPtr<imgIContainer> self(this);
return self.forget();
}
void DynamicImage::PropagateUseCounters(dom::Document*) {
// No use counters.
}
nsresult DynamicImage::GetHotspotX(int32_t* aX) {
return Image::GetHotspotX(aX);
}
nsresult DynamicImage::GetHotspotY(int32_t* aY) {
return Image::GetHotspotY(aY);
}
} // namespace mozilla::image