1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #ifndef nsImageBoxFrame_h___
7 #define nsImageBoxFrame_h___
8 
9 #include "mozilla/Attributes.h"
10 #include "nsLeafBoxFrame.h"
11 
12 #include "imgIRequest.h"
13 #include "imgIContainer.h"
14 #include "imgINotificationObserver.h"
15 
16 class imgRequestProxy;
17 class nsImageBoxFrame;
18 
19 class nsDisplayXULImage;
20 
21 namespace mozilla {
22 class PresShell;
23 }  // namespace mozilla
24 
25 class nsImageBoxListener final : public imgINotificationObserver {
26  public:
27   explicit nsImageBoxListener(nsImageBoxFrame* frame);
28 
29   NS_DECL_ISUPPORTS
30   NS_DECL_IMGINOTIFICATIONOBSERVER
31 
ClearFrame()32   void ClearFrame() { mFrame = nullptr; }
33 
34  private:
35   virtual ~nsImageBoxListener();
36 
37   nsImageBoxFrame* mFrame;
38 };
39 
40 class nsImageBoxFrame final : public nsLeafBoxFrame {
41  public:
42   typedef mozilla::image::ImgDrawResult ImgDrawResult;
43   typedef mozilla::layers::ImageContainer ImageContainer;
44   typedef mozilla::layers::LayerManager LayerManager;
45 
46   friend class nsDisplayXULImage;
47   NS_DECL_FRAMEARENA_HELPERS(nsImageBoxFrame)
48   NS_DECL_QUERYFRAME
49 
50   virtual nsSize GetXULPrefSize(nsBoxLayoutState& aBoxLayoutState) override;
51   virtual nsSize GetXULMinSize(nsBoxLayoutState& aBoxLayoutState) override;
52   virtual nscoord GetXULBoxAscent(nsBoxLayoutState& aBoxLayoutState) override;
53   virtual void MarkIntrinsicISizesDirty() override;
54 
55   void Notify(imgIRequest* aRequest, int32_t aType, const nsIntRect* aData);
56 
57   friend nsIFrame* NS_NewImageBoxFrame(mozilla::PresShell* aPresShell,
58                                        ComputedStyle* aStyle);
59 
60   virtual void Init(nsIContent* aContent, nsContainerFrame* aParent,
61                     nsIFrame* asPrevInFlow) override;
62 
63   virtual nsresult AttributeChanged(int32_t aNameSpaceID, nsAtom* aAttribute,
64                                     int32_t aModType) override;
65 
66   virtual void DidSetComputedStyle(ComputedStyle* aOldStyle) override;
67 
68   virtual void DestroyFrom(nsIFrame* aDestructRoot,
69                            PostDestroyData& aPostDestroyData) override;
70 
71 #ifdef DEBUG_FRAME_DUMP
72   virtual nsresult GetFrameName(nsAString& aResult) const override;
73 #endif
74 
75   /**
76    * Gets the image to be loaded from the current style. May be null if themed,
77    * or if not an url image.
78    *
79    * TODO(emilio): Maybe support list-style-image: linear-gradient() etc?
80    */
81   const mozilla::StyleImage* GetImageFromStyle(const ComputedStyle&) const;
GetImageFromStyle()82   const mozilla::StyleImage* GetImageFromStyle() const {
83     return GetImageFromStyle(*Style());
84   }
85 
86   mozilla::ImageResolution GetImageResolution() const;
87 
88   /**
89    * Update mUseSrcAttr from appropriate content attributes or from
90    * style, throw away the current image, and load the appropriate
91    * image.
92    * */
93   void UpdateImage();
94 
95   /**
96    * Update mLoadFlags from content attributes. Does not attempt to reload the
97    * image using the new load flags.
98    */
99   void UpdateLoadFlags();
100 
101   void RestartAnimation();
102   void StopAnimation();
103 
104   virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
105                                 const nsDisplayListSet& aLists) override;
106 
107   virtual ~nsImageBoxFrame();
108 
109   already_AddRefed<imgIContainer> GetImageContainerForPainting(
110       const nsPoint& aPt, ImgDrawResult& aDrawResult,
111       Maybe<nsPoint>& aAnchorPoint, nsRect& aDest);
112 
113   ImgDrawResult PaintImage(gfxContext& aRenderingContext,
114                            const nsRect& aDirtyRect, nsPoint aPt,
115                            uint32_t aFlags);
116 
117   ImgDrawResult CreateWebRenderCommands(
118       mozilla::wr::DisplayListBuilder& aBuilder,
119       mozilla::wr::IpcResourceUpdateQueue& aResources,
120       const mozilla::layers::StackingContextHelper& aSc,
121       mozilla::layers::RenderRootStateManager* aManager, nsDisplayItem* aItem,
122       nsPoint aPt, uint32_t aFlags);
123 
124   bool CanOptimizeToImageLayer();
125 
126   nsRect GetDestRect(const nsPoint& aOffset, Maybe<nsPoint>& aAnchorPoint);
127 
128  protected:
129   explicit nsImageBoxFrame(ComputedStyle* aStyle, nsPresContext* aPresContext);
130 
131   virtual void GetImageSize();
132 
133  private:
134   void OnSizeAvailable(imgIRequest* aRequest, imgIContainer* aImage);
135   void OnDecodeComplete(imgIRequest* aRequest);
136   void OnLoadComplete(imgIRequest* aRequest, nsresult aStatus);
137   void OnImageIsAnimated(imgIRequest* aRequest);
138   void OnFrameUpdate(imgIRequest* aRequest);
139 
140   nsRect mSubRect;  ///< If set, indicates that only the portion of the image
141                     ///< specified by the rect should be used.
142   nsSize mIntrinsicSize;
143   nsSize mImageSize;
144 
145   RefPtr<imgRequestProxy> mImageRequest;
146   nsCOMPtr<imgINotificationObserver> mListener;
147 
148   int32_t mLoadFlags;
149 
150   // Boolean variable to determine if the current image request has been
151   // registered with the refresh driver.
152   bool mRequestRegistered;
153 
154   bool mUseSrcAttr;  ///< Whether or not the image src comes from an attribute.
155   bool mSuppressStyleCheck;
156 };  // class nsImageBoxFrame
157 
158 class nsDisplayXULImage final : public nsDisplayImageContainer {
159  public:
nsDisplayXULImage(nsDisplayListBuilder * aBuilder,nsImageBoxFrame * aFrame)160   nsDisplayXULImage(nsDisplayListBuilder* aBuilder, nsImageBoxFrame* aFrame)
161       : nsDisplayImageContainer(aBuilder, aFrame) {
162     MOZ_COUNT_CTOR(nsDisplayXULImage);
163   }
164   MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayXULImage)
165 
166   virtual bool CanOptimizeToImageLayer(LayerManager* aManager,
167                                        nsDisplayListBuilder* aBuilder) override;
168   virtual already_AddRefed<imgIContainer> GetImage() override;
169   virtual nsRect GetDestRect() const override;
UpdateDrawResult(mozilla::image::ImgDrawResult aResult)170   virtual void UpdateDrawResult(
171       mozilla::image::ImgDrawResult aResult) override {
172     nsDisplayItemGenericImageGeometry::UpdateDrawResult(this, aResult);
173   }
GetBounds(nsDisplayListBuilder * aBuilder,bool * aSnap)174   virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
175                            bool* aSnap) const override {
176     *aSnap = true;
177     return nsRect(ToReferenceFrame(), Frame()->GetSize());
178   }
179   virtual nsDisplayItemGeometry* AllocateGeometry(
180       nsDisplayListBuilder* aBuilder) override;
181   virtual void ComputeInvalidationRegion(
182       nsDisplayListBuilder* aBuilder, const nsDisplayItemGeometry* aGeometry,
183       nsRegion* aInvalidRegion) const override;
184   // Doesn't handle HitTest because nsLeafBoxFrame already creates an
185   // event receiver for us
186   virtual void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
187 
188   virtual bool CreateWebRenderCommands(
189       mozilla::wr::DisplayListBuilder& aBuilder,
190       mozilla::wr::IpcResourceUpdateQueue& aResources,
191       const StackingContextHelper& aSc,
192       mozilla::layers::RenderRootStateManager* aManager,
193       nsDisplayListBuilder* aDisplayListBuilder) override;
194 
195   NS_DISPLAY_DECL_NAME("XULImage", TYPE_XUL_IMAGE)
196 };
197 
198 #endif /* nsImageBoxFrame_h___ */
199