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/. */
5 
6 #include "DynamicImage.h"
7 #include "gfxPlatform.h"
8 #include "gfxUtils.h"
9 #include "mozilla/gfx/2D.h"
10 #include "mozilla/gfx/Logging.h"
11 #include "mozilla/RefPtr.h"
12 #include "ImageRegion.h"
13 #include "Orientation.h"
14 #include "SVGImageContext.h"
15 
16 #include "mozilla/MemoryReporting.h"
17 
18 using namespace mozilla;
19 using namespace mozilla::gfx;
20 using mozilla::layers::ImageContainer;
21 using mozilla::layers::LayerManager;
22 
23 namespace mozilla {
24 namespace image {
25 
26 // Inherited methods from Image.
27 
GetProgressTracker()28 already_AddRefed<ProgressTracker> DynamicImage::GetProgressTracker() {
29   return nullptr;
30 }
31 
SizeOfSourceWithComputedFallback(SizeOfState & aState) const32 size_t DynamicImage::SizeOfSourceWithComputedFallback(
33     SizeOfState& aState) const {
34   return 0;
35 }
36 
CollectSizeOfSurfaces(nsTArray<SurfaceMemoryCounter> & aCounters,MallocSizeOf aMallocSizeOf) const37 void DynamicImage::CollectSizeOfSurfaces(
38     nsTArray<SurfaceMemoryCounter>& aCounters,
39     MallocSizeOf aMallocSizeOf) const {
40   // We can't report anything useful because gfxDrawable doesn't expose this
41   // information.
42 }
43 
IncrementAnimationConsumers()44 void DynamicImage::IncrementAnimationConsumers() {}
45 
DecrementAnimationConsumers()46 void DynamicImage::DecrementAnimationConsumers() {}
47 
48 #ifdef DEBUG
GetAnimationConsumers()49 uint32_t DynamicImage::GetAnimationConsumers() { return 0; }
50 #endif
51 
OnImageDataAvailable(nsIRequest * aRequest,nsISupports * aContext,nsIInputStream * aInStr,uint64_t aSourceOffset,uint32_t aCount)52 nsresult DynamicImage::OnImageDataAvailable(nsIRequest* aRequest,
53                                             nsISupports* aContext,
54                                             nsIInputStream* aInStr,
55                                             uint64_t aSourceOffset,
56                                             uint32_t aCount) {
57   return NS_OK;
58 }
59 
OnImageDataComplete(nsIRequest * aRequest,nsISupports * aContext,nsresult aStatus,bool aLastPart)60 nsresult DynamicImage::OnImageDataComplete(nsIRequest* aRequest,
61                                            nsISupports* aContext,
62                                            nsresult aStatus, bool aLastPart) {
63   return NS_OK;
64 }
65 
OnSurfaceDiscarded(const SurfaceKey & aSurfaceKey)66 void DynamicImage::OnSurfaceDiscarded(const SurfaceKey& aSurfaceKey) {}
67 
SetInnerWindowID(uint64_t aInnerWindowId)68 void DynamicImage::SetInnerWindowID(uint64_t aInnerWindowId) {}
69 
InnerWindowID() const70 uint64_t DynamicImage::InnerWindowID() const { return 0; }
71 
HasError()72 bool DynamicImage::HasError() { return !mDrawable; }
73 
SetHasError()74 void DynamicImage::SetHasError() {}
75 
GetURI()76 ImageURL* DynamicImage::GetURI() { return nullptr; }
77 
78 // Methods inherited from XPCOM interfaces.
79 
NS_IMPL_ISUPPORTS(DynamicImage,imgIContainer)80 NS_IMPL_ISUPPORTS(DynamicImage, imgIContainer)
81 
82 NS_IMETHODIMP
83 DynamicImage::GetWidth(int32_t* aWidth) {
84   *aWidth = mDrawable->Size().width;
85   return NS_OK;
86 }
87 
88 NS_IMETHODIMP
GetHeight(int32_t * aHeight)89 DynamicImage::GetHeight(int32_t* aHeight) {
90   *aHeight = mDrawable->Size().height;
91   return NS_OK;
92 }
93 
GetNativeSizes(nsTArray<IntSize> & aNativeSizes) const94 nsresult DynamicImage::GetNativeSizes(nsTArray<IntSize>& aNativeSizes) const {
95   return NS_ERROR_NOT_IMPLEMENTED;
96 }
97 
GetNativeSizesLength() const98 size_t DynamicImage::GetNativeSizesLength() const { return 0; }
99 
100 NS_IMETHODIMP
GetIntrinsicSize(nsSize * aSize)101 DynamicImage::GetIntrinsicSize(nsSize* aSize) {
102   IntSize intSize(mDrawable->Size());
103   *aSize = nsSize(intSize.width, intSize.height);
104   return NS_OK;
105 }
106 
107 NS_IMETHODIMP
GetIntrinsicRatio(nsSize * aSize)108 DynamicImage::GetIntrinsicRatio(nsSize* aSize) {
109   IntSize intSize(mDrawable->Size());
110   *aSize = nsSize(intSize.width, intSize.height);
111   return NS_OK;
112 }
113 
NS_IMETHODIMP_(Orientation)114 NS_IMETHODIMP_(Orientation)
115 DynamicImage::GetOrientation() { return Orientation(); }
116 
117 NS_IMETHODIMP
GetType(uint16_t * aType)118 DynamicImage::GetType(uint16_t* aType) {
119   *aType = imgIContainer::TYPE_RASTER;
120   return NS_OK;
121 }
122 
123 NS_IMETHODIMP
GetAnimated(bool * aAnimated)124 DynamicImage::GetAnimated(bool* aAnimated) {
125   *aAnimated = false;
126   return NS_OK;
127 }
128 
NS_IMETHODIMP_(already_AddRefed<SourceSurface>)129 NS_IMETHODIMP_(already_AddRefed<SourceSurface>)
130 DynamicImage::GetFrame(uint32_t aWhichFrame, uint32_t aFlags) {
131   IntSize size(mDrawable->Size());
132   return GetFrameAtSize(IntSize(size.width, size.height), aWhichFrame, aFlags);
133 }
134 
NS_IMETHODIMP_(already_AddRefed<SourceSurface>)135 NS_IMETHODIMP_(already_AddRefed<SourceSurface>)
136 DynamicImage::GetFrameAtSize(const IntSize& aSize, uint32_t aWhichFrame,
137                              uint32_t aFlags) {
138   RefPtr<DrawTarget> dt =
139       gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(
140           aSize, SurfaceFormat::B8G8R8A8);
141   if (!dt || !dt->IsValid()) {
142     gfxWarning()
143         << "DynamicImage::GetFrame failed in CreateOffscreenContentDrawTarget";
144     return nullptr;
145   }
146   RefPtr<gfxContext> context = gfxContext::CreateOrNull(dt);
147   MOZ_ASSERT(context);  // already checked the draw target above
148 
149   auto result = Draw(context, aSize, ImageRegion::Create(aSize), aWhichFrame,
150                      SamplingFilter::POINT, Nothing(), aFlags, 1.0);
151 
152   return result == ImgDrawResult::SUCCESS ? dt->Snapshot() : nullptr;
153 }
154 
NS_IMETHODIMP_(bool)155 NS_IMETHODIMP_(bool)
156 DynamicImage::WillDrawOpaqueNow() { return false; }
157 
NS_IMETHODIMP_(bool)158 NS_IMETHODIMP_(bool)
159 DynamicImage::IsImageContainerAvailable(LayerManager* aManager,
160                                         uint32_t aFlags) {
161   return false;
162 }
163 
NS_IMETHODIMP_(already_AddRefed<ImageContainer>)164 NS_IMETHODIMP_(already_AddRefed<ImageContainer>)
165 DynamicImage::GetImageContainer(LayerManager* aManager, uint32_t aFlags) {
166   return nullptr;
167 }
168 
NS_IMETHODIMP_(bool)169 NS_IMETHODIMP_(bool)
170 DynamicImage::IsImageContainerAvailableAtSize(LayerManager* aManager,
171                                               const IntSize& aSize,
172                                               uint32_t aFlags) {
173   return false;
174 }
175 
NS_IMETHODIMP_(already_AddRefed<ImageContainer>)176 NS_IMETHODIMP_(already_AddRefed<ImageContainer>)
177 DynamicImage::GetImageContainerAtSize(LayerManager* aManager,
178                                       const IntSize& aSize,
179                                       const Maybe<SVGImageContext>& aSVGContext,
180                                       uint32_t aFlags) {
181   return nullptr;
182 }
183 
NS_IMETHODIMP_(ImgDrawResult)184 NS_IMETHODIMP_(ImgDrawResult)
185 DynamicImage::Draw(gfxContext* aContext, const nsIntSize& aSize,
186                    const ImageRegion& aRegion, uint32_t aWhichFrame,
187                    SamplingFilter aSamplingFilter,
188                    const Maybe<SVGImageContext>& aSVGContext, uint32_t aFlags,
189                    float aOpacity) {
190   MOZ_ASSERT(!aSize.IsEmpty(), "Unexpected empty size");
191 
192   IntSize drawableSize(mDrawable->Size());
193 
194   if (aSize == drawableSize) {
195     gfxUtils::DrawPixelSnapped(aContext, mDrawable, SizeDouble(drawableSize),
196                                aRegion, SurfaceFormat::B8G8R8A8,
197                                aSamplingFilter, aOpacity);
198     return ImgDrawResult::SUCCESS;
199   }
200 
201   gfxSize scale(double(aSize.width) / drawableSize.width,
202                 double(aSize.height) / drawableSize.height);
203 
204   ImageRegion region(aRegion);
205   region.Scale(1.0 / scale.width, 1.0 / scale.height);
206 
207   gfxContextMatrixAutoSaveRestore saveMatrix(aContext);
208   aContext->Multiply(gfxMatrix::Scaling(scale.width, scale.height));
209 
210   gfxUtils::DrawPixelSnapped(aContext, mDrawable, SizeDouble(drawableSize),
211                              region, SurfaceFormat::B8G8R8A8, aSamplingFilter,
212                              aOpacity);
213   return ImgDrawResult::SUCCESS;
214 }
215 
216 NS_IMETHODIMP
StartDecoding(uint32_t aFlags)217 DynamicImage::StartDecoding(uint32_t aFlags) { return NS_OK; }
218 
StartDecodingWithResult(uint32_t aFlags)219 bool DynamicImage::StartDecodingWithResult(uint32_t aFlags) { return true; }
220 
221 NS_IMETHODIMP
RequestDecodeForSize(const nsIntSize & aSize,uint32_t aFlags)222 DynamicImage::RequestDecodeForSize(const nsIntSize& aSize, uint32_t aFlags) {
223   return NS_OK;
224 }
225 
226 NS_IMETHODIMP
LockImage()227 DynamicImage::LockImage() { return NS_OK; }
228 
229 NS_IMETHODIMP
UnlockImage()230 DynamicImage::UnlockImage() { return NS_OK; }
231 
232 NS_IMETHODIMP
RequestDiscard()233 DynamicImage::RequestDiscard() { return NS_OK; }
234 
NS_IMETHODIMP_(void)235 NS_IMETHODIMP_(void)
236 DynamicImage::RequestRefresh(const mozilla::TimeStamp& aTime) {}
237 
238 NS_IMETHODIMP
GetAnimationMode(uint16_t * aAnimationMode)239 DynamicImage::GetAnimationMode(uint16_t* aAnimationMode) {
240   *aAnimationMode = kNormalAnimMode;
241   return NS_OK;
242 }
243 
244 NS_IMETHODIMP
SetAnimationMode(uint16_t aAnimationMode)245 DynamicImage::SetAnimationMode(uint16_t aAnimationMode) { return NS_OK; }
246 
247 NS_IMETHODIMP
ResetAnimation()248 DynamicImage::ResetAnimation() { return NS_OK; }
249 
NS_IMETHODIMP_(float)250 NS_IMETHODIMP_(float)
251 DynamicImage::GetFrameIndex(uint32_t aWhichFrame) { return 0; }
252 
NS_IMETHODIMP_(int32_t)253 NS_IMETHODIMP_(int32_t)
254 DynamicImage::GetFirstFrameDelay() { return 0; }
255 
NS_IMETHODIMP_(void)256 NS_IMETHODIMP_(void)
257 DynamicImage::SetAnimationStartTime(const mozilla::TimeStamp& aTime) {}
258 
OptimalImageSizeForDest(const gfxSize & aDest,uint32_t aWhichFrame,SamplingFilter aSamplingFilter,uint32_t aFlags)259 nsIntSize DynamicImage::OptimalImageSizeForDest(const gfxSize& aDest,
260                                                 uint32_t aWhichFrame,
261                                                 SamplingFilter aSamplingFilter,
262                                                 uint32_t aFlags) {
263   IntSize size(mDrawable->Size());
264   return nsIntSize(size.width, size.height);
265 }
266 
NS_IMETHODIMP_(nsIntRect)267 NS_IMETHODIMP_(nsIntRect)
268 DynamicImage::GetImageSpaceInvalidationRect(const nsIntRect& aRect) {
269   return aRect;
270 }
271 
Unwrap()272 already_AddRefed<imgIContainer> DynamicImage::Unwrap() {
273   nsCOMPtr<imgIContainer> self(this);
274   return self.forget();
275 }
276 
PropagateUseCounters(nsIDocument *)277 void DynamicImage::PropagateUseCounters(nsIDocument*) {
278   // No use counters.
279 }
280 
281 }  // namespace image
282 }  // namespace mozilla
283