/* -*- 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; using mozilla::layers::ImageContainer; namespace mozilla { namespace image { // Inherited methods from Image. already_AddRefed DynamicImage::GetProgressTracker() { return nullptr; } size_t DynamicImage::SizeOfSourceWithComputedFallback( SizeOfState& aState) const { return 0; } void DynamicImage::CollectSizeOfSurfaces( nsTArray& 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; } nsresult DynamicImage::GetNativeSizes(nsTArray& aNativeSizes) const { return NS_ERROR_NOT_IMPLEMENTED; } size_t DynamicImage::GetNativeSizesLength() const { return 0; } NS_IMETHODIMP DynamicImage::GetIntrinsicSize(nsSize* aSize) { IntSize intSize(mDrawable->Size()); *aSize = nsSize(intSize.width, intSize.height); return NS_OK; } Maybe 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) 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) DynamicImage::GetFrameAtSize(const IntSize& aSize, uint32_t aWhichFrame, uint32_t aFlags) { RefPtr dt = gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget( aSize, SurfaceFormat::OS_RGBA); if (!dt || !dt->IsValid()) { gfxWarning() << "DynamicImage::GetFrame failed in CreateOffscreenContentDrawTarget"; return nullptr; } RefPtr context = gfxContext::CreateOrNull(dt); MOZ_ASSERT(context); // already checked the draw target above auto result = Draw(context, aSize, ImageRegion::Create(aSize), aWhichFrame, SamplingFilter::POINT, Nothing(), 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 Maybe& aSVGContext, const Maybe& 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 Maybe& 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; } gfxSize scale(double(aSize.width) / drawableSize.width, double(aSize.height) / drawableSize.height); ImageRegion region(aRegion); region.Scale(1.0 / scale.width, 1.0 / scale.height); gfxContextMatrixAutoSaveRestore saveMatrix(aContext); aContext->Multiply(gfxMatrix::Scaling(scale.width, scale.height)); 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 DynamicImage::Unwrap() { nsCOMPtr 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 image } // namespace mozilla