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 request to be loaded from the current style.
77    *
78    * May be null if themed.
79    */
80   imgRequestProxy* GetRequestFromStyle();
81 
82   /**
83    * Update mUseSrcAttr from appropriate content attributes or from
84    * style, throw away the current image, and load the appropriate
85    * image.
86    * */
87   void UpdateImage();
88 
89   /**
90    * Update mLoadFlags from content attributes. Does not attempt to reload the
91    * image using the new load flags.
92    */
93   void UpdateLoadFlags();
94 
95   void RestartAnimation();
96   void StopAnimation();
97 
98   virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
99                                 const nsDisplayListSet& aLists) override;
100 
101   virtual ~nsImageBoxFrame();
102 
103   already_AddRefed<imgIContainer> GetImageContainerForPainting(
104       const nsPoint& aPt, ImgDrawResult& aDrawResult,
105       Maybe<nsPoint>& aAnchorPoint, nsRect& aDest);
106 
107   ImgDrawResult PaintImage(gfxContext& aRenderingContext,
108                            const nsRect& aDirtyRect, nsPoint aPt,
109                            uint32_t aFlags);
110 
111   ImgDrawResult CreateWebRenderCommands(
112       mozilla::wr::DisplayListBuilder& aBuilder,
113       mozilla::wr::IpcResourceUpdateQueue& aResources,
114       const mozilla::layers::StackingContextHelper& aSc,
115       mozilla::layers::RenderRootStateManager* aManager, nsDisplayItem* aItem,
116       nsPoint aPt, uint32_t aFlags);
117 
118   bool CanOptimizeToImageLayer();
119 
120   nsRect GetDestRect(const nsPoint& aOffset, Maybe<nsPoint>& aAnchorPoint);
121 
122  protected:
123   explicit nsImageBoxFrame(ComputedStyle* aStyle, nsPresContext* aPresContext);
124 
125   virtual void GetImageSize();
126 
127  private:
128   void OnSizeAvailable(imgIRequest* aRequest, imgIContainer* aImage);
129   void OnDecodeComplete(imgIRequest* aRequest);
130   void OnLoadComplete(imgIRequest* aRequest, nsresult aStatus);
131   void OnImageIsAnimated(imgIRequest* aRequest);
132   void OnFrameUpdate(imgIRequest* aRequest);
133 
134   nsRect mSubRect;  ///< If set, indicates that only the portion of the image
135                     ///< specified by the rect should be used.
136   nsSize mIntrinsicSize;
137   nsSize mImageSize;
138 
139   RefPtr<imgRequestProxy> mImageRequest;
140   nsCOMPtr<imgINotificationObserver> mListener;
141 
142   int32_t mLoadFlags;
143 
144   // Boolean variable to determine if the current image request has been
145   // registered with the refresh driver.
146   bool mRequestRegistered;
147 
148   bool mUseSrcAttr;  ///< Whether or not the image src comes from an attribute.
149   bool mSuppressStyleCheck;
150 };  // class nsImageBoxFrame
151 
152 class nsDisplayXULImage final : public nsDisplayImageContainer {
153  public:
nsDisplayXULImage(nsDisplayListBuilder * aBuilder,nsImageBoxFrame * aFrame)154   nsDisplayXULImage(nsDisplayListBuilder* aBuilder, nsImageBoxFrame* aFrame)
155       : nsDisplayImageContainer(aBuilder, aFrame) {
156     MOZ_COUNT_CTOR(nsDisplayXULImage);
157   }
158   MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayXULImage)
159 
160   virtual bool CanOptimizeToImageLayer(LayerManager* aManager,
161                                        nsDisplayListBuilder* aBuilder) override;
162   virtual already_AddRefed<imgIContainer> GetImage() override;
163   virtual nsRect GetDestRect() const override;
UpdateDrawResult(mozilla::image::ImgDrawResult aResult)164   virtual void UpdateDrawResult(
165       mozilla::image::ImgDrawResult aResult) override {
166     nsDisplayItemGenericImageGeometry::UpdateDrawResult(this, aResult);
167   }
GetBounds(nsDisplayListBuilder * aBuilder,bool * aSnap)168   virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
169                            bool* aSnap) const override {
170     *aSnap = true;
171     return nsRect(ToReferenceFrame(), Frame()->GetSize());
172   }
173   virtual nsDisplayItemGeometry* AllocateGeometry(
174       nsDisplayListBuilder* aBuilder) override;
175   virtual void ComputeInvalidationRegion(
176       nsDisplayListBuilder* aBuilder, const nsDisplayItemGeometry* aGeometry,
177       nsRegion* aInvalidRegion) const override;
178   // Doesn't handle HitTest because nsLeafBoxFrame already creates an
179   // event receiver for us
180   virtual void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
181 
182   virtual bool CreateWebRenderCommands(
183       mozilla::wr::DisplayListBuilder& aBuilder,
184       mozilla::wr::IpcResourceUpdateQueue& aResources,
185       const StackingContextHelper& aSc,
186       mozilla::layers::RenderRootStateManager* aManager,
187       nsDisplayListBuilder* aDisplayListBuilder) override;
188 
189   NS_DISPLAY_DECL_NAME("XULImage", TYPE_XUL_IMAGE)
190 };
191 
192 #endif /* nsImageBoxFrame_h___ */
193