1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "DynamicImage.h"
7 #include "gfxContext.h"
8 #include "gfxPlatform.h"
10 #include "mozilla/gfx/2D.h"
11 #include "mozilla/gfx/Logging.h"
12 #include "mozilla/RefPtr.h"
13 #include "mozilla/SVGImageContext.h"
14 #include "ImageRegion.h"
15 #include "Orientation.h"
17 #include "mozilla/MemoryReporting.h"
19 using namespace mozilla
;
20 using namespace mozilla::gfx
;
21 using mozilla::layers::ImageContainer
;
22 using mozilla::layers::LayerManager
;
27 // Inherited methods from Image.
29 already_AddRefed
<ProgressTracker
> DynamicImage::GetProgressTracker() {
33 size_t DynamicImage::SizeOfSourceWithComputedFallback(
34 SizeOfState
& aState
) const {
38 void DynamicImage::CollectSizeOfSurfaces(
39 nsTArray
<SurfaceMemoryCounter
>& aCounters
,
40 MallocSizeOf aMallocSizeOf
) const {
41 // We can't report anything useful because gfxDrawable doesn't expose this
45 void DynamicImage::IncrementAnimationConsumers() {}
47 void DynamicImage::DecrementAnimationConsumers() {}
50 uint32_t DynamicImage::GetAnimationConsumers() { return 0; }
53 nsresult
DynamicImage::OnImageDataAvailable(nsIRequest
* aRequest
,
54 nsISupports
* aContext
,
55 nsIInputStream
* aInStr
,
56 uint64_t aSourceOffset
,
61 nsresult
DynamicImage::OnImageDataComplete(nsIRequest
* aRequest
,
62 nsISupports
* aContext
,
63 nsresult aStatus
, bool aLastPart
) {
67 void DynamicImage::OnSurfaceDiscarded(const SurfaceKey
& aSurfaceKey
) {}
69 void DynamicImage::SetInnerWindowID(uint64_t aInnerWindowId
) {}
71 uint64_t DynamicImage::InnerWindowID() const { return 0; }
73 bool DynamicImage::HasError() { return !mDrawable
; }
75 void DynamicImage::SetHasError() {}
77 nsIURI
* DynamicImage::GetURI() const { return nullptr; }
79 // Methods inherited from XPCOM interfaces.
81 NS_IMPL_ISUPPORTS(DynamicImage
, imgIContainer
)
84 DynamicImage::GetWidth(int32_t* aWidth
) {
85 *aWidth
= mDrawable
->Size().width
;
90 DynamicImage::GetHeight(int32_t* aHeight
) {
91 *aHeight
= mDrawable
->Size().height
;
95 nsresult
DynamicImage::GetNativeSizes(nsTArray
<IntSize
>& aNativeSizes
) const {
96 return NS_ERROR_NOT_IMPLEMENTED
;
99 size_t DynamicImage::GetNativeSizesLength() const { return 0; }
102 DynamicImage::GetIntrinsicSize(nsSize
* aSize
) {
103 IntSize
intSize(mDrawable
->Size());
104 *aSize
= nsSize(intSize
.width
, intSize
.height
);
108 Maybe
<AspectRatio
> DynamicImage::GetIntrinsicRatio() {
109 auto size
= mDrawable
->Size();
110 return Some(AspectRatio::FromSize(size
.width
, size
.height
));
113 NS_IMETHODIMP_(Orientation
)
114 DynamicImage::GetOrientation() { return Orientation(); }
117 DynamicImage::HandledOrientation() { return false; }
120 DynamicImage::GetType(uint16_t* aType
) {
121 *aType
= imgIContainer::TYPE_RASTER
;
126 DynamicImage::GetProducerId(uint32_t* aId
) {
132 DynamicImage::GetAnimated(bool* aAnimated
) {
137 NS_IMETHODIMP_(already_AddRefed
<SourceSurface
>)
138 DynamicImage::GetFrame(uint32_t aWhichFrame
, uint32_t aFlags
) {
139 IntSize
size(mDrawable
->Size());
140 return GetFrameAtSize(IntSize(size
.width
, size
.height
), aWhichFrame
, aFlags
);
143 NS_IMETHODIMP_(already_AddRefed
<SourceSurface
>)
144 DynamicImage::GetFrameAtSize(const IntSize
& aSize
, uint32_t aWhichFrame
,
146 RefPtr
<DrawTarget
> dt
=
147 gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(
148 aSize
, SurfaceFormat::OS_RGBA
);
149 if (!dt
|| !dt
->IsValid()) {
151 << "DynamicImage::GetFrame failed in CreateOffscreenContentDrawTarget";
154 RefPtr
<gfxContext
> context
= gfxContext::CreateOrNull(dt
);
155 MOZ_ASSERT(context
); // already checked the draw target above
157 auto result
= Draw(context
, aSize
, ImageRegion::Create(aSize
), aWhichFrame
,
158 SamplingFilter::POINT
, Nothing(), aFlags
, 1.0);
160 return result
== ImgDrawResult::SUCCESS
? dt
->Snapshot() : nullptr;
164 DynamicImage::WillDrawOpaqueNow() { return false; }
167 DynamicImage::IsImageContainerAvailable(LayerManager
* aManager
,
172 NS_IMETHODIMP_(already_AddRefed
<ImageContainer
>)
173 DynamicImage::GetImageContainer(LayerManager
* aManager
, uint32_t aFlags
) {
178 DynamicImage::IsImageContainerAvailableAtSize(LayerManager
* aManager
,
179 const IntSize
& aSize
,
184 NS_IMETHODIMP_(ImgDrawResult
)
185 DynamicImage::GetImageContainerAtSize(layers::LayerManager
* aManager
,
186 const gfx::IntSize
& aSize
,
187 const Maybe
<SVGImageContext
>& aSVGContext
,
189 layers::ImageContainer
** aContainer
) {
190 return ImgDrawResult::NOT_SUPPORTED
;
193 NS_IMETHODIMP_(ImgDrawResult
)
194 DynamicImage::Draw(gfxContext
* aContext
, const nsIntSize
& aSize
,
195 const ImageRegion
& aRegion
, uint32_t aWhichFrame
,
196 SamplingFilter aSamplingFilter
,
197 const Maybe
<SVGImageContext
>& aSVGContext
, uint32_t aFlags
,
199 MOZ_ASSERT(!aSize
.IsEmpty(), "Unexpected empty size");
201 IntSize
drawableSize(mDrawable
->Size());
203 if (aSize
== drawableSize
) {
204 gfxUtils::DrawPixelSnapped(aContext
, mDrawable
, SizeDouble(drawableSize
),
205 aRegion
, SurfaceFormat::OS_RGBA
, aSamplingFilter
,
207 return ImgDrawResult::SUCCESS
;
210 gfxSize
scale(double(aSize
.width
) / drawableSize
.width
,
211 double(aSize
.height
) / drawableSize
.height
);
213 ImageRegion
region(aRegion
);
214 region
.Scale(1.0 / scale
.width
, 1.0 / scale
.height
);
216 gfxContextMatrixAutoSaveRestore
saveMatrix(aContext
);
217 aContext
->Multiply(gfxMatrix::Scaling(scale
.width
, scale
.height
));
219 gfxUtils::DrawPixelSnapped(aContext
, mDrawable
, SizeDouble(drawableSize
),
220 region
, SurfaceFormat::OS_RGBA
, aSamplingFilter
,
222 return ImgDrawResult::SUCCESS
;
226 DynamicImage::StartDecoding(uint32_t aFlags
, uint32_t aWhichFrame
) {
230 bool DynamicImage::StartDecodingWithResult(uint32_t aFlags
,
231 uint32_t aWhichFrame
) {
235 imgIContainer::DecodeResult
DynamicImage::RequestDecodeWithResult(
236 uint32_t aFlags
, uint32_t aWhichFrame
) {
237 return imgIContainer::DECODE_SURFACE_AVAILABLE
;
241 DynamicImage::RequestDecodeForSize(const nsIntSize
& aSize
, uint32_t aFlags
,
242 uint32_t aWhichFrame
) {
247 DynamicImage::LockImage() { return NS_OK
; }
250 DynamicImage::UnlockImage() { return NS_OK
; }
253 DynamicImage::RequestDiscard() { return NS_OK
; }
256 DynamicImage::RequestRefresh(const mozilla::TimeStamp
& aTime
) {}
259 DynamicImage::GetAnimationMode(uint16_t* aAnimationMode
) {
260 *aAnimationMode
= kNormalAnimMode
;
265 DynamicImage::SetAnimationMode(uint16_t aAnimationMode
) { return NS_OK
; }
268 DynamicImage::ResetAnimation() { return NS_OK
; }
270 NS_IMETHODIMP_(float)
271 DynamicImage::GetFrameIndex(uint32_t aWhichFrame
) { return 0; }
273 NS_IMETHODIMP_(int32_t)
274 DynamicImage::GetFirstFrameDelay() { return 0; }
277 DynamicImage::SetAnimationStartTime(const mozilla::TimeStamp
& aTime
) {}
279 nsIntSize
DynamicImage::OptimalImageSizeForDest(const gfxSize
& aDest
,
280 uint32_t aWhichFrame
,
281 SamplingFilter aSamplingFilter
,
283 IntSize
size(mDrawable
->Size());
284 return nsIntSize(size
.width
, size
.height
);
287 NS_IMETHODIMP_(nsIntRect
)
288 DynamicImage::GetImageSpaceInvalidationRect(const nsIntRect
& aRect
) {
292 already_AddRefed
<imgIContainer
> DynamicImage::Unwrap() {
293 nsCOMPtr
<imgIContainer
> self(this);
294 return self
.forget();
297 void DynamicImage::PropagateUseCounters(dom::Document
*) {
301 nsresult
DynamicImage::GetHotspotX(int32_t* aX
) {
302 return Image::GetHotspotX(aX
);
305 nsresult
DynamicImage::GetHotspotY(int32_t* aY
) {
306 return Image::GetHotspotY(aY
);
310 } // namespace mozilla