forked from mirrors/gecko-dev
		
	 1cdf344860
			
		
	
	
		1cdf344860
		
	
	
	
	
		
			
			This should be mostly straight-forward, since we have code for this anyways for image-set() and srcset. The only thing is that we were using floats for resolution, but since EXIF allows you to scale each axis separately, we now need to pass an image::Resolution instead. The main outstanding issue is the spec comment mentioned in the previous patch, about what happens if you have srcset/image-set and the image density specified together. For now I've implemented what the image-set() spec says, but this is subject to change before shipping of course. Differential Revision: https://phabricator.services.mozilla.com/D113265
		
			
				
	
	
		
			198 lines
		
	
	
	
		
			6.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			198 lines
		
	
	
	
		
			6.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 | |
| /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 | |
| /* This Source Code Form is subject to the terms of the Mozilla Public
 | |
|  * License, v. 2.0. If a copy of the MPL was not distributed with this
 | |
|  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 | |
| #ifndef nsImageBoxFrame_h___
 | |
| #define nsImageBoxFrame_h___
 | |
| 
 | |
| #include "mozilla/Attributes.h"
 | |
| #include "nsLeafBoxFrame.h"
 | |
| 
 | |
| #include "imgIRequest.h"
 | |
| #include "imgIContainer.h"
 | |
| #include "imgINotificationObserver.h"
 | |
| 
 | |
| class imgRequestProxy;
 | |
| class nsImageBoxFrame;
 | |
| 
 | |
| class nsDisplayXULImage;
 | |
| 
 | |
| namespace mozilla {
 | |
| class PresShell;
 | |
| }  // namespace mozilla
 | |
| 
 | |
| class nsImageBoxListener final : public imgINotificationObserver {
 | |
|  public:
 | |
|   explicit nsImageBoxListener(nsImageBoxFrame* frame);
 | |
| 
 | |
|   NS_DECL_ISUPPORTS
 | |
|   NS_DECL_IMGINOTIFICATIONOBSERVER
 | |
| 
 | |
|   void ClearFrame() { mFrame = nullptr; }
 | |
| 
 | |
|  private:
 | |
|   virtual ~nsImageBoxListener();
 | |
| 
 | |
|   nsImageBoxFrame* mFrame;
 | |
| };
 | |
| 
 | |
| class nsImageBoxFrame final : public nsLeafBoxFrame {
 | |
|  public:
 | |
|   typedef mozilla::image::ImgDrawResult ImgDrawResult;
 | |
|   typedef mozilla::layers::ImageContainer ImageContainer;
 | |
|   typedef mozilla::layers::LayerManager LayerManager;
 | |
| 
 | |
|   friend class nsDisplayXULImage;
 | |
|   NS_DECL_FRAMEARENA_HELPERS(nsImageBoxFrame)
 | |
|   NS_DECL_QUERYFRAME
 | |
| 
 | |
|   virtual nsSize GetXULPrefSize(nsBoxLayoutState& aBoxLayoutState) override;
 | |
|   virtual nsSize GetXULMinSize(nsBoxLayoutState& aBoxLayoutState) override;
 | |
|   virtual nscoord GetXULBoxAscent(nsBoxLayoutState& aBoxLayoutState) override;
 | |
|   virtual void MarkIntrinsicISizesDirty() override;
 | |
| 
 | |
|   void Notify(imgIRequest* aRequest, int32_t aType, const nsIntRect* aData);
 | |
| 
 | |
|   friend nsIFrame* NS_NewImageBoxFrame(mozilla::PresShell* aPresShell,
 | |
|                                        ComputedStyle* aStyle);
 | |
| 
 | |
|   virtual void Init(nsIContent* aContent, nsContainerFrame* aParent,
 | |
|                     nsIFrame* asPrevInFlow) override;
 | |
| 
 | |
|   virtual nsresult AttributeChanged(int32_t aNameSpaceID, nsAtom* aAttribute,
 | |
|                                     int32_t aModType) override;
 | |
| 
 | |
|   virtual void DidSetComputedStyle(ComputedStyle* aOldStyle) override;
 | |
| 
 | |
|   virtual void DestroyFrom(nsIFrame* aDestructRoot,
 | |
|                            PostDestroyData& aPostDestroyData) override;
 | |
| 
 | |
| #ifdef DEBUG_FRAME_DUMP
 | |
|   virtual nsresult GetFrameName(nsAString& aResult) const override;
 | |
| #endif
 | |
| 
 | |
|   /**
 | |
|    * Gets the image to be loaded from the current style. May be null if themed,
 | |
|    * or if not an url image.
 | |
|    *
 | |
|    * TODO(emilio): Maybe support list-style-image: linear-gradient() etc?
 | |
|    */
 | |
|   const mozilla::StyleImage* GetImageFromStyle(const ComputedStyle&) const;
 | |
|   const mozilla::StyleImage* GetImageFromStyle() const {
 | |
|     return GetImageFromStyle(*Style());
 | |
|   }
 | |
| 
 | |
|   mozilla::ImageResolution GetImageResolution() const;
 | |
| 
 | |
|   /**
 | |
|    * Update mUseSrcAttr from appropriate content attributes or from
 | |
|    * style, throw away the current image, and load the appropriate
 | |
|    * image.
 | |
|    * */
 | |
|   void UpdateImage();
 | |
| 
 | |
|   /**
 | |
|    * Update mLoadFlags from content attributes. Does not attempt to reload the
 | |
|    * image using the new load flags.
 | |
|    */
 | |
|   void UpdateLoadFlags();
 | |
| 
 | |
|   void RestartAnimation();
 | |
|   void StopAnimation();
 | |
| 
 | |
|   virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
 | |
|                                 const nsDisplayListSet& aLists) override;
 | |
| 
 | |
|   virtual ~nsImageBoxFrame();
 | |
| 
 | |
|   already_AddRefed<imgIContainer> GetImageContainerForPainting(
 | |
|       const nsPoint& aPt, ImgDrawResult& aDrawResult,
 | |
|       Maybe<nsPoint>& aAnchorPoint, nsRect& aDest);
 | |
| 
 | |
|   ImgDrawResult PaintImage(gfxContext& aRenderingContext,
 | |
|                            const nsRect& aDirtyRect, nsPoint aPt,
 | |
|                            uint32_t aFlags);
 | |
| 
 | |
|   ImgDrawResult CreateWebRenderCommands(
 | |
|       mozilla::wr::DisplayListBuilder& aBuilder,
 | |
|       mozilla::wr::IpcResourceUpdateQueue& aResources,
 | |
|       const mozilla::layers::StackingContextHelper& aSc,
 | |
|       mozilla::layers::RenderRootStateManager* aManager, nsDisplayItem* aItem,
 | |
|       nsPoint aPt, uint32_t aFlags);
 | |
| 
 | |
|   bool CanOptimizeToImageLayer();
 | |
| 
 | |
|   nsRect GetDestRect(const nsPoint& aOffset, Maybe<nsPoint>& aAnchorPoint);
 | |
| 
 | |
|  protected:
 | |
|   explicit nsImageBoxFrame(ComputedStyle* aStyle, nsPresContext* aPresContext);
 | |
| 
 | |
|   virtual void GetImageSize();
 | |
| 
 | |
|  private:
 | |
|   void OnSizeAvailable(imgIRequest* aRequest, imgIContainer* aImage);
 | |
|   void OnDecodeComplete(imgIRequest* aRequest);
 | |
|   void OnLoadComplete(imgIRequest* aRequest, nsresult aStatus);
 | |
|   void OnImageIsAnimated(imgIRequest* aRequest);
 | |
|   void OnFrameUpdate(imgIRequest* aRequest);
 | |
| 
 | |
|   nsRect mSubRect;  ///< If set, indicates that only the portion of the image
 | |
|                     ///< specified by the rect should be used.
 | |
|   nsSize mIntrinsicSize;
 | |
|   nsSize mImageSize;
 | |
| 
 | |
|   RefPtr<imgRequestProxy> mImageRequest;
 | |
|   nsCOMPtr<imgINotificationObserver> mListener;
 | |
| 
 | |
|   int32_t mLoadFlags;
 | |
| 
 | |
|   // Boolean variable to determine if the current image request has been
 | |
|   // registered with the refresh driver.
 | |
|   bool mRequestRegistered;
 | |
| 
 | |
|   bool mUseSrcAttr;  ///< Whether or not the image src comes from an attribute.
 | |
|   bool mSuppressStyleCheck;
 | |
| };  // class nsImageBoxFrame
 | |
| 
 | |
| class nsDisplayXULImage final : public nsDisplayImageContainer {
 | |
|  public:
 | |
|   nsDisplayXULImage(nsDisplayListBuilder* aBuilder, nsImageBoxFrame* aFrame)
 | |
|       : nsDisplayImageContainer(aBuilder, aFrame) {
 | |
|     MOZ_COUNT_CTOR(nsDisplayXULImage);
 | |
|   }
 | |
|   MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayXULImage)
 | |
| 
 | |
|   virtual bool CanOptimizeToImageLayer(LayerManager* aManager,
 | |
|                                        nsDisplayListBuilder* aBuilder) override;
 | |
|   virtual already_AddRefed<imgIContainer> GetImage() override;
 | |
|   virtual nsRect GetDestRect() const override;
 | |
|   virtual void UpdateDrawResult(
 | |
|       mozilla::image::ImgDrawResult aResult) override {
 | |
|     nsDisplayItemGenericImageGeometry::UpdateDrawResult(this, aResult);
 | |
|   }
 | |
|   virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
 | |
|                            bool* aSnap) const override {
 | |
|     *aSnap = true;
 | |
|     return nsRect(ToReferenceFrame(), Frame()->GetSize());
 | |
|   }
 | |
|   virtual nsDisplayItemGeometry* AllocateGeometry(
 | |
|       nsDisplayListBuilder* aBuilder) override;
 | |
|   virtual void ComputeInvalidationRegion(
 | |
|       nsDisplayListBuilder* aBuilder, const nsDisplayItemGeometry* aGeometry,
 | |
|       nsRegion* aInvalidRegion) const override;
 | |
|   // Doesn't handle HitTest because nsLeafBoxFrame already creates an
 | |
|   // event receiver for us
 | |
|   virtual void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
 | |
| 
 | |
|   virtual bool CreateWebRenderCommands(
 | |
|       mozilla::wr::DisplayListBuilder& aBuilder,
 | |
|       mozilla::wr::IpcResourceUpdateQueue& aResources,
 | |
|       const StackingContextHelper& aSc,
 | |
|       mozilla::layers::RenderRootStateManager* aManager,
 | |
|       nsDisplayListBuilder* aDisplayListBuilder) override;
 | |
| 
 | |
|   NS_DISPLAY_DECL_NAME("XULImage", TYPE_XUL_IMAGE)
 | |
| };
 | |
| 
 | |
| #endif /* nsImageBoxFrame_h___ */
 |