1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 /* rendering object for replaced elements with image data */
8 #ifndef nsImageFrame_h___
9 #define nsImageFrame_h___
11 #include "nsSplittableFrame.h"
12 #include "nsIIOService.h"
13 #include "nsIObserver.h"
15 #include "imgINotificationObserver.h"
17 #include "nsDisplayList.h"
18 #include "imgIContainer.h"
19 #include "mozilla/Attributes.h"
20 #include "mozilla/DebugOnly.h"
21 #include "nsIReflowCallback.h"
22 #include "nsTObserverArray.h"
28 struct nsHTMLReflowState
;
29 class nsHTMLReflowMetrics
;
34 class nsImageLoadingContent
;
44 class nsImageListener
: public imgINotificationObserver
47 virtual ~nsImageListener();
50 explicit nsImageListener(nsImageFrame
*aFrame
);
53 NS_DECL_IMGINOTIFICATIONOBSERVER
55 void SetFrame(nsImageFrame
*frame
) { mFrame
= frame
; }
61 typedef nsSplittableFrame ImageFrameSuper
;
63 class nsImageFrame
: public ImageFrameSuper
,
64 public nsIReflowCallback
{
66 typedef mozilla::image::DrawResult DrawResult
;
67 typedef mozilla::layers::ImageContainer ImageContainer
;
68 typedef mozilla::layers::ImageLayer ImageLayer
;
69 typedef mozilla::layers::LayerManager LayerManager
;
71 NS_DECL_FRAMEARENA_HELPERS
73 explicit nsImageFrame(nsStyleContext
* aContext
);
75 NS_DECL_QUERYFRAME_TARGET(nsImageFrame
)
78 virtual void DestroyFrom(nsIFrame
* aDestructRoot
) MOZ_OVERRIDE
;
79 virtual void DidSetStyleContext(nsStyleContext
* aOldStyleContext
) MOZ_OVERRIDE
;
81 virtual void Init(nsIContent
* aContent
,
82 nsContainerFrame
* aParent
,
83 nsIFrame
* aPrevInFlow
) MOZ_OVERRIDE
;
84 virtual void BuildDisplayList(nsDisplayListBuilder
* aBuilder
,
85 const nsRect
& aDirtyRect
,
86 const nsDisplayListSet
& aLists
) MOZ_OVERRIDE
;
87 virtual nscoord
GetMinISize(nsRenderingContext
*aRenderingContext
) MOZ_OVERRIDE
;
88 virtual nscoord
GetPrefISize(nsRenderingContext
*aRenderingContext
) MOZ_OVERRIDE
;
89 virtual mozilla::IntrinsicSize
GetIntrinsicSize() MOZ_OVERRIDE
;
90 virtual nsSize
GetIntrinsicRatio() MOZ_OVERRIDE
;
91 virtual void Reflow(nsPresContext
* aPresContext
,
92 nsHTMLReflowMetrics
& aDesiredSize
,
93 const nsHTMLReflowState
& aReflowState
,
94 nsReflowStatus
& aStatus
) MOZ_OVERRIDE
;
96 virtual nsresult
GetContentForEvent(mozilla::WidgetEvent
* aEvent
,
97 nsIContent
** aContent
) MOZ_OVERRIDE
;
98 virtual nsresult
HandleEvent(nsPresContext
* aPresContext
,
99 mozilla::WidgetGUIEvent
* aEvent
,
100 nsEventStatus
* aEventStatus
) MOZ_OVERRIDE
;
101 virtual nsresult
GetCursor(const nsPoint
& aPoint
,
102 nsIFrame::Cursor
& aCursor
) MOZ_OVERRIDE
;
103 virtual nsresult
AttributeChanged(int32_t aNameSpaceID
,
105 int32_t aModType
) MOZ_OVERRIDE
;
108 virtual mozilla::a11y::AccType
AccessibleType() MOZ_OVERRIDE
;
111 virtual nsIAtom
* GetType() const MOZ_OVERRIDE
;
113 virtual bool IsFrameOfType(uint32_t aFlags
) const MOZ_OVERRIDE
115 return ImageFrameSuper::IsFrameOfType(aFlags
& ~(nsIFrame::eReplaced
));
118 #ifdef DEBUG_FRAME_DUMP
119 virtual nsresult
GetFrameName(nsAString
& aResult
) const MOZ_OVERRIDE
;
120 void List(FILE* out
= stderr
, const char* aPrefix
= "",
121 uint32_t aFlags
= 0) const MOZ_OVERRIDE
;
124 virtual LogicalSides
GetLogicalSkipSides(const nsHTMLReflowState
* aReflowState
= nullptr) const MOZ_OVERRIDE
;
126 nsresult
GetIntrinsicImageSize(nsSize
& aSize
);
128 static void ReleaseGlobals() {
130 gIconLoad
->Shutdown();
131 NS_RELEASE(gIconLoad
);
133 NS_IF_RELEASE(sIOService
);
136 nsresult
Notify(imgIRequest
*aRequest
, int32_t aType
, const nsIntRect
* aData
);
139 * Function to test whether aContent, which has aStyleContext as its style,
140 * should get an image frame. Note that this method is only used by the
141 * frame constructor; it's only here because it uses gIconLoad for now.
143 static bool ShouldCreateImageFrameFor(mozilla::dom::Element
* aElement
,
144 nsStyleContext
* aStyleContext
);
146 void DisplayAltFeedback(nsRenderingContext
& aRenderingContext
,
147 const nsRect
& aDirtyRect
,
148 imgIRequest
* aRequest
,
151 nsRect
GetInnerArea() const;
154 * Return a map element associated with this image.
156 mozilla::dom::Element
* GetMapElement() const;
159 * Return true if the image has associated image map.
161 bool HasImageMap() const { return mImageMap
|| GetMapElement(); }
163 nsImageMap
* GetImageMap();
164 nsImageMap
* GetExistingImageMap() const { return mImageMap
; }
166 virtual void AddInlineMinISize(nsRenderingContext
*aRenderingContext
,
167 InlineMinISizeData
*aData
) MOZ_OVERRIDE
;
169 void DisconnectMap();
172 virtual bool ReflowFinished() MOZ_OVERRIDE
;
173 virtual void ReflowCallbackCanceled() MOZ_OVERRIDE
;
176 virtual ~nsImageFrame();
178 void EnsureIntrinsicSizeAndRatio();
180 virtual mozilla::LogicalSize
181 ComputeSize(nsRenderingContext
*aRenderingContext
,
182 mozilla::WritingMode aWritingMode
,
183 const mozilla::LogicalSize
& aCBSize
,
184 nscoord aAvailableISize
,
185 const mozilla::LogicalSize
& aMargin
,
186 const mozilla::LogicalSize
& aBorder
,
187 const mozilla::LogicalSize
& aPadding
,
188 ComputeSizeFlags aFlags
) MOZ_OVERRIDE
;
190 bool IsServerImageMap();
192 void TranslateEventCoords(const nsPoint
& aPoint
,
193 nsIntPoint
& aResult
);
195 bool GetAnchorHREFTargetAndNode(nsIURI
** aHref
, nsString
& aTarget
,
198 * Computes the width of the string that fits into the available space
200 * @param in aLength total length of the string in PRUnichars
201 * @param in aMaxWidth width not to be exceeded
202 * @param out aMaxFit length of the string that fits within aMaxWidth
204 * @return width of the string that fits within aMaxWidth
206 nscoord
MeasureString(const char16_t
* aString
,
210 nsRenderingContext
& aContext
,
211 nsFontMetrics
& aFontMetrics
);
213 void DisplayAltText(nsPresContext
* aPresContext
,
214 nsRenderingContext
& aRenderingContext
,
215 const nsString
& aAltText
,
216 const nsRect
& aRect
);
218 DrawResult
PaintImage(nsRenderingContext
& aRenderingContext
, nsPoint aPt
,
219 const nsRect
& aDirtyRect
, imgIContainer
* aImage
,
223 friend class nsImageListener
;
224 friend class nsImageLoadingContent
;
226 nsresult
OnSizeAvailable(imgIRequest
* aRequest
, imgIContainer
* aImage
);
227 nsresult
OnFrameUpdate(imgIRequest
* aRequest
, const nsIntRect
* aRect
);
228 nsresult
OnLoadComplete(imgIRequest
* aRequest
, nsresult aStatus
);
231 * Notification that aRequest will now be the current request.
233 void NotifyNewCurrentRequest(imgIRequest
*aRequest
, nsresult aStatus
);
237 inline void SpecToURI(const nsAString
& aSpec
, nsIIOService
*aIOService
,
240 inline void GetLoadGroup(nsPresContext
*aPresContext
,
241 nsILoadGroup
**aLoadGroup
);
242 nscoord
GetContinuationOffset() const;
243 void GetDocumentCharacterSet(nsACString
& aCharset
) const;
244 bool ShouldDisplaySelection();
247 * Recalculate mIntrinsicSize from the image.
249 * @return whether aImage's size did _not_
250 * match our previous intrinsic size.
252 bool UpdateIntrinsicSize(imgIContainer
* aImage
);
255 * Recalculate mIntrinsicRatio from the image.
257 * @return whether aImage's ratio did _not_
258 * match our previous intrinsic ratio.
260 bool UpdateIntrinsicRatio(imgIContainer
* aImage
);
263 * This function calculates the transform for converting between
264 * source space & destination space. May fail if our image has a
265 * percent-valued or zero-valued height or width.
267 * @param aTransform The transform object to populate.
269 * @return whether we succeeded in creating the transform.
271 bool GetSourceToDestTransform(nsTransform2D
& aTransform
);
274 * Helper function to check whether the request corresponds to a load we don't
275 * care about. Most of the decoder observer methods will bail early if this
278 bool IsPendingLoad(imgIRequest
* aRequest
) const;
281 * Function to convert a dirty rect in the source image to a dirty
282 * rect for the image frame.
284 nsRect
SourceRectToDest(const nsIntRect
& aRect
);
287 * Triggers invalidation for both our image display item and, if appropriate,
288 * our alt-feedback display item.
290 * @param aLayerInvalidRect The area to invalidate in layer space. If null, the
291 * entire layer will be invalidated.
292 * @param aFrameInvalidRect The area to invalidate in frame space. If null, the
293 * entire frame will be invalidated.
295 void InvalidateSelf(const nsIntRect
* aLayerInvalidRect
,
296 const nsRect
* aFrameInvalidRect
);
298 nsImageMap
* mImageMap
;
300 nsCOMPtr
<imgINotificationObserver
> mListener
;
302 nsCOMPtr
<imgIContainer
> mImage
;
303 nsSize mComputedSize
;
304 mozilla::IntrinsicSize mIntrinsicSize
;
305 nsSize mIntrinsicRatio
;
307 bool mDisplayingIcon
;
308 bool mFirstFrameComplete
;
309 bool mReflowCallbackPosted
;
311 static nsIIOService
* sIOService
;
313 /* loading / broken image icon support */
315 // XXXbz this should be handled by the prescontext, I think; that
316 // way we would have a single iconload per mozilla session instead
317 // of one per document...
319 // LoadIcons: initiate the loading of the static icons used to show
320 // loading / broken images
321 nsresult
LoadIcons(nsPresContext
*aPresContext
);
322 nsresult
LoadIcon(const nsAString
& aSpec
, nsPresContext
*aPresContext
,
323 imgRequestProxy
**aRequest
);
325 class IconLoad MOZ_FINAL
: public nsIObserver
,
326 public imgINotificationObserver
{
327 // private class that wraps the data and logic needed for
328 // broken image and loading image icons
336 NS_DECL_IMGINOTIFICATIONOBSERVER
338 void AddIconObserver(nsImageFrame
*frame
) {
339 NS_ABORT_IF_FALSE(!mIconObservers
.Contains(frame
),
340 "Observer shouldn't aleady be in array");
341 mIconObservers
.AppendElement(frame
);
344 void RemoveIconObserver(nsImageFrame
*frame
) {
345 mozilla::DebugOnly
<bool> didRemove
= mIconObservers
.RemoveElement(frame
);
346 NS_ABORT_IF_FALSE(didRemove
, "Observer not in array");
353 nsTObserverArray
<nsImageFrame
*> mIconObservers
;
357 nsRefPtr
<imgRequestProxy
> mLoadingImage
;
358 nsRefPtr
<imgRequestProxy
> mBrokenImage
;
359 bool mPrefForceInlineAltText
;
360 bool mPrefShowPlaceholders
;
364 static IconLoad
* gIconLoad
; // singleton pattern: one LoadIcons instance is used
366 friend class nsDisplayImage
;
370 * Note that nsDisplayImage does not receive events. However, an image element
371 * is replaced content so its background will be z-adjacent to the
372 * image itself, and hence receive events just as if the image itself
375 class nsDisplayImage
: public nsDisplayImageContainer
{
377 typedef mozilla::layers::LayerManager LayerManager
;
379 nsDisplayImage(nsDisplayListBuilder
* aBuilder
, nsImageFrame
* aFrame
,
380 imgIContainer
* aImage
)
381 : nsDisplayImageContainer(aBuilder
, aFrame
), mImage(aImage
) {
382 MOZ_COUNT_CTOR(nsDisplayImage
);
384 virtual ~nsDisplayImage() {
385 MOZ_COUNT_DTOR(nsDisplayImage
);
388 virtual nsDisplayItemGeometry
* AllocateGeometry(nsDisplayListBuilder
* aBuilder
) MOZ_OVERRIDE
;
389 virtual void ComputeInvalidationRegion(nsDisplayListBuilder
* aBuilder
,
390 const nsDisplayItemGeometry
* aGeometry
,
391 nsRegion
* aInvalidRegion
) MOZ_OVERRIDE
;
392 virtual void Paint(nsDisplayListBuilder
* aBuilder
,
393 nsRenderingContext
* aCtx
) MOZ_OVERRIDE
;
396 * Returns an ImageContainer for this image if the image type
397 * supports it (TYPE_RASTER only).
399 virtual already_AddRefed
<ImageContainer
> GetContainer(LayerManager
* aManager
,
400 nsDisplayListBuilder
* aBuilder
) MOZ_OVERRIDE
;
402 gfxRect
GetDestRect();
404 virtual LayerState
GetLayerState(nsDisplayListBuilder
* aBuilder
,
405 LayerManager
* aManager
,
406 const ContainerLayerParameters
& aParameters
) MOZ_OVERRIDE
;
407 nsRect
GetBounds(bool* aSnap
)
411 nsImageFrame
* imageFrame
= static_cast<nsImageFrame
*>(mFrame
);
412 return imageFrame
->GetInnerArea() + ToReferenceFrame();
415 virtual nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
,
416 bool* aSnap
) MOZ_OVERRIDE
418 return GetBounds(aSnap
);
421 virtual nsRegion
GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
422 bool* aSnap
) MOZ_OVERRIDE
;
424 virtual already_AddRefed
<Layer
> BuildLayer(nsDisplayListBuilder
* aBuilder
,
425 LayerManager
* aManager
,
426 const ContainerLayerParameters
& aContainerParameters
) MOZ_OVERRIDE
;
429 * Configure an ImageLayer for this display item.
430 * Set the required filter and scaling transform.
432 virtual void ConfigureLayer(ImageLayer
* aLayer
, const nsIntPoint
& aOffset
) MOZ_OVERRIDE
;
434 NS_DISPLAY_DECL_NAME("Image", TYPE_IMAGE
)
436 nsCOMPtr
<imgIContainer
> mImage
;
439 #endif /* nsImageFrame_h___ */