layout/generic/nsImageFrame.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/layout/generic/nsImageFrame.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,408 @@
     1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +/* rendering object for replaced elements with bitmap image data */
    1.10 +
    1.11 +#ifndef nsImageFrame_h___
    1.12 +#define nsImageFrame_h___
    1.13 +
    1.14 +#include "nsSplittableFrame.h"
    1.15 +#include "nsIIOService.h"
    1.16 +#include "nsIObserver.h"
    1.17 +
    1.18 +#include "imgINotificationObserver.h"
    1.19 +
    1.20 +#include "nsDisplayList.h"
    1.21 +#include "imgIContainer.h"
    1.22 +#include "mozilla/Attributes.h"
    1.23 +#include "mozilla/DebugOnly.h"
    1.24 +#include "nsIReflowCallback.h"
    1.25 +
    1.26 +class nsImageMap;
    1.27 +class nsIURI;
    1.28 +class nsILoadGroup;
    1.29 +struct nsHTMLReflowState;
    1.30 +struct nsHTMLReflowMetrics;
    1.31 +class nsDisplayImage;
    1.32 +class nsPresContext;
    1.33 +class nsImageFrame;
    1.34 +class nsTransform2D;
    1.35 +class nsImageLoadingContent;
    1.36 +
    1.37 +namespace mozilla {
    1.38 +namespace layers {
    1.39 +  class ImageContainer;
    1.40 +  class ImageLayer;
    1.41 +  class LayerManager;
    1.42 +}
    1.43 +}
    1.44 +
    1.45 +class nsImageListener : public imgINotificationObserver
    1.46 +{
    1.47 +public:
    1.48 +  nsImageListener(nsImageFrame *aFrame);
    1.49 +  virtual ~nsImageListener();
    1.50 +
    1.51 +  NS_DECL_ISUPPORTS
    1.52 +  NS_DECL_IMGINOTIFICATIONOBSERVER
    1.53 +
    1.54 +  void SetFrame(nsImageFrame *frame) { mFrame = frame; }
    1.55 +
    1.56 +private:
    1.57 +  nsImageFrame *mFrame;
    1.58 +};
    1.59 +
    1.60 +typedef nsSplittableFrame ImageFrameSuper;
    1.61 +
    1.62 +class nsImageFrame : public ImageFrameSuper,
    1.63 +                     public nsIReflowCallback {
    1.64 +public:
    1.65 +  typedef mozilla::layers::ImageContainer ImageContainer;
    1.66 +  typedef mozilla::layers::ImageLayer ImageLayer;
    1.67 +  typedef mozilla::layers::LayerManager LayerManager;
    1.68 +
    1.69 +  NS_DECL_FRAMEARENA_HELPERS
    1.70 +
    1.71 +  nsImageFrame(nsStyleContext* aContext);
    1.72 +
    1.73 +  NS_DECL_QUERYFRAME_TARGET(nsImageFrame)
    1.74 +  NS_DECL_QUERYFRAME
    1.75 +
    1.76 +  virtual void DestroyFrom(nsIFrame* aDestructRoot) MOZ_OVERRIDE;
    1.77 +  virtual void Init(nsIContent*      aContent,
    1.78 +                    nsIFrame*        aParent,
    1.79 +                    nsIFrame*        aPrevInFlow) MOZ_OVERRIDE;
    1.80 +  virtual void BuildDisplayList(nsDisplayListBuilder*   aBuilder,
    1.81 +                                const nsRect&           aDirtyRect,
    1.82 +                                const nsDisplayListSet& aLists) MOZ_OVERRIDE;
    1.83 +  virtual nscoord GetMinWidth(nsRenderingContext *aRenderingContext) MOZ_OVERRIDE;
    1.84 +  virtual nscoord GetPrefWidth(nsRenderingContext *aRenderingContext) MOZ_OVERRIDE;
    1.85 +  virtual mozilla::IntrinsicSize GetIntrinsicSize() MOZ_OVERRIDE;
    1.86 +  virtual nsSize GetIntrinsicRatio() MOZ_OVERRIDE;
    1.87 +  virtual nsresult Reflow(nsPresContext*          aPresContext,
    1.88 +                          nsHTMLReflowMetrics&     aDesiredSize,
    1.89 +                          const nsHTMLReflowState& aReflowState,
    1.90 +                          nsReflowStatus&          aStatus) MOZ_OVERRIDE;
    1.91 +  
    1.92 +  virtual nsresult  GetContentForEvent(mozilla::WidgetEvent* aEvent,
    1.93 +                                       nsIContent** aContent) MOZ_OVERRIDE;
    1.94 +  virtual nsresult HandleEvent(nsPresContext* aPresContext,
    1.95 +                               mozilla::WidgetGUIEvent* aEvent,
    1.96 +                               nsEventStatus* aEventStatus) MOZ_OVERRIDE;
    1.97 +  virtual nsresult GetCursor(const nsPoint& aPoint,
    1.98 +                             nsIFrame::Cursor& aCursor) MOZ_OVERRIDE;
    1.99 +  virtual nsresult AttributeChanged(int32_t aNameSpaceID,
   1.100 +                                    nsIAtom* aAttribute,
   1.101 +                                    int32_t aModType) MOZ_OVERRIDE;
   1.102 +
   1.103 +#ifdef ACCESSIBILITY
   1.104 +  virtual mozilla::a11y::AccType AccessibleType() MOZ_OVERRIDE;
   1.105 +#endif
   1.106 +
   1.107 +  virtual nsIAtom* GetType() const MOZ_OVERRIDE;
   1.108 +
   1.109 +  virtual bool IsFrameOfType(uint32_t aFlags) const MOZ_OVERRIDE
   1.110 +  {
   1.111 +    return ImageFrameSuper::IsFrameOfType(aFlags & ~(nsIFrame::eReplaced));
   1.112 +  }
   1.113 +
   1.114 +#ifdef DEBUG_FRAME_DUMP
   1.115 +  virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE;
   1.116 +  void List(FILE* out = stderr, const char* aPrefix = "", 
   1.117 +            uint32_t aFlags = 0) const MOZ_OVERRIDE;
   1.118 +#endif
   1.119 +
   1.120 +  virtual int GetLogicalSkipSides(const nsHTMLReflowState* aReflowState = nullptr) const MOZ_OVERRIDE;
   1.121 +
   1.122 +  nsresult GetIntrinsicImageSize(nsSize& aSize);
   1.123 +
   1.124 +  static void ReleaseGlobals() {
   1.125 +    if (gIconLoad) {
   1.126 +      gIconLoad->Shutdown();
   1.127 +      NS_RELEASE(gIconLoad);
   1.128 +    }
   1.129 +    NS_IF_RELEASE(sIOService);
   1.130 +  }
   1.131 +
   1.132 +  nsresult Notify(imgIRequest *aRequest, int32_t aType, const nsIntRect* aData);
   1.133 +
   1.134 +  /**
   1.135 +   * Function to test whether aContent, which has aStyleContext as its style,
   1.136 +   * should get an image frame.  Note that this method is only used by the
   1.137 +   * frame constructor; it's only here because it uses gIconLoad for now.
   1.138 +   */
   1.139 +  static bool ShouldCreateImageFrameFor(mozilla::dom::Element* aElement,
   1.140 +                                          nsStyleContext* aStyleContext);
   1.141 +  
   1.142 +  void DisplayAltFeedback(nsRenderingContext& aRenderingContext,
   1.143 +                          const nsRect&        aDirtyRect,
   1.144 +                          imgIRequest*         aRequest,
   1.145 +                          nsPoint              aPt);
   1.146 +
   1.147 +  nsRect GetInnerArea() const;
   1.148 +
   1.149 +  /**
   1.150 +   * Return a map element associated with this image.
   1.151 +   */
   1.152 +  mozilla::dom::Element* GetMapElement() const
   1.153 +  {
   1.154 +    nsAutoString usemap;
   1.155 +    if (mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::usemap, usemap)) {
   1.156 +      return mContent->OwnerDoc()->FindImageMap(usemap);
   1.157 +    }
   1.158 +    return nullptr;
   1.159 +  }
   1.160 +
   1.161 +  /**
   1.162 +   * Return true if the image has associated image map.
   1.163 +   */
   1.164 +  bool HasImageMap() const { return mImageMap || GetMapElement(); }
   1.165 +
   1.166 +  nsImageMap* GetImageMap();
   1.167 +  nsImageMap* GetExistingImageMap() const { return mImageMap; }
   1.168 +
   1.169 +  virtual void AddInlineMinWidth(nsRenderingContext *aRenderingContext,
   1.170 +                                 InlineMinWidthData *aData) MOZ_OVERRIDE;
   1.171 +
   1.172 +  void DisconnectMap();
   1.173 +
   1.174 +  // nsIReflowCallback
   1.175 +  virtual bool ReflowFinished() MOZ_OVERRIDE;
   1.176 +  virtual void ReflowCallbackCanceled() MOZ_OVERRIDE;
   1.177 +
   1.178 +protected:
   1.179 +  virtual ~nsImageFrame();
   1.180 +
   1.181 +  void EnsureIntrinsicSizeAndRatio(nsPresContext* aPresContext);
   1.182 +
   1.183 +  virtual nsSize ComputeSize(nsRenderingContext *aRenderingContext,
   1.184 +                             nsSize aCBSize, nscoord aAvailableWidth,
   1.185 +                             nsSize aMargin, nsSize aBorder, nsSize aPadding,
   1.186 +                             uint32_t aFlags) MOZ_OVERRIDE;
   1.187 +
   1.188 +  bool IsServerImageMap();
   1.189 +
   1.190 +  void TranslateEventCoords(const nsPoint& aPoint,
   1.191 +                            nsIntPoint& aResult);
   1.192 +
   1.193 +  bool GetAnchorHREFTargetAndNode(nsIURI** aHref, nsString& aTarget,
   1.194 +                                    nsIContent** aNode);
   1.195 +  /**
   1.196 +   * Computes the width of the string that fits into the available space
   1.197 +   *
   1.198 +   * @param in aLength total length of the string in PRUnichars
   1.199 +   * @param in aMaxWidth width not to be exceeded
   1.200 +   * @param out aMaxFit length of the string that fits within aMaxWidth
   1.201 +   *            in PRUnichars
   1.202 +   * @return width of the string that fits within aMaxWidth
   1.203 +   */
   1.204 +  nscoord MeasureString(const char16_t*     aString,
   1.205 +                        int32_t              aLength,
   1.206 +                        nscoord              aMaxWidth,
   1.207 +                        uint32_t&            aMaxFit,
   1.208 +                        nsRenderingContext& aContext);
   1.209 +
   1.210 +  void DisplayAltText(nsPresContext*      aPresContext,
   1.211 +                      nsRenderingContext& aRenderingContext,
   1.212 +                      const nsString&      aAltText,
   1.213 +                      const nsRect&        aRect);
   1.214 +
   1.215 +  void PaintImage(nsRenderingContext& aRenderingContext, nsPoint aPt,
   1.216 +                  const nsRect& aDirtyRect, imgIContainer* aImage,
   1.217 +                  uint32_t aFlags);
   1.218 +
   1.219 +protected:
   1.220 +  friend class nsImageListener;
   1.221 +  friend class nsImageLoadingContent;
   1.222 +  nsresult OnStartContainer(imgIRequest *aRequest, imgIContainer *aImage);
   1.223 +  nsresult OnDataAvailable(imgIRequest *aRequest, const nsIntRect *rect);
   1.224 +  nsresult OnStopRequest(imgIRequest *aRequest,
   1.225 +                         nsresult aStatus);
   1.226 +  nsresult FrameChanged(imgIRequest *aRequest,
   1.227 +                        imgIContainer *aContainer);
   1.228 +  /**
   1.229 +   * Notification that aRequest will now be the current request.
   1.230 +   */
   1.231 +  void NotifyNewCurrentRequest(imgIRequest *aRequest, nsresult aStatus);
   1.232 +
   1.233 +private:
   1.234 +  // random helpers
   1.235 +  inline void SpecToURI(const nsAString& aSpec, nsIIOService *aIOService,
   1.236 +                        nsIURI **aURI);
   1.237 +
   1.238 +  inline void GetLoadGroup(nsPresContext *aPresContext,
   1.239 +                           nsILoadGroup **aLoadGroup);
   1.240 +  nscoord GetContinuationOffset() const;
   1.241 +  void GetDocumentCharacterSet(nsACString& aCharset) const;
   1.242 +  bool ShouldDisplaySelection();
   1.243 +
   1.244 +  /**
   1.245 +   * Recalculate mIntrinsicSize from the image.
   1.246 +   *
   1.247 +   * @return whether aImage's size did _not_
   1.248 +   *         match our previous intrinsic size.
   1.249 +   */
   1.250 +  bool UpdateIntrinsicSize(imgIContainer* aImage);
   1.251 +
   1.252 +  /**
   1.253 +   * Recalculate mIntrinsicRatio from the image.
   1.254 +   *
   1.255 +   * @return whether aImage's ratio did _not_
   1.256 +   *         match our previous intrinsic ratio.
   1.257 +   */
   1.258 +  bool UpdateIntrinsicRatio(imgIContainer* aImage);
   1.259 +
   1.260 +  /**
   1.261 +   * This function calculates the transform for converting between
   1.262 +   * source space & destination space. May fail if our image has a
   1.263 +   * percent-valued or zero-valued height or width.
   1.264 +   *
   1.265 +   * @param aTransform The transform object to populate.
   1.266 +   *
   1.267 +   * @return whether we succeeded in creating the transform.
   1.268 +   */
   1.269 +  bool GetSourceToDestTransform(nsTransform2D& aTransform);
   1.270 +
   1.271 +  /**
   1.272 +   * Helper functions to check whether the request or image container
   1.273 +   * corresponds to a load we don't care about.  Most of the decoder
   1.274 +   * observer methods will bail early if these return true.
   1.275 +   */
   1.276 +  bool IsPendingLoad(imgIRequest* aRequest) const;
   1.277 +  bool IsPendingLoad(imgIContainer* aContainer) const;
   1.278 +
   1.279 +  /**
   1.280 +   * Function to convert a dirty rect in the source image to a dirty
   1.281 +   * rect for the image frame.
   1.282 +   */
   1.283 +  nsRect SourceRectToDest(const nsIntRect & aRect);
   1.284 +
   1.285 +  nsImageMap*         mImageMap;
   1.286 +
   1.287 +  nsCOMPtr<imgINotificationObserver> mListener;
   1.288 +
   1.289 +  nsCOMPtr<imgIContainer> mImage;
   1.290 +  nsSize mComputedSize;
   1.291 +  mozilla::IntrinsicSize mIntrinsicSize;
   1.292 +  nsSize mIntrinsicRatio;
   1.293 +
   1.294 +  bool mDisplayingIcon;
   1.295 +  bool mFirstFrameComplete;
   1.296 +  bool mReflowCallbackPosted;
   1.297 +
   1.298 +  static nsIIOService* sIOService;
   1.299 +  
   1.300 +  /* loading / broken image icon support */
   1.301 +
   1.302 +  // XXXbz this should be handled by the prescontext, I think; that
   1.303 +  // way we would have a single iconload per mozilla session instead
   1.304 +  // of one per document...
   1.305 +
   1.306 +  // LoadIcons: initiate the loading of the static icons used to show
   1.307 +  // loading / broken images
   1.308 +  nsresult LoadIcons(nsPresContext *aPresContext);
   1.309 +  nsresult LoadIcon(const nsAString& aSpec, nsPresContext *aPresContext,
   1.310 +                    imgRequestProxy **aRequest);
   1.311 +
   1.312 +  class IconLoad MOZ_FINAL : public nsIObserver,
   1.313 +                             public imgINotificationObserver {
   1.314 +    // private class that wraps the data and logic needed for
   1.315 +    // broken image and loading image icons
   1.316 +  public:
   1.317 +    IconLoad();
   1.318 +
   1.319 +    void Shutdown();
   1.320 +
   1.321 +    NS_DECL_ISUPPORTS
   1.322 +    NS_DECL_NSIOBSERVER
   1.323 +    NS_DECL_IMGINOTIFICATIONOBSERVER
   1.324 +
   1.325 +    void AddIconObserver(nsImageFrame *frame) {
   1.326 +        NS_ABORT_IF_FALSE(!mIconObservers.Contains(frame),
   1.327 +                          "Observer shouldn't aleady be in array");
   1.328 +        mIconObservers.AppendElement(frame);
   1.329 +    }
   1.330 +
   1.331 +    void RemoveIconObserver(nsImageFrame *frame) {
   1.332 +      mozilla::DebugOnly<bool> didRemove = mIconObservers.RemoveElement(frame);
   1.333 +      NS_ABORT_IF_FALSE(didRemove, "Observer not in array");
   1.334 +    }
   1.335 +
   1.336 +  private:
   1.337 +    void GetPrefs();
   1.338 +    nsTObserverArray<nsImageFrame*> mIconObservers;
   1.339 +
   1.340 +
   1.341 +  public:
   1.342 +    nsRefPtr<imgRequestProxy> mLoadingImage;
   1.343 +    nsRefPtr<imgRequestProxy> mBrokenImage;
   1.344 +    bool             mPrefForceInlineAltText;
   1.345 +    bool             mPrefShowPlaceholders;
   1.346 +  };
   1.347 +  
   1.348 +public:
   1.349 +  static IconLoad* gIconLoad; // singleton pattern: one LoadIcons instance is used
   1.350 +  
   1.351 +  friend class nsDisplayImage;
   1.352 +};
   1.353 +
   1.354 +/**
   1.355 + * Note that nsDisplayImage does not receive events. However, an image element
   1.356 + * is replaced content so its background will be z-adjacent to the
   1.357 + * image itself, and hence receive events just as if the image itself
   1.358 + * received events.
   1.359 + */
   1.360 +class nsDisplayImage : public nsDisplayImageContainer {
   1.361 +public:
   1.362 +  typedef mozilla::layers::LayerManager LayerManager;
   1.363 +
   1.364 +  nsDisplayImage(nsDisplayListBuilder* aBuilder, nsImageFrame* aFrame,
   1.365 +                 imgIContainer* aImage)
   1.366 +    : nsDisplayImageContainer(aBuilder, aFrame), mImage(aImage) {
   1.367 +    MOZ_COUNT_CTOR(nsDisplayImage);
   1.368 +  }
   1.369 +  virtual ~nsDisplayImage() {
   1.370 +    MOZ_COUNT_DTOR(nsDisplayImage);
   1.371 +  }
   1.372 +  virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
   1.373 +                                         const nsDisplayItemGeometry* aGeometry,
   1.374 +                                         nsRegion* aInvalidRegion) MOZ_OVERRIDE;
   1.375 +  virtual void Paint(nsDisplayListBuilder* aBuilder,
   1.376 +                     nsRenderingContext* aCtx) MOZ_OVERRIDE;
   1.377 +
   1.378 +  /**
   1.379 +   * Returns an ImageContainer for this image if the image type
   1.380 +   * supports it (TYPE_RASTER only).
   1.381 +   */
   1.382 +  virtual already_AddRefed<ImageContainer> GetContainer(LayerManager* aManager,
   1.383 +                                                        nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE;
   1.384 +
   1.385 +  gfxRect GetDestRect();
   1.386 +
   1.387 +  virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
   1.388 +                                   LayerManager* aManager,
   1.389 +                                   const ContainerLayerParameters& aParameters) MOZ_OVERRIDE;
   1.390 +  virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE
   1.391 +  {
   1.392 +    *aSnap = true;
   1.393 +    return nsRect(ToReferenceFrame(), Frame()->GetSize());
   1.394 +  }
   1.395 +
   1.396 +  virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
   1.397 +                                             LayerManager* aManager,
   1.398 +                                             const ContainerLayerParameters& aContainerParameters) MOZ_OVERRIDE;
   1.399 +
   1.400 +  /**
   1.401 +   * Configure an ImageLayer for this display item.
   1.402 +   * Set the required filter and scaling transform.
   1.403 +   */
   1.404 +  virtual void ConfigureLayer(ImageLayer* aLayer, const nsIntPoint& aOffset) MOZ_OVERRIDE;
   1.405 +
   1.406 +  NS_DISPLAY_DECL_NAME("Image", TYPE_IMAGE)
   1.407 +private:
   1.408 +  nsCOMPtr<imgIContainer> mImage;
   1.409 +};
   1.410 +
   1.411 +#endif /* nsImageFrame_h___ */

mercurial