1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is mozilla.org code.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * Netscape Communications Corporation.
19 : * Portions created by the Initial Developer are Copyright (C) 1998
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : * L. David Baron <dbaron@dbaron.org>, Mozilla Corporation
24 : *
25 : * Alternatively, the contents of this file may be used under the terms of
26 : * either of the GNU General Public License Version 2 or later (the "GPL"),
27 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 : * in which case the provisions of the GPL or the LGPL are applicable instead
29 : * of those above. If you wish to allow use of your version of this file only
30 : * under the terms of either the GPL or the LGPL, and not to allow others to
31 : * use your version of this file under the terms of the MPL, indicate your
32 : * decision by deleting the provisions above and replace them with the notice
33 : * and other provisions required by the GPL or the LGPL. If you do not delete
34 : * the provisions above, a recipient may use your version of this file under
35 : * the terms of any one of the MPL, the GPL or the LGPL.
36 : *
37 : * ***** END LICENSE BLOCK ***** */
38 :
39 : /* rendering object for replaced elements with bitmap image data */
40 :
41 : #ifndef nsImageFrame_h___
42 : #define nsImageFrame_h___
43 :
44 : #include "nsSplittableFrame.h"
45 : #include "nsIIOService.h"
46 : #include "nsIObserver.h"
47 :
48 : #include "nsStubImageDecoderObserver.h"
49 : #include "imgIDecoderObserver.h"
50 :
51 : #include "nsDisplayList.h"
52 : #include "imgIContainer.h"
53 :
54 : class nsIFrame;
55 : class nsImageMap;
56 : class nsIURI;
57 : class nsILoadGroup;
58 : struct nsHTMLReflowState;
59 : struct nsHTMLReflowMetrics;
60 : struct nsSize;
61 : class nsDisplayImage;
62 : class nsPresContext;
63 : class nsImageFrame;
64 : class nsTransform2D;
65 :
66 : namespace mozilla {
67 : namespace layers {
68 : class ImageContainer;
69 : class ImageLayer;
70 : class LayerManager;
71 : }
72 : }
73 :
74 : class nsImageListener : public nsStubImageDecoderObserver
75 : {
76 : public:
77 : nsImageListener(nsImageFrame *aFrame);
78 : virtual ~nsImageListener();
79 :
80 : NS_DECL_ISUPPORTS
81 : // imgIDecoderObserver (override nsStubImageDecoderObserver)
82 : NS_IMETHOD OnStartContainer(imgIRequest *aRequest, imgIContainer *aImage);
83 : NS_IMETHOD OnDataAvailable(imgIRequest *aRequest, bool aCurrentFrame,
84 : const nsIntRect *aRect);
85 : NS_IMETHOD OnStopDecode(imgIRequest *aRequest, nsresult status,
86 : const PRUnichar *statusArg);
87 : // imgIContainerObserver (override nsStubImageDecoderObserver)
88 : NS_IMETHOD FrameChanged(imgIRequest *aRequest,
89 : imgIContainer *aContainer,
90 : const nsIntRect *dirtyRect);
91 :
92 0 : void SetFrame(nsImageFrame *frame) { mFrame = frame; }
93 :
94 : private:
95 : nsImageFrame *mFrame;
96 : };
97 :
98 : #define IMAGE_SIZECONSTRAINED NS_FRAME_STATE_BIT(20)
99 : #define IMAGE_GOTINITIALREFLOW NS_FRAME_STATE_BIT(21)
100 :
101 : #define ImageFrameSuper nsSplittableFrame
102 :
103 : class nsImageFrame : public ImageFrameSuper {
104 : public:
105 : typedef mozilla::layers::ImageContainer ImageContainer;
106 : typedef mozilla::layers::ImageLayer ImageLayer;
107 : typedef mozilla::layers::LayerManager LayerManager;
108 :
109 : NS_DECL_FRAMEARENA_HELPERS
110 :
111 : nsImageFrame(nsStyleContext* aContext);
112 :
113 : NS_DECL_QUERYFRAME_TARGET(nsImageFrame)
114 : NS_DECL_QUERYFRAME
115 :
116 : virtual void DestroyFrom(nsIFrame* aDestructRoot);
117 : NS_IMETHOD Init(nsIContent* aContent,
118 : nsIFrame* aParent,
119 : nsIFrame* aPrevInFlow);
120 : NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder,
121 : const nsRect& aDirtyRect,
122 : const nsDisplayListSet& aLists);
123 : virtual nscoord GetMinWidth(nsRenderingContext *aRenderingContext);
124 : virtual nscoord GetPrefWidth(nsRenderingContext *aRenderingContext);
125 : virtual IntrinsicSize GetIntrinsicSize();
126 : virtual nsSize GetIntrinsicRatio();
127 : NS_IMETHOD Reflow(nsPresContext* aPresContext,
128 : nsHTMLReflowMetrics& aDesiredSize,
129 : const nsHTMLReflowState& aReflowState,
130 : nsReflowStatus& aStatus);
131 :
132 : NS_IMETHOD GetContentForEvent(nsEvent* aEvent,
133 : nsIContent** aContent);
134 : NS_IMETHOD HandleEvent(nsPresContext* aPresContext,
135 : nsGUIEvent* aEvent,
136 : nsEventStatus* aEventStatus);
137 : NS_IMETHOD GetCursor(const nsPoint& aPoint,
138 : nsIFrame::Cursor& aCursor);
139 : NS_IMETHOD AttributeChanged(PRInt32 aNameSpaceID,
140 : nsIAtom* aAttribute,
141 : PRInt32 aModType);
142 :
143 : #ifdef ACCESSIBILITY
144 : virtual already_AddRefed<nsAccessible> CreateAccessible();
145 : #endif
146 :
147 : virtual nsIAtom* GetType() const;
148 :
149 0 : virtual bool IsFrameOfType(PRUint32 aFlags) const
150 : {
151 0 : return ImageFrameSuper::IsFrameOfType(aFlags & ~(nsIFrame::eReplaced));
152 : }
153 :
154 : #ifdef DEBUG
155 : NS_IMETHOD GetFrameName(nsAString& aResult) const;
156 : NS_IMETHOD List(FILE* out, PRInt32 aIndent) const;
157 : #endif
158 :
159 : virtual PRIntn GetSkipSides() const;
160 :
161 : nsresult GetIntrinsicImageSize(nsSize& aSize);
162 :
163 1403 : static void ReleaseGlobals() {
164 1403 : if (gIconLoad) {
165 0 : gIconLoad->Shutdown();
166 0 : NS_RELEASE(gIconLoad);
167 : }
168 1403 : NS_IF_RELEASE(sIOService);
169 1403 : }
170 :
171 : /**
172 : * Function to test whether aContent, which has aStyleContext as its style,
173 : * should get an image frame. Note that this method is only used by the
174 : * frame constructor; it's only here because it uses gIconLoad for now.
175 : */
176 : static bool ShouldCreateImageFrameFor(mozilla::dom::Element* aElement,
177 : nsStyleContext* aStyleContext);
178 :
179 : void DisplayAltFeedback(nsRenderingContext& aRenderingContext,
180 : const nsRect& aDirtyRect,
181 : imgIRequest* aRequest,
182 : nsPoint aPt);
183 :
184 : nsRect GetInnerArea() const;
185 :
186 : nsImageMap* GetImageMap();
187 :
188 : virtual void AddInlineMinWidth(nsRenderingContext *aRenderingContext,
189 : InlineMinWidthData *aData);
190 :
191 : void DisconnectMap();
192 : protected:
193 : virtual ~nsImageFrame();
194 :
195 : void EnsureIntrinsicSizeAndRatio(nsPresContext* aPresContext);
196 :
197 : virtual nsSize ComputeSize(nsRenderingContext *aRenderingContext,
198 : nsSize aCBSize, nscoord aAvailableWidth,
199 : nsSize aMargin, nsSize aBorder, nsSize aPadding,
200 : bool aShrinkWrap);
201 :
202 : bool IsServerImageMap();
203 :
204 : void TranslateEventCoords(const nsPoint& aPoint,
205 : nsIntPoint& aResult);
206 :
207 : bool GetAnchorHREFTargetAndNode(nsIURI** aHref, nsString& aTarget,
208 : nsIContent** aNode);
209 : /**
210 : * Computes the width of the string that fits into the available space
211 : *
212 : * @param in aLength total length of the string in PRUnichars
213 : * @param in aMaxWidth width not to be exceeded
214 : * @param out aMaxFit length of the string that fits within aMaxWidth
215 : * in PRUnichars
216 : * @return width of the string that fits within aMaxWidth
217 : */
218 : nscoord MeasureString(const PRUnichar* aString,
219 : PRInt32 aLength,
220 : nscoord aMaxWidth,
221 : PRUint32& aMaxFit,
222 : nsRenderingContext& aContext);
223 :
224 : void DisplayAltText(nsPresContext* aPresContext,
225 : nsRenderingContext& aRenderingContext,
226 : const nsString& aAltText,
227 : const nsRect& aRect);
228 :
229 : void PaintImage(nsRenderingContext& aRenderingContext, nsPoint aPt,
230 : const nsRect& aDirtyRect, imgIContainer* aImage,
231 : PRUint32 aFlags);
232 :
233 : protected:
234 : friend class nsImageListener;
235 : nsresult OnStartContainer(imgIRequest *aRequest, imgIContainer *aImage);
236 : nsresult OnDataAvailable(imgIRequest *aRequest, bool aCurrentFrame,
237 : const nsIntRect *rect);
238 : nsresult OnStopDecode(imgIRequest *aRequest,
239 : nsresult aStatus,
240 : const PRUnichar *aStatusArg);
241 : nsresult FrameChanged(imgIRequest *aRequest,
242 : imgIContainer *aContainer,
243 : const nsIntRect *aDirtyRect);
244 :
245 : private:
246 : // random helpers
247 : inline void SpecToURI(const nsAString& aSpec, nsIIOService *aIOService,
248 : nsIURI **aURI);
249 :
250 : inline void GetLoadGroup(nsPresContext *aPresContext,
251 : nsILoadGroup **aLoadGroup);
252 : nscoord GetContinuationOffset() const;
253 : void GetDocumentCharacterSet(nsACString& aCharset) const;
254 : bool ShouldDisplaySelection();
255 :
256 : /**
257 : * Recalculate mIntrinsicSize from the image.
258 : *
259 : * @return whether aImage's size did _not_
260 : * match our previous intrinsic size.
261 : */
262 : bool UpdateIntrinsicSize(imgIContainer* aImage);
263 :
264 : /**
265 : * Recalculate mIntrinsicRatio from the image.
266 : *
267 : * @return whether aImage's ratio did _not_
268 : * match our previous intrinsic ratio.
269 : */
270 : bool UpdateIntrinsicRatio(imgIContainer* aImage);
271 :
272 : /**
273 : * This function calculates the transform for converting between
274 : * source space & destination space. May fail if our image has a
275 : * percent-valued or zero-valued height or width.
276 : *
277 : * @param aTransform The transform object to populate.
278 : *
279 : * @return whether we succeeded in creating the transform.
280 : */
281 : bool GetSourceToDestTransform(nsTransform2D& aTransform);
282 :
283 : /**
284 : * Helper functions to check whether the request or image container
285 : * corresponds to a load we don't care about. Most of the decoder
286 : * observer methods will bail early if these return true.
287 : */
288 : bool IsPendingLoad(imgIRequest* aRequest) const;
289 : bool IsPendingLoad(imgIContainer* aContainer) const;
290 :
291 : /**
292 : * Function to convert a dirty rect in the source image to a dirty
293 : * rect for the image frame.
294 : */
295 : nsRect SourceRectToDest(const nsIntRect & aRect);
296 :
297 : nsImageMap* mImageMap;
298 :
299 : nsCOMPtr<imgIDecoderObserver> mListener;
300 :
301 : nsSize mComputedSize;
302 : nsIFrame::IntrinsicSize mIntrinsicSize;
303 : nsSize mIntrinsicRatio;
304 :
305 : bool mDisplayingIcon;
306 :
307 : static nsIIOService* sIOService;
308 :
309 : /* loading / broken image icon support */
310 :
311 : // XXXbz this should be handled by the prescontext, I think; that
312 : // way we would have a single iconload per mozilla session instead
313 : // of one per document...
314 :
315 : // LoadIcons: initiate the loading of the static icons used to show
316 : // loading / broken images
317 : nsresult LoadIcons(nsPresContext *aPresContext);
318 : nsresult LoadIcon(const nsAString& aSpec, nsPresContext *aPresContext,
319 : imgIRequest **aRequest);
320 :
321 : class IconLoad : public nsIObserver,
322 0 : public imgIDecoderObserver {
323 : // private class that wraps the data and logic needed for
324 : // broken image and loading image icons
325 : public:
326 : IconLoad();
327 :
328 : void Shutdown();
329 :
330 : NS_DECL_ISUPPORTS
331 : NS_DECL_NSIOBSERVER
332 : NS_DECL_IMGICONTAINEROBSERVER
333 : NS_DECL_IMGIDECODEROBSERVER
334 :
335 0 : void AddIconObserver(nsImageFrame *frame) {
336 0 : NS_ABORT_IF_FALSE(!mIconObservers.Contains(frame),
337 : "Observer shouldn't aleady be in array");
338 0 : mIconObservers.AppendElement(frame);
339 0 : }
340 :
341 0 : void RemoveIconObserver(nsImageFrame *frame) {
342 : #ifdef DEBUG
343 : bool rv =
344 : #endif
345 0 : mIconObservers.RemoveElement(frame);
346 0 : NS_ABORT_IF_FALSE(rv, "Observer not in array");
347 0 : }
348 :
349 : private:
350 : void GetPrefs();
351 : nsTObserverArray<nsImageFrame*> mIconObservers;
352 :
353 :
354 : public:
355 : nsCOMPtr<imgIRequest> mLoadingImage;
356 : nsCOMPtr<imgIRequest> mBrokenImage;
357 : bool mPrefForceInlineAltText;
358 : bool mPrefShowPlaceholders;
359 : };
360 :
361 : public:
362 : static IconLoad* gIconLoad; // singleton pattern: one LoadIcons instance is used
363 :
364 : friend class nsDisplayImage;
365 : };
366 :
367 : /**
368 : * Note that nsDisplayImage does not receive events. However, an image element
369 : * is replaced content so its background will be z-adjacent to the
370 : * image itself, and hence receive events just as if the image itself
371 : * received events.
372 : */
373 : class nsDisplayImage : public nsDisplayItem {
374 : public:
375 : typedef mozilla::layers::ImageContainer ImageContainer;
376 : typedef mozilla::layers::ImageLayer ImageLayer;
377 : typedef mozilla::layers::LayerManager LayerManager;
378 :
379 0 : nsDisplayImage(nsDisplayListBuilder* aBuilder, nsImageFrame* aFrame,
380 : imgIContainer* aImage)
381 0 : : nsDisplayItem(aBuilder, aFrame), mImage(aImage) {
382 0 : MOZ_COUNT_CTOR(nsDisplayImage);
383 0 : }
384 0 : virtual ~nsDisplayImage() {
385 0 : MOZ_COUNT_DTOR(nsDisplayImage);
386 0 : }
387 : virtual void Paint(nsDisplayListBuilder* aBuilder,
388 : nsRenderingContext* aCtx);
389 :
390 : /**
391 : * Returns an ImageContainer for this image if the image type
392 : * supports it (TYPE_RASTER only).
393 : */
394 : already_AddRefed<ImageContainer> GetContainer();
395 :
396 : /**
397 : * Configure an ImageLayer for this display item.
398 : * Set the required filter and scaling transform.
399 : */
400 : void ConfigureLayer(ImageLayer* aLayer);
401 :
402 0 : NS_DISPLAY_DECL_NAME("Image", TYPE_IMAGE)
403 : private:
404 : nsCOMPtr<imgIContainer> mImage;
405 : };
406 :
407 : #endif /* nsImageFrame_h___ */
|