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___ */