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 #ifndef mozilla_image_VectorImage_h
7 #define mozilla_image_VectorImage_h
8 
9 #include "Image.h"
10 #include "nsIStreamListener.h"
11 #include "mozilla/MemoryReporting.h"
12 
13 class nsIRequest;
14 class gfxDrawable;
15 
16 namespace mozilla {
17 namespace image {
18 
19 struct SVGDrawingParameters;
20 class SVGDocumentWrapper;
21 class SVGRootRenderingObserver;
22 class SVGLoadEventListener;
23 class SVGParseCompleteListener;
24 
25 class VectorImage final : public ImageResource, public nsIStreamListener {
26  public:
27   NS_DECL_ISUPPORTS
28   NS_DECL_NSIREQUESTOBSERVER
29   NS_DECL_NSISTREAMLISTENER
30   NS_DECL_IMGICONTAINER
31 
32   // (no public constructor - use ImageFactory)
33 
34   // Methods inherited from Image
35   nsresult GetNativeSizes(nsTArray<gfx::IntSize>& aNativeSizes) const override;
36   size_t GetNativeSizesLength() const override;
37   virtual size_t SizeOfSourceWithComputedFallback(
38       SizeOfState& aState) const override;
39   virtual void CollectSizeOfSurfaces(nsTArray<SurfaceMemoryCounter>& aCounters,
40                                      MallocSizeOf aMallocSizeOf) const override;
41 
42   virtual nsresult OnImageDataAvailable(nsIRequest* aRequest,
43                                         nsISupports* aContext,
44                                         nsIInputStream* aInStr,
45                                         uint64_t aSourceOffset,
46                                         uint32_t aCount) override;
47   virtual nsresult OnImageDataComplete(nsIRequest* aRequest,
48                                        nsISupports* aContext, nsresult aResult,
49                                        bool aLastPart) override;
50 
51   virtual void OnSurfaceDiscarded(const SurfaceKey& aSurfaceKey) override;
52 
53   /**
54    * Callback for SVGRootRenderingObserver.
55    *
56    * This just sets a dirty flag that we check in VectorImage::RequestRefresh,
57    * which is called under the ticks of the refresh driver of any observing
58    * documents that we may have. Only then (after all animations in this image
59    * have been updated) do we send out "frame changed" notifications,
60    */
61   void InvalidateObserversOnNextRefreshDriverTick();
62 
63   // Callback for SVGParseCompleteListener.
64   void OnSVGDocumentParsed();
65 
66   // Callbacks for SVGLoadEventListener.
67   void OnSVGDocumentLoaded();
68   void OnSVGDocumentError();
69 
70   virtual void ReportUseCounters() override;
71 
72  protected:
73   explicit VectorImage(ImageURL* aURI = nullptr);
74   virtual ~VectorImage();
75 
76   virtual nsresult StartAnimation() override;
77   virtual nsresult StopAnimation() override;
78   virtual bool ShouldAnimate() override;
79 
80  private:
81   Tuple<ImgDrawResult, IntSize, RefPtr<SourceSurface>> GetFrameInternal(
82       const IntSize& aSize, const Maybe<SVGImageContext>& aSVGContext,
83       uint32_t aWhichFrame, uint32_t aFlags) override;
84 
85   IntSize GetImageContainerSize(layers::LayerManager* aManager,
86                                 const IntSize& aSize, uint32_t aFlags) override;
87 
88   /// Attempt to find a matching cached surface in the SurfaceCache.
89   already_AddRefed<SourceSurface> LookupCachedSurface(
90       const IntSize& aSize, const Maybe<SVGImageContext>& aSVGContext,
91       uint32_t aFlags);
92 
93   bool MaybeRestrictSVGContext(Maybe<SVGImageContext>& aNewSVGContext,
94                                const Maybe<SVGImageContext>& aSVGContext,
95                                uint32_t aFlags);
96 
97   /// Create a gfxDrawable which callbacks into the SVG document.
98   already_AddRefed<gfxDrawable> CreateSVGDrawable(
99       const SVGDrawingParameters& aParams);
100 
101   /// Rasterize the SVG into a surface. aWillCache will be set to whether or
102   /// not the new surface was put into the cache.
103   already_AddRefed<SourceSurface> CreateSurface(
104       const SVGDrawingParameters& aParams, gfxDrawable* aSVGDrawable,
105       bool& aWillCache);
106 
107   /// Send a frame complete notification if appropriate. Must be called only
108   /// after all drawing has been completed.
109   void SendFrameComplete(bool aDidCache, uint32_t aFlags);
110 
111   void Show(gfxDrawable* aDrawable, const SVGDrawingParameters& aParams);
112 
113   nsresult Init(const char* aMimeType, uint32_t aFlags);
114 
115   /**
116    * In catastrophic circumstances like a GPU driver crash, we may lose our
117    * surfaces even if they're locked. RecoverFromLossOfSurfaces discards all
118    * existing surfaces, allowing us to recover.
119    */
120   void RecoverFromLossOfSurfaces();
121 
122   void CancelAllListeners();
123   void SendInvalidationNotifications();
124 
125   RefPtr<SVGDocumentWrapper> mSVGDocumentWrapper;
126   RefPtr<SVGRootRenderingObserver> mRenderingObserver;
127   RefPtr<SVGLoadEventListener> mLoadEventListener;
128   RefPtr<SVGParseCompleteListener> mParseCompleteListener;
129 
130   /// Count of locks on this image (roughly correlated to visible instances).
131   uint32_t mLockCount;
132 
133   // Stored result from the Necko load of the image, which we save in
134   // OnImageDataComplete if the underlying SVG document isn't loaded. If we save
135   // this, we actually notify this progress (and clear this value) in
136   // OnSVGDocumentLoaded or OnSVGDocumentError.
137   Maybe<Progress> mLoadProgress;
138 
139   bool mIsInitialized;           // Have we been initialized?
140   bool mDiscardable;             // Are we discardable?
141   bool mIsFullyLoaded;           // Has the SVG document finished
142                                  // loading?
143   bool mIsDrawing;               // Are we currently drawing?
144   bool mHaveAnimations;          // Is our SVG content SMIL-animated?
145                                  // (Only set after mIsFullyLoaded.)
146   bool mHasPendingInvalidation;  // Invalidate observers next refresh
147                                  // driver tick.
148 
149   friend class ImageFactory;
150 };
151 
GetAnimationMode(uint16_t * aAnimationMode)152 inline NS_IMETHODIMP VectorImage::GetAnimationMode(uint16_t* aAnimationMode) {
153   return GetAnimationModeInternal(aAnimationMode);
154 }
155 
SetAnimationMode(uint16_t aAnimationMode)156 inline NS_IMETHODIMP VectorImage::SetAnimationMode(uint16_t aAnimationMode) {
157   return SetAnimationModeInternal(aAnimationMode);
158 }
159 
160 }  // namespace image
161 }  // namespace mozilla
162 
163 #endif  // mozilla_image_VectorImage_h
164