1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set ts=2 sw=2 et tw=78: */
3 : /* ***** BEGIN LICENSE BLOCK *****
4 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 : *
6 : * The contents of this file are subject to the Mozilla Public License Version
7 : * 1.1 (the "License"); you may not use this file except in compliance with
8 : * the License. You may obtain a copy of the License at
9 : * http://www.mozilla.org/MPL/
10 : *
11 : * Software distributed under the License is distributed on an "AS IS" basis,
12 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 : * for the specific language governing rights and limitations under the
14 : * License.
15 : *
16 : * The Original Code is mozilla.org code.
17 : *
18 : * The Initial Developer of the Original Code is
19 : * Netscape Communications Corporation.
20 : * Portions created by the Initial Developer are Copyright (C) 1998
21 : * the Initial Developer. All Rights Reserved.
22 : *
23 : * Contributor(s):
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 : /* interface for all rendering objects */
40 :
41 : #ifndef nsIFrame_h___
42 : #define nsIFrame_h___
43 :
44 : #ifndef MOZILLA_INTERNAL_API
45 : #error This header/class should only be used within Mozilla code. It should not be used by extensions.
46 : #endif
47 :
48 : /* nsIFrame is in the process of being deCOMtaminated, i.e., this file is eventually
49 : going to be eliminated, and all callers will use nsFrame instead. At the moment
50 : we're midway through this process, so you will see inlined functions and member
51 : variables in this file. -dwh */
52 :
53 : #include <stdio.h>
54 : #include "nsQueryFrame.h"
55 : #include "nsEvent.h"
56 : #include "nsStyleStruct.h"
57 : #include "nsStyleContext.h"
58 : #include "nsIContent.h"
59 : #include "nsHTMLReflowMetrics.h"
60 : #include "gfxMatrix.h"
61 : #include "nsFrameList.h"
62 : #include "nsAlgorithm.h"
63 : #include "mozilla/layout/FrameChildList.h"
64 : #include "FramePropertyTable.h"
65 :
66 : /**
67 : * New rules of reflow:
68 : * 1. you get a WillReflow() followed by a Reflow() followed by a DidReflow() in order
69 : * (no separate pass over the tree)
70 : * 2. it's the parent frame's responsibility to size/position the child's view (not
71 : * the child frame's responsibility as it is today) during reflow (and before
72 : * sending the DidReflow() notification)
73 : * 3. positioning of child frames (and their views) is done on the way down the tree,
74 : * and sizing of child frames (and their views) on the way back up
75 : * 4. if you move a frame (outside of the reflow process, or after reflowing it),
76 : * then you must make sure that its view (or its child frame's views) are re-positioned
77 : * as well. It's reasonable to not position the view until after all reflowing the
78 : * entire line, for example, but the frame should still be positioned and sized (and
79 : * the view sized) during the reflow (i.e., before sending the DidReflow() notification)
80 : * 5. the view system handles moving of widgets, i.e., it's not our problem
81 : */
82 :
83 : struct nsHTMLReflowState;
84 : class nsHTMLReflowCommand;
85 :
86 : class nsIAtom;
87 : class nsPresContext;
88 : class nsIPresShell;
89 : class nsRenderingContext;
90 : class nsIView;
91 : class nsIWidget;
92 : class nsIDOMRange;
93 : class nsISelectionController;
94 : class nsBoxLayoutState;
95 : class nsBoxLayout;
96 : class nsILineIterator;
97 : #ifdef ACCESSIBILITY
98 : class nsAccessible;
99 : #endif
100 : class nsDisplayListBuilder;
101 : class nsDisplayListSet;
102 : class nsDisplayList;
103 : class gfxSkipChars;
104 : class gfxSkipCharsIterator;
105 : class gfxContext;
106 : class nsLineList_iterator;
107 : class nsAbsoluteContainingBlock;
108 :
109 : struct nsPeekOffsetStruct;
110 : struct nsPoint;
111 : struct nsRect;
112 : struct nsSize;
113 : struct nsMargin;
114 : struct CharacterDataChangeInfo;
115 :
116 : namespace mozilla {
117 : namespace layers {
118 : class Layer;
119 : }
120 : }
121 :
122 : typedef class nsIFrame nsIBox;
123 :
124 : /**
125 : * Indication of how the frame can be split. This is used when doing runaround
126 : * of floats, and when pulling up child frames from a next-in-flow.
127 : *
128 : * The choices are splittable, not splittable at all, and splittable in
129 : * a non-rectangular fashion. This last type only applies to block-level
130 : * elements, and indicates whether splitting can be used when doing runaround.
131 : * If you can split across page boundaries, but you expect each continuing
132 : * frame to be the same width then return frSplittable and not
133 : * frSplittableNonRectangular.
134 : *
135 : * @see #GetSplittableType()
136 : */
137 : typedef PRUint32 nsSplittableType;
138 :
139 : #define NS_FRAME_NOT_SPLITTABLE 0 // Note: not a bit!
140 : #define NS_FRAME_SPLITTABLE 0x1
141 : #define NS_FRAME_SPLITTABLE_NON_RECTANGULAR 0x3
142 :
143 : #define NS_FRAME_IS_SPLITTABLE(type)\
144 : (0 != ((type) & NS_FRAME_SPLITTABLE))
145 :
146 : #define NS_FRAME_IS_NOT_SPLITTABLE(type)\
147 : (0 == ((type) & NS_FRAME_SPLITTABLE))
148 :
149 : #define NS_INTRINSIC_WIDTH_UNKNOWN nscoord_MIN
150 :
151 : //----------------------------------------------------------------------
152 :
153 : /**
154 : * Frame state bits. Any bits not listed here are reserved for future
155 : * extensions, but must be stored by the frames.
156 : */
157 : typedef PRUint64 nsFrameState;
158 :
159 : #define NS_FRAME_STATE_BIT(n_) (nsFrameState(1) << (n_))
160 :
161 : #define NS_FRAME_IN_REFLOW NS_FRAME_STATE_BIT(0)
162 :
163 : // This bit is set when a frame is created. After it has been reflowed
164 : // once (during the DidReflow with a finished state) the bit is
165 : // cleared.
166 : #define NS_FRAME_FIRST_REFLOW NS_FRAME_STATE_BIT(1)
167 :
168 : // For a continuation frame, if this bit is set, then this a "fluid"
169 : // continuation, i.e., across a line boundary. Otherwise it's a "hard"
170 : // continuation, e.g. a bidi continuation.
171 : #define NS_FRAME_IS_FLUID_CONTINUATION NS_FRAME_STATE_BIT(2)
172 :
173 : // This bit is set whenever the frame has one or more associated
174 : // container layers.
175 : #define NS_FRAME_HAS_CONTAINER_LAYER NS_FRAME_STATE_BIT(3)
176 :
177 : // If this bit is set, then a reference to the frame is being held
178 : // elsewhere. The frame may want to send a notification when it is
179 : // destroyed to allow these references to be cleared.
180 : #define NS_FRAME_EXTERNAL_REFERENCE NS_FRAME_STATE_BIT(4)
181 :
182 : // If this bit is set, this frame or one of its descendants has a
183 : // percentage height that depends on an ancestor of this frame.
184 : // (Or it did at one point in the past, since we don't necessarily clear
185 : // the bit when it's no longer needed; it's an optimization.)
186 : #define NS_FRAME_CONTAINS_RELATIVE_HEIGHT NS_FRAME_STATE_BIT(5)
187 :
188 : // If this bit is set, then the frame corresponds to generated content
189 : #define NS_FRAME_GENERATED_CONTENT NS_FRAME_STATE_BIT(6)
190 :
191 : // If this bit is set the frame is a continuation that is holding overflow,
192 : // i.e. it is a next-in-flow created to hold overflow after the box's
193 : // height has ended. This means the frame should be a) at the top of the
194 : // page and b) invisible: no borders, zero height, ignored in margin
195 : // collapsing, etc. See nsContainerFrame.h
196 : #define NS_FRAME_IS_OVERFLOW_CONTAINER NS_FRAME_STATE_BIT(7)
197 :
198 : // If this bit is set, then the frame has been moved out of the flow,
199 : // e.g., it is absolutely positioned or floated
200 : #define NS_FRAME_OUT_OF_FLOW NS_FRAME_STATE_BIT(8)
201 :
202 : // This bit is available for re-use.
203 : //#define NS_FRAME_SELECTED_CONTENT NS_FRAME_STATE_BIT(9)
204 :
205 : // If this bit is set, then the frame is dirty and needs to be reflowed.
206 : // This bit is set when the frame is first created.
207 : // This bit is cleared by DidReflow after the required call to Reflow has
208 : // finished.
209 : // Do not set this bit yourself if you plan to pass the frame to
210 : // nsIPresShell::FrameNeedsReflow. Pass the right arguments instead.
211 : #define NS_FRAME_IS_DIRTY NS_FRAME_STATE_BIT(10)
212 :
213 : // If this bit is set then the frame is too deep in the frame tree, and
214 : // we'll stop updating it and its children, to prevent stack overflow
215 : // and the like.
216 : #define NS_FRAME_TOO_DEEP_IN_FRAME_TREE NS_FRAME_STATE_BIT(11)
217 :
218 : // If this bit is set, either:
219 : // 1. the frame has children that have either NS_FRAME_IS_DIRTY or
220 : // NS_FRAME_HAS_DIRTY_CHILDREN, or
221 : // 2. the frame has had descendants removed.
222 : // It means that Reflow needs to be called, but that Reflow will not
223 : // do as much work as it would if NS_FRAME_IS_DIRTY were set.
224 : // This bit is cleared by DidReflow after the required call to Reflow has
225 : // finished.
226 : // Do not set this bit yourself if you plan to pass the frame to
227 : // nsIPresShell::FrameNeedsReflow. Pass the right arguments instead.
228 : #define NS_FRAME_HAS_DIRTY_CHILDREN NS_FRAME_STATE_BIT(12)
229 :
230 : // If this bit is set, the frame has an associated view
231 : #define NS_FRAME_HAS_VIEW NS_FRAME_STATE_BIT(13)
232 :
233 : // If this bit is set, the frame was created from anonymous content.
234 : #define NS_FRAME_INDEPENDENT_SELECTION NS_FRAME_STATE_BIT(14)
235 :
236 : // If this bit is set, the frame is "special" (lame term, I know),
237 : // which means that it is part of the mangled frame hierarchy that
238 : // results when an inline has been split because of a nested block.
239 : // See the comments in nsCSSFrameConstructor::ConstructInline for
240 : // more details.
241 : #define NS_FRAME_IS_SPECIAL NS_FRAME_STATE_BIT(15)
242 :
243 : // If this bit is set, the frame may have a transform that it applies
244 : // to its coordinate system (e.g. CSS transform, SVG foreignObject).
245 : // This is used primarily in GetTransformMatrix to optimize for the
246 : // common case.
247 : #define NS_FRAME_MAY_BE_TRANSFORMED NS_FRAME_STATE_BIT(16)
248 :
249 : #ifdef IBMBIDI
250 : // If this bit is set, the frame itself is a bidi continuation,
251 : // or is incomplete (its next sibling is a bidi continuation)
252 : #define NS_FRAME_IS_BIDI NS_FRAME_STATE_BIT(17)
253 : #endif
254 :
255 : // If this bit is set the frame has descendant with a view
256 : #define NS_FRAME_HAS_CHILD_WITH_VIEW NS_FRAME_STATE_BIT(18)
257 :
258 : // If this bit is set, then reflow may be dispatched from the current
259 : // frame instead of the root frame.
260 : #define NS_FRAME_REFLOW_ROOT NS_FRAME_STATE_BIT(19)
261 :
262 : // Bits 20-31 and 60-63 of the frame state are reserved for implementations.
263 : #define NS_FRAME_IMPL_RESERVED nsFrameState(0xF0000000FFF00000)
264 : #define NS_FRAME_RESERVED ~NS_FRAME_IMPL_RESERVED
265 :
266 : // This bit is set on floats whose parent does not contain their
267 : // placeholder. This can happen for two reasons: (1) the float was
268 : // split, and this piece is the continuation, or (2) the entire float
269 : // didn't fit on the page.
270 : #define NS_FRAME_IS_PUSHED_FLOAT NS_FRAME_STATE_BIT(32)
271 :
272 : // This bit acts as a loop flag for recursive paint server drawing.
273 : #define NS_FRAME_DRAWING_AS_PAINTSERVER NS_FRAME_STATE_BIT(33)
274 :
275 : // Frame or one of its (cross-doc) descendants may have the
276 : // NS_FRAME_HAS_CONTAINER_LAYER bit.
277 : #define NS_FRAME_HAS_CONTAINER_LAYER_DESCENDANT NS_FRAME_STATE_BIT(34)
278 :
279 : // Frame's overflow area was clipped by the 'clip' property.
280 : #define NS_FRAME_HAS_CLIP NS_FRAME_STATE_BIT(35)
281 :
282 : // Frame is a display root and the retained layer tree needs to be updated
283 : // at the next paint via display list construction.
284 : // Only meaningful for display roots, so we don't really need a global state
285 : // bit; we could free up this bit with a little extra complexity.
286 : #define NS_FRAME_UPDATE_LAYER_TREE NS_FRAME_STATE_BIT(36)
287 :
288 : // Frame can accept absolutely positioned children.
289 : #define NS_FRAME_HAS_ABSPOS_CHILDREN NS_FRAME_STATE_BIT(37)
290 :
291 : // A display item for this frame has been painted as part of a ThebesLayer.
292 : #define NS_FRAME_PAINTED_THEBES NS_FRAME_STATE_BIT(38)
293 :
294 : // Frame is or is a descendant of something with a fixed height, unless that
295 : // ancestor is a body or html element, and has no closer ancestor that is
296 : // overflow:auto or overflow:scroll.
297 : #define NS_FRAME_IN_CONSTRAINED_HEIGHT NS_FRAME_STATE_BIT(39)
298 :
299 : // This is only set during painting
300 : #define NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO NS_FRAME_STATE_BIT(40)
301 :
302 : // Is this frame a container for font size inflation, i.e., is it a
303 : // frame whose width is used to determine the inflation factor for
304 : // everything whose nearest ancestor container for this frame?
305 : #define NS_FRAME_FONT_INFLATION_CONTAINER NS_FRAME_STATE_BIT(41)
306 :
307 : // Box layout bits
308 : #define NS_STATE_IS_HORIZONTAL NS_FRAME_STATE_BIT(22)
309 : #define NS_STATE_IS_DIRECTION_NORMAL NS_FRAME_STATE_BIT(31)
310 :
311 : // Helper macros
312 : #define NS_SUBTREE_DIRTY(_frame) \
313 : (((_frame)->GetStateBits() & \
314 : (NS_FRAME_IS_DIRTY | NS_FRAME_HAS_DIRTY_CHILDREN)) != 0)
315 :
316 : //----------------------------------------------------------------------
317 :
318 : enum nsSelectionAmount {
319 : eSelectCharacter = 0, // a single Unicode character;
320 : // do not use this (prefer Cluster) unless you
321 : // are really sure it's what you want
322 : eSelectCluster = 1, // a grapheme cluster: this is usually the right
323 : // choice for movement or selection by "character"
324 : // as perceived by the user
325 : eSelectWord = 2,
326 : eSelectLine = 3, // previous drawn line in flow.
327 : eSelectBeginLine = 4,
328 : eSelectEndLine = 5,
329 : eSelectNoAmount = 6, // just bounce back current offset.
330 : eSelectParagraph = 7, // select a "paragraph"
331 : eSelectWordNoSpace = 8 // select a "word" without selecting the following
332 : // space, no matter what the default platform
333 : // behavior is
334 : };
335 :
336 : enum nsDirection {
337 : eDirNext = 0,
338 : eDirPrevious= 1
339 : };
340 :
341 : enum nsSpread {
342 : eSpreadNone = 0,
343 : eSpreadAcross = 1,
344 : eSpreadDown = 2
345 : };
346 :
347 : // Carried out margin flags
348 : #define NS_CARRIED_TOP_MARGIN_IS_AUTO 0x1
349 : #define NS_CARRIED_BOTTOM_MARGIN_IS_AUTO 0x2
350 :
351 : //----------------------------------------------------------------------
352 :
353 : /**
354 : * Reflow status returned by the reflow methods. There are three
355 : * completion statuses, represented by two bit flags.
356 : *
357 : * NS_FRAME_COMPLETE means the frame is fully complete.
358 : *
359 : * NS_FRAME_NOT_COMPLETE bit flag means the frame does not map all its
360 : * content, and that the parent frame should create a continuing frame.
361 : * If this bit isn't set it means the frame does map all its content.
362 : * This bit is mutually exclusive with NS_FRAME_OVERFLOW_INCOMPLETE.
363 : *
364 : * NS_FRAME_OVERFLOW_INCOMPLETE bit flag means that the frame has
365 : * overflow that is not complete, but its own box is complete.
366 : * (This happens when content overflows a fixed-height box.)
367 : * The reflower should place and size the frame and continue its reflow,
368 : * but needs to create an overflow container as a continuation for this
369 : * frame. See nsContainerFrame.h for more information.
370 : * This bit is mutually exclusive with NS_FRAME_NOT_COMPLETE.
371 : *
372 : * Please use the SET macro for handling
373 : * NS_FRAME_NOT_COMPLETE and NS_FRAME_OVERFLOW_INCOMPLETE.
374 : *
375 : * NS_FRAME_REFLOW_NEXTINFLOW bit flag means that the next-in-flow is
376 : * dirty, and also needs to be reflowed. This status only makes sense
377 : * for a frame that is not complete, i.e. you wouldn't set both
378 : * NS_FRAME_COMPLETE and NS_FRAME_REFLOW_NEXTINFLOW.
379 : *
380 : * The low 8 bits of the nsReflowStatus are reserved for future extensions;
381 : * the remaining 24 bits are zero (and available for extensions; however
382 : * API's that accept/return nsReflowStatus must not receive/return any
383 : * extension bits).
384 : *
385 : * @see #Reflow()
386 : */
387 : typedef PRUint32 nsReflowStatus;
388 :
389 : #define NS_FRAME_COMPLETE 0 // Note: not a bit!
390 : #define NS_FRAME_NOT_COMPLETE 0x1
391 : #define NS_FRAME_REFLOW_NEXTINFLOW 0x2
392 : #define NS_FRAME_OVERFLOW_INCOMPLETE 0x4
393 :
394 : #define NS_FRAME_IS_COMPLETE(status) \
395 : (0 == ((status) & NS_FRAME_NOT_COMPLETE))
396 :
397 : #define NS_FRAME_IS_NOT_COMPLETE(status) \
398 : (0 != ((status) & NS_FRAME_NOT_COMPLETE))
399 :
400 : #define NS_FRAME_OVERFLOW_IS_INCOMPLETE(status) \
401 : (0 != ((status) & NS_FRAME_OVERFLOW_INCOMPLETE))
402 :
403 : #define NS_FRAME_IS_FULLY_COMPLETE(status) \
404 : (NS_FRAME_IS_COMPLETE(status) && !NS_FRAME_OVERFLOW_IS_INCOMPLETE(status))
405 :
406 : // These macros set or switch incompete statuses without touching th
407 : // NS_FRAME_REFLOW_NEXTINFLOW bit.
408 : #define NS_FRAME_SET_INCOMPLETE(status) \
409 : status = (status & ~NS_FRAME_OVERFLOW_INCOMPLETE) | NS_FRAME_NOT_COMPLETE
410 :
411 : #define NS_FRAME_SET_OVERFLOW_INCOMPLETE(status) \
412 : status = (status & ~NS_FRAME_NOT_COMPLETE) | NS_FRAME_OVERFLOW_INCOMPLETE
413 :
414 : // This macro tests to see if an nsReflowStatus is an error value
415 : // or just a regular return value
416 : #define NS_IS_REFLOW_ERROR(_status) (PRInt32(_status) < 0)
417 :
418 : /**
419 : * Extensions to the reflow status bits defined by nsIFrameReflow
420 : */
421 :
422 : // This bit is set, when a break is requested. This bit is orthogonal
423 : // to the nsIFrame::nsReflowStatus completion bits.
424 : #define NS_INLINE_BREAK 0x0100
425 :
426 : // When a break is requested, this bit when set indicates that the
427 : // break should occur after the frame just reflowed; when the bit is
428 : // clear the break should occur before the frame just reflowed.
429 : #define NS_INLINE_BREAK_BEFORE 0x0000
430 : #define NS_INLINE_BREAK_AFTER 0x0200
431 :
432 : // The type of break requested can be found in these bits.
433 : #define NS_INLINE_BREAK_TYPE_MASK 0xF000
434 :
435 : // Set when a break was induced by completion of a first-letter
436 : #define NS_INLINE_BREAK_FIRST_LETTER_COMPLETE 0x10000
437 :
438 : //----------------------------------------
439 : // Macros that use those bits
440 :
441 : #define NS_INLINE_IS_BREAK(_status) \
442 : (0 != ((_status) & NS_INLINE_BREAK))
443 :
444 : #define NS_INLINE_IS_BREAK_AFTER(_status) \
445 : (0 != ((_status) & NS_INLINE_BREAK_AFTER))
446 :
447 : #define NS_INLINE_IS_BREAK_BEFORE(_status) \
448 : (NS_INLINE_BREAK == ((_status) & (NS_INLINE_BREAK|NS_INLINE_BREAK_AFTER)))
449 :
450 : #define NS_INLINE_GET_BREAK_TYPE(_status) (((_status) >> 12) & 0xF)
451 :
452 : #define NS_INLINE_MAKE_BREAK_TYPE(_type) ((_type) << 12)
453 :
454 : // Construct a line-break-before status. Note that there is no
455 : // completion status for a line-break before because we *know* that
456 : // the frame will be reflowed later and hence it's current completion
457 : // status doesn't matter.
458 : #define NS_INLINE_LINE_BREAK_BEFORE() \
459 : (NS_INLINE_BREAK | NS_INLINE_BREAK_BEFORE | \
460 : NS_INLINE_MAKE_BREAK_TYPE(NS_STYLE_CLEAR_LINE))
461 :
462 : // Take a completion status and add to it the desire to have a
463 : // line-break after. For this macro we do need the completion status
464 : // because the user of the status will need to know whether to
465 : // continue the frame or not.
466 : #define NS_INLINE_LINE_BREAK_AFTER(_completionStatus) \
467 : ((_completionStatus) | NS_INLINE_BREAK | NS_INLINE_BREAK_AFTER | \
468 : NS_INLINE_MAKE_BREAK_TYPE(NS_STYLE_CLEAR_LINE))
469 :
470 : // A frame is "truncated" if the part of the frame before the first
471 : // possible break point was unable to fit in the available vertical
472 : // space. Therefore, the entire frame should be moved to the next page.
473 : // A frame that begins at the top of the page must never be "truncated".
474 : // Doing so would likely cause an infinite loop.
475 : #define NS_FRAME_TRUNCATED 0x0010
476 : #define NS_FRAME_IS_TRUNCATED(status) \
477 : (0 != ((status) & NS_FRAME_TRUNCATED))
478 : #define NS_FRAME_SET_TRUNCATION(status, aReflowState, aMetrics) \
479 : aReflowState.SetTruncated(aMetrics, &status);
480 :
481 : // Merge the incompleteness, truncation and NS_FRAME_REFLOW_NEXTINFLOW
482 : // status from aSecondary into aPrimary.
483 : void NS_MergeReflowStatusInto(nsReflowStatus* aPrimary,
484 : nsReflowStatus aSecondary);
485 :
486 : //----------------------------------------------------------------------
487 :
488 : /**
489 : * DidReflow status values.
490 : */
491 : typedef bool nsDidReflowStatus;
492 :
493 : #define NS_FRAME_REFLOW_NOT_FINISHED false
494 : #define NS_FRAME_REFLOW_FINISHED true
495 :
496 : /**
497 : * When there is no scrollable overflow rect, the visual overflow rect
498 : * may be stored as four 1-byte deltas each strictly LESS THAN 0xff, for
499 : * the four edges of the rectangle, or the four bytes may be read as a
500 : * single 32-bit "overflow-rect type" value including at least one 0xff
501 : * byte as an indicator that the value does NOT represent four deltas.
502 : * If all four deltas are zero, this means that no overflow rect has
503 : * actually been set (this is the initial state of newly-created frames).
504 : */
505 : #define NS_FRAME_OVERFLOW_DELTA_MAX 0xfe // max delta we can store
506 :
507 : #define NS_FRAME_OVERFLOW_NONE 0x00000000 // there are no overflow rects;
508 : // code relies on this being
509 : // the all-zero value
510 :
511 : #define NS_FRAME_OVERFLOW_LARGE 0x000000ff // overflow is stored as a
512 : // separate rect property
513 :
514 : //----------------------------------------------------------------------
515 :
516 : /**
517 : * A frame in the layout model. This interface is supported by all frame
518 : * objects.
519 : *
520 : * Frames can have multiple child lists: the default child list
521 : * (referred to as the <i>principal</i> child list, and additional named
522 : * child lists. There is an ordering of frames within a child list, but
523 : * there is no order defined between frames in different child lists of
524 : * the same parent frame.
525 : *
526 : * Frames are NOT reference counted. Use the Destroy() member function
527 : * to destroy a frame. The lifetime of the frame hierarchy is bounded by the
528 : * lifetime of the presentation shell which owns the frames.
529 : *
530 : * nsIFrame is a private Gecko interface. If you are not Gecko then you
531 : * should not use it. If you're not in layout, then you won't be able to
532 : * link to many of the functions defined here. Too bad.
533 : *
534 : * If you're not in layout but you must call functions in here, at least
535 : * restrict yourself to calling virtual methods, which won't hurt you as badly.
536 : */
537 : class nsIFrame : public nsQueryFrame
538 : {
539 : public:
540 : typedef mozilla::FramePropertyDescriptor FramePropertyDescriptor;
541 : typedef mozilla::FrameProperties FrameProperties;
542 : typedef mozilla::layers::Layer Layer;
543 : typedef mozilla::layout::FrameChildList ChildList;
544 : typedef mozilla::layout::FrameChildListID ChildListID;
545 : typedef mozilla::layout::FrameChildListIDs ChildListIDs;
546 : typedef mozilla::layout::FrameChildListIterator ChildListIterator;
547 : typedef mozilla::layout::FrameChildListArrayIterator ChildListArrayIterator;
548 :
549 : NS_DECL_QUERYFRAME_TARGET(nsIFrame)
550 :
551 0 : nsPresContext* PresContext() const {
552 0 : return GetStyleContext()->GetRuleNode()->GetPresContext();
553 : }
554 :
555 : /**
556 : * Called to initialize the frame. This is called immediately after creating
557 : * the frame.
558 : *
559 : * If the frame is a continuing frame, then aPrevInFlow indicates the previous
560 : * frame (the frame that was split).
561 : *
562 : * If you want a view associated with your frame, you should create the view
563 : * now.
564 : *
565 : * @param aContent the content object associated with the frame
566 : * @param aGeometricParent the geometric parent frame
567 : * @param aContentParent the content parent frame
568 : * @param aContext the style context associated with the frame
569 : * @param aPrevInFlow the prev-in-flow frame
570 : */
571 : NS_IMETHOD Init(nsIContent* aContent,
572 : nsIFrame* aParent,
573 : nsIFrame* aPrevInFlow) = 0;
574 :
575 : /**
576 : * Destroys this frame and each of its child frames (recursively calls
577 : * Destroy() for each child). If this frame is a first-continuation, this
578 : * also removes the frame from the primary frame map and clears undisplayed
579 : * content for its content node.
580 : * If the frame is a placeholder, it also ensures the out-of-flow frame's
581 : * removal and destruction.
582 : */
583 : void Destroy() { DestroyFrom(this); }
584 :
585 : protected:
586 : /**
587 : * Return true if the frame is part of a Selection.
588 : * Helper method to implement the public IsSelected() API.
589 : */
590 : virtual bool IsFrameSelected() const;
591 :
592 : /**
593 : * Implements Destroy(). Do not call this directly except from within a
594 : * DestroyFrom() implementation.
595 : *
596 : * @note This will always be called, so it is not necessary to override
597 : * Destroy() in subclasses of nsFrame, just DestroyFrom().
598 : *
599 : * @param aDestructRoot is the root of the subtree being destroyed
600 : */
601 : virtual void DestroyFrom(nsIFrame* aDestructRoot) = 0;
602 : friend class nsFrameList; // needed to pass aDestructRoot through to children
603 : friend class nsLineBox; // needed to pass aDestructRoot through to children
604 : public:
605 :
606 : /**
607 : * Called to set the initial list of frames. This happens after the frame
608 : * has been initialized.
609 : *
610 : * This is only called once for a given child list, and won't be called
611 : * at all for child lists with no initial list of frames.
612 : *
613 : * @param aListID the child list identifier.
614 : * @param aChildList list of child frames. Each of the frames has its
615 : * NS_FRAME_IS_DIRTY bit set. Must not be empty.
616 : * This method cannot handle the child list returned by
617 : * GetAbsoluteListID().
618 : * @return NS_ERROR_INVALID_ARG if there is no child list with the specified
619 : * name,
620 : * NS_ERROR_UNEXPECTED if the frame is an atomic frame or if the
621 : * initial list of frames has already been set for that child list,
622 : * NS_OK otherwise. In this case, SetInitialChildList empties out
623 : * aChildList in the process of moving the frames over to its own
624 : * child list.
625 : * @see #Init()
626 : */
627 : NS_IMETHOD SetInitialChildList(ChildListID aListID,
628 : nsFrameList& aChildList) = 0;
629 :
630 : /**
631 : * This method is responsible for appending frames to the frame
632 : * list. The implementation should append the frames to the specified
633 : * child list and then generate a reflow command.
634 : *
635 : * @param aListID the child list identifier.
636 : * @param aFrameList list of child frames to append. Each of the frames has
637 : * its NS_FRAME_IS_DIRTY bit set. Must not be empty.
638 : * @return NS_ERROR_INVALID_ARG if there is no child list with the specified
639 : * name,
640 : * NS_ERROR_UNEXPECTED if the frame is an atomic frame,
641 : * NS_OK otherwise. In this case, AppendFrames empties out
642 : * aChildList in the process of moving the frames over to its own
643 : * child list.
644 : */
645 : NS_IMETHOD AppendFrames(ChildListID aListID,
646 : nsFrameList& aFrameList) = 0;
647 :
648 : /**
649 : * This method is responsible for inserting frames into the frame
650 : * list. The implementation should insert the new frames into the specified
651 : * child list and then generate a reflow command.
652 : *
653 : * @param aListID the child list identifier.
654 : * @param aPrevFrame the frame to insert frames <b>after</b>
655 : * @param aFrameList list of child frames to insert <b>after</b> aPrevFrame.
656 : * Each of the frames has its NS_FRAME_IS_DIRTY bit set
657 : * @return NS_ERROR_INVALID_ARG if there is no child list with the specified
658 : * name,
659 : * NS_ERROR_UNEXPECTED if the frame is an atomic frame,
660 : * NS_OK otherwise. In this case, InsertFrames empties out
661 : * aChildList in the process of moving the frames over to its own
662 : * child list.
663 : */
664 : NS_IMETHOD InsertFrames(ChildListID aListID,
665 : nsIFrame* aPrevFrame,
666 : nsFrameList& aFrameList) = 0;
667 :
668 : /**
669 : * This method is responsible for removing a frame in the frame
670 : * list. The implementation should do something with the removed frame
671 : * and then generate a reflow command. The implementation is responsible
672 : * for destroying aOldFrame (the caller mustn't destroy aOldFrame).
673 : *
674 : * @param aListID the child list identifier.
675 : * @param aOldFrame the frame to remove
676 : * @return NS_ERROR_INVALID_ARG if there is no child list with the specified
677 : * name,
678 : * NS_ERROR_FAILURE if the child frame is not in the specified
679 : * child list,
680 : * NS_ERROR_UNEXPECTED if the frame is an atomic frame,
681 : * NS_OK otherwise
682 : */
683 : NS_IMETHOD RemoveFrame(ChildListID aListID,
684 : nsIFrame* aOldFrame) = 0;
685 :
686 : /**
687 : * Get the content object associated with this frame. Does not add a reference.
688 : */
689 0 : nsIContent* GetContent() const { return mContent; }
690 :
691 : /**
692 : * Get the frame that should be the parent for the frames of child elements
693 : * May return nsnull during reflow
694 : */
695 0 : virtual nsIFrame* GetContentInsertionFrame() { return this; }
696 :
697 : /**
698 : * Get the frame that should be scrolled if the content associated
699 : * with this frame is targeted for scrolling. For frames implementing
700 : * nsIScrollableFrame this will return the frame itself. For frames
701 : * like nsTextControlFrame that contain a scrollframe, will return
702 : * that scrollframe.
703 : */
704 0 : virtual nsIScrollableFrame* GetScrollTargetFrame() { return nsnull; }
705 :
706 : /**
707 : * Get the offsets of the frame. most will be 0,0
708 : *
709 : */
710 : NS_IMETHOD GetOffsets(PRInt32 &start, PRInt32 &end) const = 0;
711 :
712 : /**
713 : * Reset the offsets when splitting frames during Bidi reordering
714 : *
715 : */
716 0 : virtual void AdjustOffsetsForBidi(PRInt32 aStart, PRInt32 aEnd) {}
717 :
718 : /**
719 : * Get the style context associated with this frame.
720 : *
721 : */
722 0 : nsStyleContext* GetStyleContext() const { return mStyleContext; }
723 : void SetStyleContext(nsStyleContext* aContext)
724 : {
725 : if (aContext != mStyleContext) {
726 : nsStyleContext* oldStyleContext = mStyleContext;
727 : mStyleContext = aContext;
728 : if (aContext) {
729 : aContext->AddRef();
730 : DidSetStyleContext(oldStyleContext);
731 : }
732 : if (oldStyleContext)
733 : oldStyleContext->Release();
734 : }
735 : }
736 :
737 : void SetStyleContextWithoutNotification(nsStyleContext* aContext)
738 : {
739 : if (aContext != mStyleContext) {
740 : if (mStyleContext)
741 : mStyleContext->Release();
742 : mStyleContext = aContext;
743 : if (aContext) {
744 : aContext->AddRef();
745 : }
746 : }
747 : }
748 :
749 : // Style post processing hook
750 : // Attention: the old style context is the one we're forgetting,
751 : // and hence possibly completely bogus for GetStyle* purposes.
752 : // Use PeekStyleData instead.
753 : virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext) = 0;
754 :
755 : /**
756 : * Get the style data associated with this frame. This returns a
757 : * const style struct pointer that should never be modified. See
758 : * |nsIStyleContext::GetStyleData| for more information.
759 : *
760 : * The use of the typesafe functions below is preferred to direct use
761 : * of this function.
762 : */
763 : virtual const void* GetStyleDataExternal(nsStyleStructID aSID) const = 0;
764 :
765 : /**
766 : * Define typesafe getter functions for each style struct by
767 : * preprocessing the list of style structs. These functions are the
768 : * preferred way to get style data. The macro creates functions like:
769 : * const nsStyleBorder* GetStyleBorder();
770 : * const nsStyleColor* GetStyleColor();
771 : */
772 :
773 : #ifdef _IMPL_NS_LAYOUT
774 : #define STYLE_STRUCT(name_, checkdata_cb_, ctor_args_) \
775 : const nsStyle##name_ * GetStyle##name_ () const { \
776 : NS_ASSERTION(mStyleContext, "No style context found!"); \
777 : return mStyleContext->GetStyle##name_ (); \
778 : }
779 : #else
780 : #define STYLE_STRUCT(name_, checkdata_cb_, ctor_args_) \
781 : const nsStyle##name_ * GetStyle##name_ () const { \
782 : return static_cast<const nsStyle##name_*>( \
783 : GetStyleDataExternal(eStyleStruct_##name_)); \
784 : }
785 : #endif
786 : #include "nsStyleStructList.h"
787 : #undef STYLE_STRUCT
788 :
789 : #ifdef _IMPL_NS_LAYOUT
790 : /** Also forward GetVisitedDependentColor to the style context */
791 0 : nscolor GetVisitedDependentColor(nsCSSProperty aProperty)
792 0 : { return mStyleContext->GetVisitedDependentColor(aProperty); }
793 : #endif
794 :
795 : /**
796 : * These methods are to access any additional style contexts that
797 : * the frame may be holding. These are contexts that are children
798 : * of the frame's primary context and are NOT used as style contexts
799 : * for any child frames. These contexts also MUST NOT have any child
800 : * contexts whatsoever. If you need to insert style contexts into the
801 : * style tree, then you should create pseudo element frames to own them
802 : * The indicies must be consecutive and implementations MUST return an
803 : * NS_ERROR_INVALID_ARG if asked for an index that is out of range.
804 : */
805 : virtual nsStyleContext* GetAdditionalStyleContext(PRInt32 aIndex) const = 0;
806 :
807 : virtual void SetAdditionalStyleContext(PRInt32 aIndex,
808 : nsStyleContext* aStyleContext) = 0;
809 :
810 : /**
811 : * @return false if this frame definitely has no borders at all
812 : */
813 : bool HasBorder() const;
814 :
815 : /**
816 : * Accessor functions for geometric parent
817 : */
818 0 : nsIFrame* GetParent() const { return mParent; }
819 : virtual void SetParent(nsIFrame* aParent) = 0;
820 :
821 : /**
822 : * Bounding rect of the frame. The values are in app units, and the origin is
823 : * relative to the upper-left of the geometric parent. The size includes the
824 : * content area, borders, and padding.
825 : *
826 : * Note: moving or sizing the frame does not affect the view's size or
827 : * position.
828 : */
829 0 : nsRect GetRect() const { return mRect; }
830 0 : nsPoint GetPosition() const { return nsPoint(mRect.x, mRect.y); }
831 0 : nsSize GetSize() const { return nsSize(mRect.width, mRect.height); }
832 :
833 : /**
834 : * When we change the size of the frame's border-box rect, we may need to
835 : * reset the overflow rect if it was previously stored as deltas.
836 : * (If it is currently a "large" overflow and could be re-packed as deltas,
837 : * we don't bother as the cost of the allocation has already been paid.)
838 : */
839 : void SetRect(const nsRect& aRect) {
840 : if (mOverflow.mType != NS_FRAME_OVERFLOW_LARGE &&
841 : mOverflow.mType != NS_FRAME_OVERFLOW_NONE) {
842 : nsOverflowAreas overflow = GetOverflowAreas();
843 : mRect = aRect;
844 : SetOverflowAreas(overflow);
845 : } else {
846 : mRect = aRect;
847 : }
848 : }
849 : void SetSize(const nsSize& aSize) {
850 : SetRect(nsRect(mRect.TopLeft(), aSize));
851 : }
852 : void SetPosition(const nsPoint& aPt) { mRect.MoveTo(aPt); }
853 :
854 : /**
855 : * Return frame's computed offset due to relative positioning
856 : */
857 : nsPoint GetRelativeOffset(const nsStyleDisplay* aDisplay = nsnull) const;
858 :
859 0 : virtual nsPoint GetPositionOfChildIgnoringScrolling(nsIFrame* aChild)
860 0 : { return aChild->GetPosition(); }
861 :
862 0 : nsPoint GetPositionIgnoringScrolling() {
863 0 : return mParent ? mParent->GetPositionOfChildIgnoringScrolling(this)
864 0 : : GetPosition();
865 : }
866 :
867 : static void DestroyRegion(void* aPropertyValue)
868 : {
869 : delete static_cast<nsRegion*>(aPropertyValue);
870 : }
871 :
872 : static void DestroyMargin(void* aPropertyValue)
873 : {
874 : delete static_cast<nsMargin*>(aPropertyValue);
875 : }
876 :
877 : static void DestroyRect(void* aPropertyValue)
878 : {
879 : delete static_cast<nsRect*>(aPropertyValue);
880 : }
881 :
882 : static void DestroyPoint(void* aPropertyValue)
883 : {
884 : delete static_cast<nsPoint*>(aPropertyValue);
885 : }
886 :
887 : static void DestroyOverflowAreas(void* aPropertyValue)
888 : {
889 : delete static_cast<nsOverflowAreas*>(aPropertyValue);
890 : }
891 :
892 : #ifdef _MSC_VER
893 : // XXX Workaround MSVC issue by making the static FramePropertyDescriptor
894 : // non-const. See bug 555727.
895 : #define NS_PROPERTY_DESCRIPTOR_CONST
896 : #else
897 : #define NS_PROPERTY_DESCRIPTOR_CONST const
898 : #endif
899 :
900 : #define NS_DECLARE_FRAME_PROPERTY(prop, dtor) \
901 : static const FramePropertyDescriptor* prop() { \
902 : static NS_PROPERTY_DESCRIPTOR_CONST FramePropertyDescriptor descriptor = { dtor, nsnull }; \
903 : return &descriptor; \
904 : }
905 : // Don't use this unless you really know what you're doing!
906 : #define NS_DECLARE_FRAME_PROPERTY_WITH_FRAME_IN_DTOR(prop, dtor) \
907 : static const FramePropertyDescriptor* prop() { \
908 : static NS_PROPERTY_DESCRIPTOR_CONST FramePropertyDescriptor descriptor = { nsnull, dtor }; \
909 : return &descriptor; \
910 : }
911 :
912 0 : NS_DECLARE_FRAME_PROPERTY(IBSplitSpecialSibling, nsnull)
913 0 : NS_DECLARE_FRAME_PROPERTY(IBSplitSpecialPrevSibling, nsnull)
914 :
915 : NS_DECLARE_FRAME_PROPERTY(ComputedOffsetProperty, DestroyPoint)
916 :
917 : NS_DECLARE_FRAME_PROPERTY(OutlineInnerRectProperty, DestroyRect)
918 : NS_DECLARE_FRAME_PROPERTY(PreEffectsBBoxProperty, DestroyRect)
919 : NS_DECLARE_FRAME_PROPERTY(PreTransformOverflowAreasProperty,
920 : DestroyOverflowAreas)
921 :
922 : // The initial overflow area passed to FinishAndStoreOverflow. This is only set
923 : // on frames that Preserve3D(), and when at least one of the overflow areas
924 : // differs from the frame bound rect.
925 : NS_DECLARE_FRAME_PROPERTY(InitialOverflowProperty, DestroyOverflowAreas);
926 :
927 : NS_DECLARE_FRAME_PROPERTY(UsedMarginProperty, DestroyMargin)
928 : NS_DECLARE_FRAME_PROPERTY(UsedPaddingProperty, DestroyMargin)
929 : NS_DECLARE_FRAME_PROPERTY(UsedBorderProperty, DestroyMargin)
930 :
931 : NS_DECLARE_FRAME_PROPERTY(ScrollLayerCount, nsnull)
932 :
933 : NS_DECLARE_FRAME_PROPERTY(LineBaselineOffset, nsnull)
934 :
935 : /**
936 : * Return the distance between the border edge of the frame and the
937 : * margin edge of the frame. Like GetRect(), returns the dimensions
938 : * as of the most recent reflow.
939 : *
940 : * This doesn't include any margin collapsing that may have occurred.
941 : *
942 : * It also treats 'auto' margins as zero, and treats any margins that
943 : * should have been turned into 'auto' because of overconstraint as
944 : * having their original values.
945 : */
946 : virtual nsMargin GetUsedMargin() const;
947 :
948 : /**
949 : * Return the distance between the border edge of the frame (which is
950 : * its rect) and the padding edge of the frame. Like GetRect(), returns
951 : * the dimensions as of the most recent reflow.
952 : *
953 : * Note that this differs from GetStyleBorder()->GetBorder() in that
954 : * this describes region of the frame's box, and
955 : * GetStyleBorder()->GetBorder() describes a border. They differ only
956 : * for tables, particularly border-collapse tables.
957 : */
958 : virtual nsMargin GetUsedBorder() const;
959 :
960 : /**
961 : * Return the distance between the padding edge of the frame and the
962 : * content edge of the frame. Like GetRect(), returns the dimensions
963 : * as of the most recent reflow.
964 : */
965 : virtual nsMargin GetUsedPadding() const;
966 :
967 0 : nsMargin GetUsedBorderAndPadding() const {
968 0 : return GetUsedBorder() + GetUsedPadding();
969 : }
970 :
971 : /**
972 : * Apply the result of GetSkipSides() on this frame to an nsMargin by
973 : * setting to zero any sides that are skipped.
974 : */
975 : void ApplySkipSides(nsMargin& aMargin) const;
976 :
977 : /**
978 : * Like the frame's rect (see |GetRect|), which is the border rect,
979 : * other rectangles of the frame, in app units, relative to the parent.
980 : */
981 : nsRect GetPaddingRect() const;
982 : nsRect GetPaddingRectRelativeToSelf() const;
983 : nsRect GetContentRect() const;
984 : nsRect GetContentRectRelativeToSelf() const;
985 :
986 : /**
987 : * Get the size, in app units, of the border radii. It returns FALSE iff all
988 : * returned radii == 0 (so no border radii), TRUE otherwise.
989 : * For the aRadii indexes, use the NS_CORNER_* constants in nsStyleConsts.h
990 : * If a side is skipped via aSkipSides, its corners are forced to 0.
991 : *
992 : * All corner radii are then adjusted so they do not require more
993 : * space than aBorderArea, according to the algorithm in css3-background.
994 : *
995 : * aFrameSize is used as the basis for percentage widths and heights.
996 : * aBorderArea is used for the adjustment of radii that might be too
997 : * large.
998 : * FIXME: In the long run, we can probably get away with only one of
999 : * these, especially if we change the way we handle outline-radius (by
1000 : * removing it and inflating the border radius)
1001 : *
1002 : * Return whether any radii are nonzero.
1003 : */
1004 : static bool ComputeBorderRadii(const nsStyleCorners& aBorderRadius,
1005 : const nsSize& aFrameSize,
1006 : const nsSize& aBorderArea,
1007 : PRIntn aSkipSides,
1008 : nscoord aRadii[8]);
1009 :
1010 : /*
1011 : * Given a set of border radii for one box (e.g., border box), convert
1012 : * it to the equivalent set of radii for another box (e.g., in to
1013 : * padding box, out to outline box) by reducing radii or increasing
1014 : * nonzero radii as appropriate.
1015 : *
1016 : * Indices into aRadii are the NS_CORNER_* constants in nsStyleConsts.h
1017 : *
1018 : * Note that InsetBorderRadii is lossy, since it can turn nonzero
1019 : * radii into zero, and OutsetBorderRadii does not inflate zero radii.
1020 : * Therefore, callers should always inset or outset directly from the
1021 : * original value coming from style.
1022 : */
1023 : static void InsetBorderRadii(nscoord aRadii[8], const nsMargin &aOffsets);
1024 : static void OutsetBorderRadii(nscoord aRadii[8], const nsMargin &aOffsets);
1025 :
1026 : /**
1027 : * Fill in border radii for this frame. Return whether any are
1028 : * nonzero.
1029 : *
1030 : * Indices into aRadii are the NS_CORNER_* constants in nsStyleConsts.h
1031 : */
1032 : virtual bool GetBorderRadii(nscoord aRadii[8]) const;
1033 :
1034 : bool GetPaddingBoxBorderRadii(nscoord aRadii[8]) const;
1035 : bool GetContentBoxBorderRadii(nscoord aRadii[8]) const;
1036 :
1037 : /**
1038 : * Get the position of the frame's baseline, relative to the top of
1039 : * the frame (its top border edge). Only valid when Reflow is not
1040 : * needed.
1041 : */
1042 : virtual nscoord GetBaseline() const = 0;
1043 :
1044 : /**
1045 : * Get the position of the baseline on which the caret needs to be placed,
1046 : * relative to the top of the frame. This is mostly needed for frames
1047 : * which return a baseline from GetBaseline which is not useful for
1048 : * caret positioning.
1049 : */
1050 0 : virtual nscoord GetCaretBaseline() const {
1051 0 : return GetBaseline();
1052 : }
1053 :
1054 : /**
1055 : * Get the specified child list.
1056 : *
1057 : * @param aListID identifies the requested child list.
1058 : * @return the child list. If the requested list is unsupported by this
1059 : * frame type, an empty list will be returned.
1060 : */
1061 : virtual const nsFrameList& GetChildList(ChildListID aListID) const = 0;
1062 : const nsFrameList& PrincipalChildList() { return GetChildList(kPrincipalList); }
1063 : virtual void GetChildLists(nsTArray<ChildList>* aLists) const = 0;
1064 : // XXXbz this method should go away
1065 0 : nsIFrame* GetFirstChild(ChildListID aListID) const {
1066 0 : return GetChildList(aListID).FirstChild();
1067 : }
1068 : // XXXmats this method should also go away then
1069 0 : nsIFrame* GetLastChild(ChildListID aListID) const {
1070 0 : return GetChildList(aListID).LastChild();
1071 : }
1072 0 : nsIFrame* GetFirstPrincipalChild() const {
1073 0 : return GetFirstChild(kPrincipalList);
1074 : }
1075 :
1076 : // The individual concrete child lists.
1077 : static const ChildListID kPrincipalList = mozilla::layout::kPrincipalList;
1078 : static const ChildListID kAbsoluteList = mozilla::layout::kAbsoluteList;
1079 : static const ChildListID kBulletList = mozilla::layout::kBulletList;
1080 : static const ChildListID kCaptionList = mozilla::layout::kCaptionList;
1081 : static const ChildListID kColGroupList = mozilla::layout::kColGroupList;
1082 : static const ChildListID kExcessOverflowContainersList = mozilla::layout::kExcessOverflowContainersList;
1083 : static const ChildListID kFixedList = mozilla::layout::kFixedList;
1084 : static const ChildListID kFloatList = mozilla::layout::kFloatList;
1085 : static const ChildListID kOverflowContainersList = mozilla::layout::kOverflowContainersList;
1086 : static const ChildListID kOverflowList = mozilla::layout::kOverflowList;
1087 : static const ChildListID kOverflowOutOfFlowList = mozilla::layout::kOverflowOutOfFlowList;
1088 : static const ChildListID kPopupList = mozilla::layout::kPopupList;
1089 : static const ChildListID kPushedFloatsList = mozilla::layout::kPushedFloatsList;
1090 : static const ChildListID kSelectPopupList = mozilla::layout::kSelectPopupList;
1091 : // A special alias for kPrincipalList that do not request reflow.
1092 : static const ChildListID kNoReflowPrincipalList = mozilla::layout::kNoReflowPrincipalList;
1093 :
1094 : /**
1095 : * Child frames are linked together in a doubly-linked list
1096 : */
1097 0 : nsIFrame* GetNextSibling() const { return mNextSibling; }
1098 : void SetNextSibling(nsIFrame* aNextSibling) {
1099 : NS_ASSERTION(this != aNextSibling, "Creating a circular frame list, this is very bad.");
1100 : if (mNextSibling && mNextSibling->GetPrevSibling() == this) {
1101 : mNextSibling->mPrevSibling = nsnull;
1102 : }
1103 : mNextSibling = aNextSibling;
1104 : if (mNextSibling) {
1105 : mNextSibling->mPrevSibling = this;
1106 : }
1107 : }
1108 :
1109 : nsIFrame* GetPrevSibling() const { return mPrevSibling; }
1110 :
1111 : /**
1112 : * Builds the display lists for the content represented by this frame
1113 : * and its descendants. The background+borders of this element must
1114 : * be added first, before any other content.
1115 : *
1116 : * This should only be called by methods in nsFrame. Instead of calling this
1117 : * directly, call either BuildDisplayListForStackingContext or
1118 : * BuildDisplayListForChild.
1119 : *
1120 : * See nsDisplayList.h for more information about display lists.
1121 : *
1122 : * @param aDirtyRect content outside this rectangle can be ignored; the
1123 : * rectangle is in frame coordinates
1124 : */
1125 : NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder,
1126 : const nsRect& aDirtyRect,
1127 : const nsDisplayListSet& aLists) { return NS_OK; }
1128 : /**
1129 : * Displays the caret onto the given display list builder. The caret is
1130 : * painted on top of the rest of the display list items.
1131 : *
1132 : * @param aDirtyRect is the dirty rectangle that we're repainting.
1133 : */
1134 : nsresult DisplayCaret(nsDisplayListBuilder* aBuilder,
1135 : const nsRect& aDirtyRect,
1136 : nsDisplayList* aList);
1137 :
1138 : /**
1139 : * Get the preferred caret color at the offset.
1140 : *
1141 : * @param aOffset is offset of the content.
1142 : */
1143 : virtual nscolor GetCaretColorAt(PRInt32 aOffset);
1144 :
1145 :
1146 0 : bool IsThemed(nsITheme::Transparency* aTransparencyState = nsnull) const {
1147 0 : return IsThemed(GetStyleDisplay(), aTransparencyState);
1148 : }
1149 0 : bool IsThemed(const nsStyleDisplay* aDisp,
1150 : nsITheme::Transparency* aTransparencyState = nsnull) const {
1151 0 : nsIFrame* mutable_this = const_cast<nsIFrame*>(this);
1152 0 : if (!aDisp->mAppearance)
1153 0 : return false;
1154 0 : nsPresContext* pc = PresContext();
1155 0 : nsITheme *theme = pc->GetTheme();
1156 0 : if(!theme ||
1157 0 : !theme->ThemeSupportsWidget(pc, mutable_this, aDisp->mAppearance))
1158 0 : return false;
1159 0 : if (aTransparencyState) {
1160 : *aTransparencyState =
1161 0 : theme->GetWidgetTransparency(mutable_this, aDisp->mAppearance);
1162 : }
1163 0 : return true;
1164 : }
1165 :
1166 : /**
1167 : * Builds a display list for the content represented by this frame,
1168 : * treating this frame as the root of a stacking context.
1169 : * @param aDirtyRect content outside this rectangle can be ignored; the
1170 : * rectangle is in frame coordinates
1171 : */
1172 : nsresult BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
1173 : const nsRect& aDirtyRect,
1174 : nsDisplayList* aList);
1175 :
1176 : /**
1177 : * Clips the display items of aFromSet, putting the results in aToSet.
1178 : * Only items corresponding to frames which are descendants of this frame
1179 : * are clipped. In other words, descendant elements whose CSS boxes do not
1180 : * have this frame as a container are not clipped. Also,
1181 : * border/background/outline items for this frame are not clipped,
1182 : * unless aClipBorderBackground is set to true. (We need this because
1183 : * a scrollframe must overflow-clip its scrolled child's background/borders.)
1184 : *
1185 : * Indices into aClipRadii are the NS_CORNER_* constants in nsStyleConsts.h
1186 : */
1187 : nsresult OverflowClip(nsDisplayListBuilder* aBuilder,
1188 : const nsDisplayListSet& aFromSet,
1189 : const nsDisplayListSet& aToSet,
1190 : const nsRect& aClipRect,
1191 : const nscoord aClipRadii[8],
1192 : bool aClipBorderBackground = false,
1193 : bool aClipAll = false);
1194 :
1195 : enum {
1196 : DISPLAY_CHILD_FORCE_PSEUDO_STACKING_CONTEXT = 0x01,
1197 : DISPLAY_CHILD_FORCE_STACKING_CONTEXT = 0x02,
1198 : DISPLAY_CHILD_INLINE = 0x04
1199 : };
1200 : /**
1201 : * Adjusts aDirtyRect for the child's offset, checks that the dirty rect
1202 : * actually intersects the child (or its descendants), calls BuildDisplayList
1203 : * on the child if necessary, and puts things in the right lists if the child
1204 : * is positioned.
1205 : *
1206 : * @param aFlags combination of DISPLAY_CHILD_FORCE_PSEUDO_STACKING_CONTEXT,
1207 : * DISPLAY_CHILD_FORCE_STACKING_CONTEXT and DISPLAY_CHILD_INLINE
1208 : */
1209 : nsresult BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
1210 : nsIFrame* aChild,
1211 : const nsRect& aDirtyRect,
1212 : const nsDisplayListSet& aLists,
1213 : PRUint32 aFlags = 0);
1214 :
1215 : /**
1216 : * A helper for replaced elements that want to clip their content to a
1217 : * border radius, but only need clipping at all when they have a
1218 : * border radius.
1219 : */
1220 : void WrapReplacedContentForBorderRadius(nsDisplayListBuilder* aBuilder,
1221 : nsDisplayList* aFromList,
1222 : const nsDisplayListSet& aToLists);
1223 :
1224 : /**
1225 : * Does this frame need a view?
1226 : */
1227 0 : virtual bool NeedsView() { return false; }
1228 :
1229 : /**
1230 : * Returns whether this frame has a transform matrix applied to it. This is true
1231 : * if we have the -moz-transform property or if we're an SVGForeignObjectFrame.
1232 : */
1233 : virtual bool IsTransformed() const;
1234 :
1235 : /**
1236 : * Returns whether this frame will attempt to preserve the 3d transforms of its
1237 : * children. This is a direct indicator of -moz-transform-style: preserve-3d.
1238 : */
1239 : bool Preserves3DChildren() const;
1240 :
1241 : /**
1242 : * Returns whether this frame has a parent that Preserves3DChildren() and
1243 : * can respect this. Returns false if the frame is clipped.
1244 : */
1245 : bool Preserves3D() const;
1246 :
1247 : bool HasPerspective() const;
1248 :
1249 : bool ChildrenHavePerspective() const;
1250 :
1251 : // Calculate the overflow size of all child frames, taking preserve-3d into account
1252 : void ComputePreserve3DChildrenOverflow(nsOverflowAreas& aOverflowAreas, const nsRect& aBounds);
1253 :
1254 : void RecomputePerspectiveChildrenOverflow(const nsStyleContext* aStartStyle, const nsRect* aBounds);
1255 :
1256 : /**
1257 : * Event handling of GUI events.
1258 : *
1259 : * @param aEvent event structure describing the type of event and rge widget
1260 : * where the event originated
1261 : * The |point| member of this is in the coordinate system of the
1262 : * view returned by GetOffsetFromView.
1263 : * @param aEventStatus a return value indicating whether the event was handled
1264 : * and whether default processing should be done
1265 : *
1266 : * XXX From a frame's perspective it's unclear what the effect of the event status
1267 : * is. Does it cause the event to continue propagating through the frame hierarchy
1268 : * or is it just returned to the widgets?
1269 : *
1270 : * @see nsGUIEvent
1271 : * @see nsEventStatus
1272 : */
1273 : NS_IMETHOD HandleEvent(nsPresContext* aPresContext,
1274 : nsGUIEvent* aEvent,
1275 : nsEventStatus* aEventStatus) = 0;
1276 :
1277 : NS_IMETHOD GetContentForEvent(nsEvent* aEvent,
1278 : nsIContent** aContent) = 0;
1279 :
1280 : // This structure keeps track of the content node and offsets associated with
1281 : // a point; there is a primary and a secondary offset associated with any
1282 : // point. The primary and secondary offsets differ when the point is over a
1283 : // non-text object. The primary offset is the expected position of the
1284 : // cursor calculated from a point; the secondary offset, when it is different,
1285 : // indicates that the point is in the boundaries of some selectable object.
1286 : // Note that the primary offset can be after the secondary offset; for places
1287 : // that need the beginning and end of the object, the StartOffset and
1288 : // EndOffset helpers can be used.
1289 0 : struct NS_STACK_CLASS ContentOffsets {
1290 : nsCOMPtr<nsIContent> content;
1291 : bool IsNull() { return !content; }
1292 : PRInt32 offset;
1293 : PRInt32 secondaryOffset;
1294 : // Helpers for places that need the ends of the offsets and expect them in
1295 : // numerical order, as opposed to wanting the primary and secondary offsets
1296 : PRInt32 StartOffset() { return NS_MIN(offset, secondaryOffset); }
1297 : PRInt32 EndOffset() { return NS_MAX(offset, secondaryOffset); }
1298 : // This boolean indicates whether the associated content is before or after
1299 : // the offset; the most visible use is to allow the caret to know which line
1300 : // to display on.
1301 : bool associateWithNext;
1302 : };
1303 : /**
1304 : * This function calculates the content offsets for selection relative to
1305 : * a point. Note that this should generally only be callled on the event
1306 : * frame associated with an event because this function does not account
1307 : * for frame lists other than the primary one.
1308 : * @param aPoint point relative to this frame
1309 : */
1310 : ContentOffsets GetContentOffsetsFromPoint(nsPoint aPoint,
1311 : bool aIgnoreSelectionStyle = false);
1312 :
1313 0 : virtual ContentOffsets GetContentOffsetsFromPointExternal(nsPoint aPoint,
1314 : bool aIgnoreSelectionStyle = false)
1315 0 : { return GetContentOffsetsFromPoint(aPoint, aIgnoreSelectionStyle); }
1316 :
1317 : /**
1318 : * This structure holds information about a cursor. mContainer represents a
1319 : * loaded image that should be preferred. If it is not possible to use it, or
1320 : * if it is null, mCursor should be used.
1321 : */
1322 : struct NS_STACK_CLASS Cursor {
1323 : nsCOMPtr<imgIContainer> mContainer;
1324 : PRInt32 mCursor;
1325 : bool mHaveHotspot;
1326 : float mHotspotX, mHotspotY;
1327 : };
1328 : /**
1329 : * Get the cursor for a given frame.
1330 : */
1331 : NS_IMETHOD GetCursor(const nsPoint& aPoint,
1332 : Cursor& aCursor) = 0;
1333 :
1334 : /**
1335 : * Get a point (in the frame's coordinate space) given an offset into
1336 : * the content. This point should be on the baseline of text with
1337 : * the correct horizontal offset
1338 : */
1339 : NS_IMETHOD GetPointFromOffset(PRInt32 inOffset,
1340 : nsPoint* outPoint) = 0;
1341 :
1342 : /**
1343 : * Get the child frame of this frame which contains the given
1344 : * content offset. outChildFrame may be this frame, or nsnull on return.
1345 : * outContentOffset returns the content offset relative to the start
1346 : * of the returned node. You can also pass a hint which tells the method
1347 : * to stick to the end of the first found frame or the beginning of the
1348 : * next in case the offset falls on a boundary.
1349 : */
1350 : NS_IMETHOD GetChildFrameContainingOffset(PRInt32 inContentOffset,
1351 : bool inHint,//false stick left
1352 : PRInt32* outFrameContentOffset,
1353 : nsIFrame* *outChildFrame) = 0;
1354 :
1355 : /**
1356 : * Get the current frame-state value for this frame. aResult is
1357 : * filled in with the state bits.
1358 : */
1359 0 : nsFrameState GetStateBits() const { return mState; }
1360 :
1361 : /**
1362 : * Update the current frame-state value for this frame.
1363 : */
1364 0 : void AddStateBits(nsFrameState aBits) { mState |= aBits; }
1365 : void RemoveStateBits(nsFrameState aBits) { mState &= ~aBits; }
1366 :
1367 : /**
1368 : * This call is invoked on the primary frame for a character data content
1369 : * node, when it is changed in the content tree.
1370 : */
1371 : NS_IMETHOD CharacterDataChanged(CharacterDataChangeInfo* aInfo) = 0;
1372 :
1373 : /**
1374 : * This call is invoked when the value of a content objects's attribute
1375 : * is changed.
1376 : * The first frame that maps that content is asked to deal
1377 : * with the change by doing whatever is appropriate.
1378 : *
1379 : * @param aNameSpaceID the namespace of the attribute
1380 : * @param aAttribute the atom name of the attribute
1381 : * @param aModType Whether or not the attribute was added, changed, or removed.
1382 : * The constants are defined in nsIDOMMutationEvent.h.
1383 : */
1384 : NS_IMETHOD AttributeChanged(PRInt32 aNameSpaceID,
1385 : nsIAtom* aAttribute,
1386 : PRInt32 aModType) = 0;
1387 :
1388 : /**
1389 : * When the content states of a content object change, this method is invoked
1390 : * on the primary frame of that content object.
1391 : *
1392 : * @param aStates the changed states
1393 : */
1394 0 : virtual void ContentStatesChanged(nsEventStates aStates) { };
1395 :
1396 : /**
1397 : * Return how your frame can be split.
1398 : */
1399 : virtual nsSplittableType GetSplittableType() const = 0;
1400 :
1401 : /**
1402 : * Continuation member functions
1403 : */
1404 : virtual nsIFrame* GetPrevContinuation() const = 0;
1405 : NS_IMETHOD SetPrevContinuation(nsIFrame*) = 0;
1406 : virtual nsIFrame* GetNextContinuation() const = 0;
1407 : NS_IMETHOD SetNextContinuation(nsIFrame*) = 0;
1408 0 : virtual nsIFrame* GetFirstContinuation() const {
1409 0 : return const_cast<nsIFrame*>(this);
1410 : }
1411 0 : virtual nsIFrame* GetLastContinuation() const {
1412 0 : return const_cast<nsIFrame*>(this);
1413 : }
1414 :
1415 : /**
1416 : * GetTailContinuation gets the last non-overflow-container continuation
1417 : * in the continuation chain, i.e. where the next sibling element
1418 : * should attach).
1419 : */
1420 : nsIFrame* GetTailContinuation();
1421 :
1422 : /**
1423 : * Flow member functions
1424 : */
1425 : virtual nsIFrame* GetPrevInFlowVirtual() const = 0;
1426 0 : nsIFrame* GetPrevInFlow() const { return GetPrevInFlowVirtual(); }
1427 : NS_IMETHOD SetPrevInFlow(nsIFrame*) = 0;
1428 :
1429 : virtual nsIFrame* GetNextInFlowVirtual() const = 0;
1430 0 : nsIFrame* GetNextInFlow() const { return GetNextInFlowVirtual(); }
1431 : NS_IMETHOD SetNextInFlow(nsIFrame*) = 0;
1432 :
1433 : /**
1434 : * Return the first frame in our current flow.
1435 : */
1436 0 : virtual nsIFrame* GetFirstInFlow() const {
1437 0 : return const_cast<nsIFrame*>(this);
1438 : }
1439 :
1440 : /**
1441 : * Return the last frame in our current flow.
1442 : */
1443 0 : virtual nsIFrame* GetLastInFlow() const {
1444 0 : return const_cast<nsIFrame*>(this);
1445 : }
1446 :
1447 :
1448 : /**
1449 : * Mark any stored intrinsic width information as dirty (requiring
1450 : * re-calculation). Note that this should generally not be called
1451 : * directly; nsPresShell::FrameNeedsReflow will call it instead.
1452 : */
1453 : virtual void MarkIntrinsicWidthsDirty() = 0;
1454 :
1455 : /**
1456 : * Get the intrinsic minimum width of the frame. This must be less
1457 : * than or equal to the intrinsic width.
1458 : *
1459 : * This is *not* affected by the CSS 'min-width', 'width', and
1460 : * 'max-width' properties on this frame, but it is affected by the
1461 : * values of those properties on this frame's descendants. (It may be
1462 : * called during computation of the values of those properties, so it
1463 : * cannot depend on any values in the nsStylePosition for this frame.)
1464 : *
1465 : * The value returned should **NOT** include the space required for
1466 : * padding and border.
1467 : *
1468 : * Note that many frames will cache the result of this function call
1469 : * unless MarkIntrinsicWidthsDirty is called.
1470 : *
1471 : * It is not acceptable for a frame to mark itself dirty when this
1472 : * method is called.
1473 : *
1474 : * This method must not return a negative value.
1475 : */
1476 : virtual nscoord GetMinWidth(nsRenderingContext *aRenderingContext) = 0;
1477 :
1478 : /**
1479 : * Get the intrinsic width of the frame. This must be greater than or
1480 : * equal to the intrinsic minimum width.
1481 : *
1482 : * Otherwise, all the comments for |GetMinWidth| above apply.
1483 : */
1484 : virtual nscoord GetPrefWidth(nsRenderingContext *aRenderingContext) = 0;
1485 :
1486 : /**
1487 : * |InlineIntrinsicWidth| represents the intrinsic width information
1488 : * in inline layout. Code that determines the intrinsic width of a
1489 : * region of inline layout accumulates the result into this structure.
1490 : * This pattern is needed because we need to maintain state
1491 : * information about whitespace (for both collapsing and trimming).
1492 : */
1493 0 : struct InlineIntrinsicWidthData {
1494 0 : InlineIntrinsicWidthData()
1495 : : line(nsnull)
1496 : , lineContainer(nsnull)
1497 : , prevLines(0)
1498 : , currentLine(0)
1499 : , skipWhitespace(true)
1500 0 : , trailingWhitespace(0)
1501 0 : {}
1502 :
1503 : // The line. This may be null if the inlines are not associated with
1504 : // a block or if we just don't know the line.
1505 : const nsLineList_iterator* line;
1506 :
1507 : // The line container.
1508 : nsIFrame* lineContainer;
1509 :
1510 : // The maximum intrinsic width for all previous lines.
1511 : nscoord prevLines;
1512 :
1513 : // The maximum intrinsic width for the current line. At a line
1514 : // break (mandatory for preferred width; allowed for minimum width),
1515 : // the caller should call |Break()|.
1516 : nscoord currentLine;
1517 :
1518 : // True if initial collapsable whitespace should be skipped. This
1519 : // should be true at the beginning of a block, after hard breaks
1520 : // and when the last text ended with whitespace.
1521 : bool skipWhitespace;
1522 :
1523 : // This contains the width of the trimmable whitespace at the end of
1524 : // |currentLine|; it is zero if there is no such whitespace.
1525 : nscoord trailingWhitespace;
1526 :
1527 : // Floats encountered in the lines.
1528 : nsTArray<nsIFrame*> floats;
1529 : };
1530 :
1531 0 : struct InlineMinWidthData : public InlineIntrinsicWidthData {
1532 0 : InlineMinWidthData()
1533 : : trailingTextFrame(nsnull)
1534 0 : , atStartOfLine(true)
1535 0 : {}
1536 :
1537 : // We need to distinguish forced and optional breaks for cases where the
1538 : // current line total is negative. When it is, we need to ignore
1539 : // optional breaks to prevent min-width from ending up bigger than
1540 : // pref-width.
1541 : void ForceBreak(nsRenderingContext *aRenderingContext);
1542 :
1543 : // If the break here is actually taken, aHyphenWidth must be added to the
1544 : // width of the current line.
1545 : void OptionallyBreak(nsRenderingContext *aRenderingContext,
1546 : nscoord aHyphenWidth = 0);
1547 :
1548 : // The last text frame processed so far in the current line, when
1549 : // the last characters in that text frame are relevant for line
1550 : // break opportunities.
1551 : nsIFrame *trailingTextFrame;
1552 :
1553 : // Whether we're currently at the start of the line. If we are, we
1554 : // can't break (for example, between the text-indent and the first
1555 : // word).
1556 : bool atStartOfLine;
1557 : };
1558 :
1559 0 : struct InlinePrefWidthData : public InlineIntrinsicWidthData {
1560 : void ForceBreak(nsRenderingContext *aRenderingContext);
1561 : };
1562 :
1563 : /**
1564 : * Add the intrinsic minimum width of a frame in a way suitable for
1565 : * use in inline layout to an |InlineIntrinsicWidthData| object that
1566 : * represents the intrinsic width information of all the previous
1567 : * frames in the inline layout region.
1568 : *
1569 : * All *allowed* breakpoints within the frame determine what counts as
1570 : * a line for the |InlineIntrinsicWidthData|. This means that
1571 : * |aData->trailingWhitespace| will always be zero (unlike for
1572 : * AddInlinePrefWidth).
1573 : *
1574 : * All the comments for |GetMinWidth| apply, except that this function
1575 : * is responsible for adding padding, border, and margin and for
1576 : * considering the effects of 'width', 'min-width', and 'max-width'.
1577 : *
1578 : * This may be called on any frame. Frames that do not participate in
1579 : * line breaking can inherit the default implementation on nsFrame,
1580 : * which calls |GetMinWidth|.
1581 : */
1582 : virtual void
1583 : AddInlineMinWidth(nsRenderingContext *aRenderingContext,
1584 : InlineMinWidthData *aData) = 0;
1585 :
1586 : /**
1587 : * Add the intrinsic preferred width of a frame in a way suitable for
1588 : * use in inline layout to an |InlineIntrinsicWidthData| object that
1589 : * represents the intrinsic width information of all the previous
1590 : * frames in the inline layout region.
1591 : *
1592 : * All the comments for |AddInlineMinWidth| and |GetPrefWidth| apply,
1593 : * except that this fills in an |InlineIntrinsicWidthData| structure
1594 : * based on using all *mandatory* breakpoints within the frame.
1595 : */
1596 : virtual void
1597 : AddInlinePrefWidth(nsRenderingContext *aRenderingContext,
1598 : InlinePrefWidthData *aData) = 0;
1599 :
1600 : /**
1601 : * Return the horizontal components of padding, border, and margin
1602 : * that contribute to the intrinsic width that applies to the parent.
1603 : */
1604 : struct IntrinsicWidthOffsetData {
1605 : nscoord hPadding, hBorder, hMargin;
1606 : float hPctPadding, hPctMargin;
1607 :
1608 : IntrinsicWidthOffsetData()
1609 : : hPadding(0), hBorder(0), hMargin(0)
1610 : , hPctPadding(0.0f), hPctMargin(0.0f)
1611 : {}
1612 : };
1613 : virtual IntrinsicWidthOffsetData
1614 : IntrinsicWidthOffsets(nsRenderingContext* aRenderingContext) = 0;
1615 :
1616 : /*
1617 : * For replaced elements only. Gets the intrinsic dimensions of this element.
1618 : * The dimensions may only be one of the following two types:
1619 : *
1620 : * eStyleUnit_Coord - a length in app units
1621 : * eStyleUnit_None - the element has no intrinsic size in this dimension
1622 : */
1623 : struct IntrinsicSize {
1624 : nsStyleCoord width, height;
1625 :
1626 : IntrinsicSize()
1627 : : width(eStyleUnit_None), height(eStyleUnit_None)
1628 : {}
1629 : IntrinsicSize(const IntrinsicSize& rhs)
1630 : : width(rhs.width), height(rhs.height)
1631 : {}
1632 : IntrinsicSize& operator=(const IntrinsicSize& rhs) {
1633 : width = rhs.width; height = rhs.height; return *this;
1634 : }
1635 : bool operator==(const IntrinsicSize& rhs) {
1636 : return width == rhs.width && height == rhs.height;
1637 : }
1638 : bool operator!=(const IntrinsicSize& rhs) {
1639 : return !(*this == rhs);
1640 : }
1641 : };
1642 : virtual IntrinsicSize GetIntrinsicSize() = 0;
1643 :
1644 : /*
1645 : * Get the intrinsic ratio of this element, or nsSize(0,0) if it has
1646 : * no intrinsic ratio. The intrinsic ratio is the ratio of the
1647 : * height/width of a box with an intrinsic size or the intrinsic
1648 : * aspect ratio of a scalable vector image without an intrinsic size.
1649 : *
1650 : * Either one of the sides may be zero, indicating a zero or infinite
1651 : * ratio.
1652 : */
1653 : virtual nsSize GetIntrinsicRatio() = 0;
1654 :
1655 : /**
1656 : * Compute the size that a frame will occupy. Called while
1657 : * constructing the nsHTMLReflowState to be used to Reflow the frame,
1658 : * in order to fill its mComputedWidth and mComputedHeight member
1659 : * variables.
1660 : *
1661 : * The |height| member of the return value may be
1662 : * NS_UNCONSTRAINEDSIZE, but the |width| member must not be.
1663 : *
1664 : * Note that the reason that border and padding need to be passed
1665 : * separately is so that the 'box-sizing' property can be handled.
1666 : * Thus aMargin includes absolute positioning offsets as well.
1667 : *
1668 : * @param aCBSize The size of the element's containing block. (Well,
1669 : * the |height| component isn't really.)
1670 : * @param aAvailableWidth The available width for 'auto' widths.
1671 : * This is usually the same as aCBSize.width,
1672 : * but differs in cases such as block
1673 : * formatting context roots next to floats, or
1674 : * in some cases of float reflow in quirks
1675 : * mode.
1676 : * @param aMargin The sum of the vertical / horizontal margins
1677 : * ***AND*** absolute positioning offsets (top, right,
1678 : * bottom, left) of the frame, including actual values
1679 : * resulting from percentages and from the
1680 : * "hypothetical box" for absolute positioning, but
1681 : * not including actual values resulting from 'auto'
1682 : * margins or ignored 'auto' values in absolute
1683 : * positioning.
1684 : * @param aBorder The sum of the vertical / horizontal border widths
1685 : * of the frame.
1686 : * @param aPadding The sum of the vertical / horizontal margins of
1687 : * the frame, including actual values resulting from
1688 : * percentages.
1689 : * @param aShrinkWrap Whether the frame is in a context where
1690 : * non-replaced blocks should shrink-wrap (e.g.,
1691 : * it's floating, absolutely positioned, or
1692 : * inline-block).
1693 : */
1694 : virtual nsSize ComputeSize(nsRenderingContext *aRenderingContext,
1695 : nsSize aCBSize, nscoord aAvailableWidth,
1696 : nsSize aMargin, nsSize aBorder, nsSize aPadding,
1697 : bool aShrinkWrap) = 0;
1698 :
1699 : /**
1700 : * Compute a tight bounding rectangle for the frame. This is a rectangle
1701 : * that encloses the pixels that are actually drawn. We're allowed to be
1702 : * conservative and currently we don't try very hard. The rectangle is
1703 : * in appunits and relative to the origin of this frame.
1704 : *
1705 : * This probably only needs to include frame bounds, glyph bounds, and
1706 : * text decorations, but today it sometimes includes other things that
1707 : * contribute to visual overflow.
1708 : *
1709 : * @param aContext a rendering context that can be used if we need
1710 : * to do measurement
1711 : */
1712 : virtual nsRect ComputeTightBounds(gfxContext* aContext) const;
1713 :
1714 : /**
1715 : * Pre-reflow hook. Before a frame is reflowed this method will be called.
1716 : * This call will always be invoked at least once before a subsequent Reflow
1717 : * and DidReflow call. It may be called more than once, In general you will
1718 : * receive on WillReflow notification before each Reflow request.
1719 : *
1720 : * XXX Is this really the semantics we want? Because we have the NS_FRAME_IN_REFLOW
1721 : * bit we can ensure we don't call it more than once...
1722 : */
1723 : NS_IMETHOD WillReflow(nsPresContext* aPresContext) = 0;
1724 :
1725 : /**
1726 : * The frame is given an available size and asked for its desired
1727 : * size. This is the frame's opportunity to reflow its children.
1728 : *
1729 : * If the frame has the NS_FRAME_IS_DIRTY bit set then it is
1730 : * responsible for completely reflowing itself and all of its
1731 : * descendants.
1732 : *
1733 : * Otherwise, if the frame has the NS_FRAME_HAS_DIRTY_CHILDREN bit
1734 : * set, then it is responsible for reflowing at least those
1735 : * children that have NS_FRAME_HAS_DIRTY_CHILDREN or NS_FRAME_IS_DIRTY
1736 : * set.
1737 : *
1738 : * If a difference in available size from the previous reflow causes
1739 : * the frame's size to change, it should reflow descendants as needed.
1740 : *
1741 : * @param aReflowMetrics <i>out</i> parameter where you should return the
1742 : * desired size and ascent/descent info. You should include any
1743 : * space you want for border/padding in the desired size you return.
1744 : *
1745 : * It's okay to return a desired size that exceeds the avail
1746 : * size if that's the smallest you can be, i.e. it's your
1747 : * minimum size.
1748 : *
1749 : * For an incremental reflow you are responsible for invalidating
1750 : * any area within your frame that needs repainting (including
1751 : * borders). If your new desired size is different than your current
1752 : * size, then your parent frame is responsible for making sure that
1753 : * the difference between the two rects is repainted
1754 : *
1755 : * @param aReflowState information about your reflow including the reason
1756 : * for the reflow and the available space in which to lay out. Each
1757 : * dimension of the available space can either be constrained or
1758 : * unconstrained (a value of NS_UNCONSTRAINEDSIZE).
1759 : *
1760 : * Note that the available space can be negative. In this case you
1761 : * still must return an accurate desired size. If you're a container
1762 : * you must <b>always</b> reflow at least one frame regardless of the
1763 : * available space
1764 : *
1765 : * @param aStatus a return value indicating whether the frame is complete
1766 : * and whether the next-in-flow is dirty and needs to be reflowed
1767 : */
1768 : NS_IMETHOD Reflow(nsPresContext* aPresContext,
1769 : nsHTMLReflowMetrics& aReflowMetrics,
1770 : const nsHTMLReflowState& aReflowState,
1771 : nsReflowStatus& aStatus) = 0;
1772 :
1773 : /**
1774 : * Post-reflow hook. After a frame is reflowed this method will be called
1775 : * informing the frame that this reflow process is complete, and telling the
1776 : * frame the status returned by the Reflow member function.
1777 : *
1778 : * This call may be invoked many times, while NS_FRAME_IN_REFLOW is set, before
1779 : * it is finally called once with a NS_FRAME_REFLOW_COMPLETE value. When called
1780 : * with a NS_FRAME_REFLOW_COMPLETE value the NS_FRAME_IN_REFLOW bit in the
1781 : * frame state will be cleared.
1782 : *
1783 : * XXX This doesn't make sense. If the frame is reflowed but not complete, then
1784 : * the status should be NS_FRAME_NOT_COMPLETE and not NS_FRAME_COMPLETE
1785 : * XXX Don't we want the semantics to dictate that we only call this once for
1786 : * a given reflow?
1787 : */
1788 : NS_IMETHOD DidReflow(nsPresContext* aPresContext,
1789 : const nsHTMLReflowState* aReflowState,
1790 : nsDidReflowStatus aStatus) = 0;
1791 :
1792 : // XXX Maybe these three should be a separate interface?
1793 :
1794 : /**
1795 : * Updates the overflow areas of the frame. This can be called if an
1796 : * overflow area of the frame's children has changed without reflowing.
1797 : * @return true if either of the overflow areas for this frame have changed.
1798 : */
1799 : virtual bool UpdateOverflow() = 0;
1800 :
1801 : /**
1802 : * Helper method used by block reflow to identify runs of text so
1803 : * that proper word-breaking can be done.
1804 : *
1805 : * @return
1806 : * true if we can continue a "text run" through the frame. A
1807 : * text run is text that should be treated contiguously for line
1808 : * and word breaking.
1809 : */
1810 : virtual bool CanContinueTextRun() const = 0;
1811 :
1812 : /**
1813 : * Append the rendered text to the passed-in string.
1814 : * The appended text will often not contain all the whitespace from source,
1815 : * depending on whether the CSS rule "white-space: pre" is active for this frame.
1816 : * if aStartOffset + aLength goes past end, or if aLength is not specified
1817 : * then use the text up to the string's end.
1818 : * Call this on the primary frame for a text node.
1819 : * @param aAppendToString String to append text to, or null if text should not be returned
1820 : * @param aSkipChars if aSkipIter is non-null, this must also be non-null.
1821 : * This gets used as backing data for the iterator so it should outlive the iterator.
1822 : * @param aSkipIter Where to fill in the gfxSkipCharsIterator info, or null if not needed by caller
1823 : * @param aStartOffset Skipped (rendered text) start offset
1824 : * @param aSkippedMaxLength Maximum number of characters to return
1825 : * The iterator can be used to map content offsets to offsets in the returned string, or vice versa.
1826 : */
1827 0 : virtual nsresult GetRenderedText(nsAString* aAppendToString = nsnull,
1828 : gfxSkipChars* aSkipChars = nsnull,
1829 : gfxSkipCharsIterator* aSkipIter = nsnull,
1830 : PRUint32 aSkippedStartOffset = 0,
1831 : PRUint32 aSkippedMaxLength = PR_UINT32_MAX)
1832 0 : { return NS_ERROR_NOT_IMPLEMENTED; }
1833 :
1834 : /**
1835 : * Returns true if the frame contains any non-collapsed characters.
1836 : * This method is only available for text frames, and it will return false
1837 : * for all other frame types.
1838 : */
1839 0 : virtual bool HasAnyNoncollapsedCharacters()
1840 0 : { return false; }
1841 :
1842 : /**
1843 : * Accessor functions to get/set the associated view object
1844 : *
1845 : * GetView returns non-null if and only if |HasView| returns true.
1846 : */
1847 0 : bool HasView() const { return !!(mState & NS_FRAME_HAS_VIEW); }
1848 : nsIView* GetView() const;
1849 : virtual nsIView* GetViewExternal() const;
1850 : nsresult SetView(nsIView* aView);
1851 :
1852 : /**
1853 : * Find the closest view (on |this| or an ancestor).
1854 : * If aOffset is non-null, it will be set to the offset of |this|
1855 : * from the returned view.
1856 : */
1857 : nsIView* GetClosestView(nsPoint* aOffset = nsnull) const;
1858 :
1859 : /**
1860 : * Find the closest ancestor (excluding |this| !) that has a view
1861 : */
1862 : nsIFrame* GetAncestorWithView() const;
1863 : virtual nsIFrame* GetAncestorWithViewExternal() const;
1864 :
1865 : /**
1866 : * Get the offset between the coordinate systems of |this| and aOther.
1867 : * Adding the return value to a point in the coordinate system of |this|
1868 : * will transform the point to the coordinate system of aOther.
1869 : *
1870 : * aOther must be non-null.
1871 : *
1872 : * This function is fastest when aOther is an ancestor of |this|.
1873 : *
1874 : * This function _DOES NOT_ work across document boundaries.
1875 : * Use this function only when |this| and aOther are in the same document.
1876 : *
1877 : * NOTE: this actually returns the offset from aOther to |this|, but
1878 : * that offset is added to transform _coordinates_ from |this| to
1879 : * aOther.
1880 : */
1881 : nsPoint GetOffsetTo(const nsIFrame* aOther) const;
1882 : virtual nsPoint GetOffsetToExternal(const nsIFrame* aOther) const;
1883 :
1884 : /**
1885 : * Get the offset between the coordinate systems of |this| and aOther
1886 : * expressed in appunits per dev pixel of |this|' document. Adding the return
1887 : * value to a point that is relative to the origin of |this| will make the
1888 : * point relative to the origin of aOther but in the appunits per dev pixel
1889 : * ratio of |this|.
1890 : *
1891 : * aOther must be non-null.
1892 : *
1893 : * This function is fastest when aOther is an ancestor of |this|.
1894 : *
1895 : * This function works across document boundaries.
1896 : *
1897 : * Because this function may cross document boundaries that have different
1898 : * app units per dev pixel ratios it needs to be used very carefully.
1899 : *
1900 : * NOTE: this actually returns the offset from aOther to |this|, but
1901 : * that offset is added to transform _coordinates_ from |this| to
1902 : * aOther.
1903 : */
1904 : nsPoint GetOffsetToCrossDoc(const nsIFrame* aOther) const;
1905 :
1906 : /**
1907 : * Get the screen rect of the frame in pixels.
1908 : * @return the pixel rect of the frame in screen coordinates.
1909 : */
1910 : nsIntRect GetScreenRect() const;
1911 : virtual nsIntRect GetScreenRectExternal() const;
1912 :
1913 : /**
1914 : * Get the screen rect of the frame in app units.
1915 : * @return the app unit rect of the frame in screen coordinates.
1916 : */
1917 : nsRect GetScreenRectInAppUnits() const;
1918 : virtual nsRect GetScreenRectInAppUnitsExternal() const;
1919 :
1920 : /**
1921 : * Returns the offset from this frame to the closest geometric parent that
1922 : * has a view. Also returns the containing view or null in case of error
1923 : */
1924 : NS_IMETHOD GetOffsetFromView(nsPoint& aOffset,
1925 : nsIView** aView) const = 0;
1926 :
1927 : /**
1928 : * Returns the nearest widget containing this frame. If this frame has a
1929 : * view and the view has a widget, then this frame's widget is
1930 : * returned, otherwise this frame's geometric parent is checked
1931 : * recursively upwards.
1932 : * XXX virtual because gfx callers use it! (themes)
1933 : */
1934 : virtual nsIWidget* GetNearestWidget() const;
1935 :
1936 : /**
1937 : * Same as GetNearestWidget() above but uses an outparam to return the offset
1938 : * of this frame to the returned widget expressed in appunits of |this| (the
1939 : * widget might be in a different document with a different zoom).
1940 : */
1941 : virtual nsIWidget* GetNearestWidget(nsPoint& aOffset) const;
1942 :
1943 : /**
1944 : * Get the "type" of the frame. May return a NULL atom pointer
1945 : *
1946 : * @see nsGkAtoms
1947 : */
1948 : virtual nsIAtom* GetType() const = 0;
1949 :
1950 : /**
1951 : * Returns a transformation matrix that converts points in this frame's
1952 : * coordinate space to points in some ancestor frame's coordinate space.
1953 : * The frame decides which ancestor it will use as a reference point.
1954 : * If this frame has no ancestor, aOutAncestor will be set to null.
1955 : *
1956 : * @param aStopAtAncestor don't look further than aStopAtAncestor. If null,
1957 : * all ancestors (including across documents) will be traversed.
1958 : * @param aOutAncestor [out] The ancestor frame the frame has chosen. If
1959 : * this frame has no ancestor, *aOutAncestor will be set to null.
1960 : * @return A gfxMatrix that converts points in this frame's coordinate space
1961 : * into points in aOutAncestor's coordinate space.
1962 : */
1963 : virtual gfx3DMatrix GetTransformMatrix(nsIFrame* aStopAtAncestor,
1964 : nsIFrame **aOutAncestor);
1965 :
1966 : /**
1967 : * Bit-flags to pass to IsFrameOfType()
1968 : */
1969 : enum {
1970 : eMathML = 1 << 0,
1971 : eSVG = 1 << 1,
1972 : eSVGForeignObject = 1 << 2,
1973 : eSVGContainer = 1 << 3,
1974 : eSVGGeometry = 1 << 4,
1975 : eSVGPaintServer = 1 << 5,
1976 : eBidiInlineContainer = 1 << 6,
1977 : // the frame is for a replaced element, such as an image
1978 : eReplaced = 1 << 7,
1979 : // Frame that contains a block but looks like a replaced element
1980 : // from the outside
1981 : eReplacedContainsBlock = 1 << 8,
1982 : // A frame that participates in inline reflow, i.e., one that
1983 : // requires nsHTMLReflowState::mLineLayout.
1984 : eLineParticipant = 1 << 9,
1985 : eXULBox = 1 << 10,
1986 : eCanContainOverflowContainers = 1 << 11,
1987 : eBlockFrame = 1 << 12,
1988 : // If this bit is set, the frame doesn't allow ignorable whitespace as
1989 : // children. For example, the whitespace between <table>\n<tr>\n<td>
1990 : // will be excluded during the construction of children.
1991 : eExcludesIgnorableWhitespace = 1 << 13,
1992 :
1993 : // These are to allow nsFrame::Init to assert that IsFrameOfType
1994 : // implementations all call the base class method. They are only
1995 : // meaningful in DEBUG builds.
1996 : eDEBUGAllFrames = 1 << 30,
1997 : eDEBUGNoFrames = 1 << 31
1998 : };
1999 :
2000 : /**
2001 : * API for doing a quick check if a frame is of a given
2002 : * type. Returns true if the frame matches ALL flags passed in.
2003 : *
2004 : * Implementations should always override with inline virtual
2005 : * functions that call the base class's IsFrameOfType method.
2006 : */
2007 0 : virtual bool IsFrameOfType(PRUint32 aFlags) const
2008 : {
2009 : #ifdef DEBUG
2010 0 : return !(aFlags & ~(nsIFrame::eDEBUGAllFrames));
2011 : #else
2012 : return !aFlags;
2013 : #endif
2014 : }
2015 :
2016 : /**
2017 : * Returns true if the frame is a block wrapper.
2018 : */
2019 : bool IsBlockWrapper() const;
2020 :
2021 : /**
2022 : * Get this frame's CSS containing block.
2023 : *
2024 : * The algorithm is defined in
2025 : * http://www.w3.org/TR/CSS2/visudet.html#containing-block-details.
2026 : */
2027 : nsIFrame* GetContainingBlock() const;
2028 :
2029 : /**
2030 : * Is this frame a containing block for floating elements?
2031 : * Note that very few frames are, so default to false.
2032 : */
2033 0 : virtual bool IsFloatContainingBlock() const { return false; }
2034 :
2035 : /**
2036 : * Is this a leaf frame? Frames that want the frame constructor to be able
2037 : * to construct kids for them should return false, all others should return
2038 : * true. Note that returning true here does not mean that the frame _can't_
2039 : * have kids. It could still have kids created via
2040 : * nsIAnonymousContentCreator. Returning true indicates that "normal"
2041 : * (non-anonymous, XBL-bound, CSS generated content, etc) children should not
2042 : * be constructed.
2043 : */
2044 : virtual bool IsLeaf() const;
2045 :
2046 : /**
2047 : * This must only be called on frames that are display roots (see
2048 : * nsLayoutUtils::GetDisplayRootFrame). This causes all invalidates
2049 : * reaching this frame to be performed asynchronously off an event,
2050 : * instead of being applied to the widget immediately. Also,
2051 : * invalidation of areas in aExcludeRegion is ignored completely
2052 : * for invalidates with INVALIDATE_EXCLUDE_CURRENT_PAINT specified.
2053 : * These can't be nested; two invocations of
2054 : * BeginDeferringInvalidatesForDisplayRoot for a frame must have a
2055 : * EndDeferringInvalidatesForDisplayRoot between them.
2056 : */
2057 : void BeginDeferringInvalidatesForDisplayRoot(const nsRegion& aExcludeRegion);
2058 :
2059 : /**
2060 : * Cancel the most recent BeginDeferringInvalidatesForDisplayRoot.
2061 : */
2062 : void EndDeferringInvalidatesForDisplayRoot();
2063 :
2064 : /**
2065 : * Mark this frame as using active layers. This marking will time out
2066 : * after a short period. This call does no immediate invalidation,
2067 : * but when the mark times out, we'll invalidate the frame's overflow
2068 : * area.
2069 : * @param aChangeHint nsChangeHint_UpdateTransformLayer or
2070 : * nsChangeHint_UpdateOpacityLayer or 0, depending on whether the change
2071 : * triggering the activity is a changing transform, changing opacity, or
2072 : * something else.
2073 : */
2074 : void MarkLayersActive(nsChangeHint aHint);
2075 : /**
2076 : * Return true if this frame is marked as needing active layers.
2077 : */
2078 : bool AreLayersMarkedActive();
2079 : /**
2080 : * Return true if this frame is marked as needing active layers.
2081 : * @param aChangeHint nsChangeHint_UpdateTransformLayer or
2082 : * nsChangeHint_UpdateOpacityLayer. We return true only if
2083 : * a change in the transform or opacity has been recorded while layers have
2084 : * been marked active for this frame.
2085 : */
2086 : bool AreLayersMarkedActive(nsChangeHint aChangeHint);
2087 :
2088 : /**
2089 : * @param aFlags see InvalidateInternal below
2090 : */
2091 : void InvalidateWithFlags(const nsRect& aDamageRect, PRUint32 aFlags);
2092 :
2093 : /**
2094 : * Invalidate part of the frame by asking the view manager to repaint.
2095 : * aDamageRect is allowed to extend outside the frame's bounds. We'll do the right
2096 : * thing.
2097 : * We deliberately don't have an Invalidate() method that defaults to the frame's bounds.
2098 : * We want all callers to *think* about what has changed in the frame and what area might
2099 : * need to be repainted.
2100 : *
2101 : * @param aDamageRect is in the frame's local coordinate space
2102 : */
2103 0 : void Invalidate(const nsRect& aDamageRect)
2104 0 : { return InvalidateWithFlags(aDamageRect, 0); }
2105 :
2106 : /**
2107 : * As Invalidate above, except that this should be called when the
2108 : * rendering that has changed is performed using layers so we can avoid
2109 : * updating the contents of ThebesLayers.
2110 : * If the frame has a dedicated layer rendering this display item, we
2111 : * return that layer.
2112 : * @param aDisplayItemKey must not be zero; indicates the kind of display
2113 : * item that is being invalidated.
2114 : */
2115 : Layer* InvalidateLayer(const nsRect& aDamageRect, PRUint32 aDisplayItemKey);
2116 :
2117 : /**
2118 : * Invalidate the area of the parent that's covered by the transformed
2119 : * visual overflow rect of this frame. Don't depend on the transform style
2120 : * for this frame, in case that's changed since this frame was painted.
2121 : */
2122 : void InvalidateTransformLayer();
2123 :
2124 : /**
2125 : * Helper function that can be overridden by frame classes. The rectangle
2126 : * (plus aOffsetX/aOffsetY) is relative to this frame.
2127 : *
2128 : * The offset is given as two coords rather than as an nsPoint because
2129 : * gcc optimizes it better that way, in particular in the default
2130 : * implementation that passes the area to the parent frame becomes a tail
2131 : * call.
2132 : *
2133 : * The default implementation will crash if the frame has no parent so
2134 : * frames without parents MUST* override.
2135 : *
2136 : * @param aForChild if the invalidation is coming from a child frame, this
2137 : * is the frame; otherwise, this is null.
2138 : * @param aFlags INVALIDATE_IMMEDIATE: repaint now if true, repaint later if false.
2139 : * In case it's true, pending notifications will be flushed which
2140 : * could cause frames to be deleted (including |this|).
2141 : * @param aFlags INVALIDATE_CROSS_DOC: true if the invalidation
2142 : * originated in a subdocument
2143 : * @param aFlags INVALIDATE_REASON_SCROLL_BLIT: set if the invalidation
2144 : * was really just the scroll machinery copying pixels from one
2145 : * part of the window to another
2146 : * @param aFlags INVALIDATE_REASON_SCROLL_REPAINT: set if the invalidation
2147 : * was triggered by scrolling
2148 : * @param aFlags INVALIDATE_NO_THEBES_LAYERS: don't invalidate the
2149 : * ThebesLayers of any container layer owned by an ancestor. Set this
2150 : * only if ThebesLayers definitely don't need to be updated.
2151 : * @param aFlags INVALIDATE_ONLY_THEBES_LAYERS: invalidate only in the
2152 : * ThebesLayers of the nearest container layer.
2153 : * @param aFlags INVALIDATE_EXCLUDE_CURRENT_PAINT: if the invalidation
2154 : * occurs while we're painting (to be precise, while
2155 : * BeginDeferringInvalidatesForDisplayRoot is active on the display root),
2156 : * then invalidation in the current paint region is simply discarded.
2157 : * Use this flag if areas that are being painted do not need
2158 : * to be invalidated. By default, when this flag is not specified,
2159 : * areas that are invalidated while currently being painted will be repainted
2160 : * again.
2161 : * This flag is useful when, during painting, FrameLayerBuilder discovers that
2162 : * a region of the window needs to be drawn differently, and that region
2163 : * may or may not be contained in the currently painted region.
2164 : * @param aFlags INVALIDATE_NO_UPDATE_LAYER_TREE: display lists and the
2165 : * layer tree do not need to be updated. This can be used when the layer
2166 : * tree has already been updated outside a transaction, e.g. via
2167 : * ImageContainer::SetCurrentImage.
2168 : */
2169 : enum {
2170 : INVALIDATE_IMMEDIATE = 0x01,
2171 : INVALIDATE_CROSS_DOC = 0x02,
2172 : INVALIDATE_REASON_SCROLL_BLIT = 0x04,
2173 : INVALIDATE_REASON_SCROLL_REPAINT = 0x08,
2174 : INVALIDATE_REASON_MASK = INVALIDATE_REASON_SCROLL_BLIT |
2175 : INVALIDATE_REASON_SCROLL_REPAINT,
2176 : INVALIDATE_NO_THEBES_LAYERS = 0x10,
2177 : INVALIDATE_ONLY_THEBES_LAYERS = 0x20,
2178 : INVALIDATE_EXCLUDE_CURRENT_PAINT = 0x40,
2179 : INVALIDATE_NO_UPDATE_LAYER_TREE = 0x80,
2180 : INVALIDATE_ALREADY_TRANSFORMED = 0x100
2181 : };
2182 : virtual void InvalidateInternal(const nsRect& aDamageRect,
2183 : nscoord aOffsetX, nscoord aOffsetY,
2184 : nsIFrame* aForChild, PRUint32 aFlags);
2185 :
2186 : /**
2187 : * Helper function that funnels an InvalidateInternal request up to the
2188 : * parent. This function is used so that if MOZ_SVG is not defined, we still
2189 : * have unified control paths in the InvalidateInternal chain.
2190 : *
2191 : * @param aDamageRect The rect to invalidate.
2192 : * @param aX The x offset from the origin of this frame to the rectangle.
2193 : * @param aY The y offset from the origin of this frame to the rectangle.
2194 : * @param aImmediate Whether to redraw immediately.
2195 : * @return None, though this funnels the request up to the parent frame.
2196 : */
2197 : void InvalidateInternalAfterResize(const nsRect& aDamageRect, nscoord aX,
2198 : nscoord aY, PRUint32 aFlags);
2199 :
2200 : /**
2201 : * Take two rectangles in the coordinate system of this frame which
2202 : * have the same origin and invalidate the difference between them.
2203 : * This is a helper method to be used when a frame is being resized.
2204 : *
2205 : * @param aR1 the first rectangle
2206 : * @param aR2 the second rectangle
2207 : */
2208 : void InvalidateRectDifference(const nsRect& aR1, const nsRect& aR2);
2209 :
2210 : /**
2211 : * Invalidate the entire frame subtree for this frame. Invalidates this
2212 : * frame's overflow rect, and also ensures that all ThebesLayer children
2213 : * of ContainerLayers associated with frames in this subtree are
2214 : * completely invalidated.
2215 : */
2216 : void InvalidateFrameSubtree();
2217 :
2218 : /**
2219 : * Invalidates this frame's visual overflow rect. Does not necessarily
2220 : * cause ThebesLayers for descendant frames to be repainted; only this
2221 : * frame can be relied on to be repainted.
2222 : */
2223 : void InvalidateOverflowRect();
2224 :
2225 : /**
2226 : * Returns a rect that encompasses everything that might be painted by
2227 : * this frame. This includes this frame, all its descendent frames, this
2228 : * frame's outline, and descentant frames' outline, but does not include
2229 : * areas clipped out by the CSS "overflow" and "clip" properties.
2230 : *
2231 : * HasOverflowRects() (below) will return true when this overflow
2232 : * rect has been explicitly set, even if it matches mRect.
2233 : * XXX Note: because of a space optimization using the formula above,
2234 : * during reflow this function does not give accurate data if
2235 : * FinishAndStoreOverflow has been called but mRect hasn't yet been
2236 : * updated yet. FIXME: This actually isn't true, but it should be.
2237 : *
2238 : * The visual overflow rect should NEVER be used for things that
2239 : * affect layout. The scrollable overflow rect is permitted to affect
2240 : * layout.
2241 : *
2242 : * @return the rect relative to this frame's origin, but after
2243 : * CSS transforms have been applied (i.e. not really this frame's coordinate
2244 : * system, and may not contain the frame's border-box, e.g. if there
2245 : * is a CSS transform scaling it down)
2246 : */
2247 : nsRect GetVisualOverflowRect() const {
2248 : return GetOverflowRect(eVisualOverflow);
2249 : }
2250 :
2251 : /**
2252 : * Returns a rect that encompasses the area of this frame that the
2253 : * user should be able to scroll to reach. This is similar to
2254 : * GetVisualOverflowRect, but does not include outline or shadows, and
2255 : * may in the future include more margins than visual overflow does.
2256 : * It does not include areas clipped out by the CSS "overflow" and
2257 : * "clip" properties.
2258 : *
2259 : * HasOverflowRects() (below) will return true when this overflow
2260 : * rect has been explicitly set, even if it matches mRect.
2261 : * XXX Note: because of a space optimization using the formula above,
2262 : * during reflow this function does not give accurate data if
2263 : * FinishAndStoreOverflow has been called but mRect hasn't yet been
2264 : * updated yet.
2265 : *
2266 : * @return the rect relative to this frame's origin, but after
2267 : * CSS transforms have been applied (i.e. not really this frame's coordinate
2268 : * system, and may not contain the frame's border-box, e.g. if there
2269 : * is a CSS transform scaling it down)
2270 : */
2271 0 : nsRect GetScrollableOverflowRect() const {
2272 0 : return GetOverflowRect(eScrollableOverflow);
2273 : }
2274 :
2275 : nsRect GetOverflowRect(nsOverflowType aType) const;
2276 :
2277 : nsOverflowAreas GetOverflowAreas() const;
2278 :
2279 : /**
2280 : * Same as GetScrollableOverflowRect, except relative to the parent
2281 : * frame.
2282 : *
2283 : * @return the rect relative to the parent frame, in the parent frame's
2284 : * coordinate system
2285 : */
2286 : nsRect GetScrollableOverflowRectRelativeToParent() const;
2287 :
2288 : /**
2289 : * Like GetVisualOverflowRect, except in this frame's
2290 : * coordinate system (before transforms are applied).
2291 : *
2292 : * @return the rect relative to this frame, before any CSS transforms have
2293 : * been applied, i.e. in this frame's coordinate system
2294 : */
2295 : nsRect GetVisualOverflowRectRelativeToSelf() const;
2296 :
2297 : /**
2298 : * Store the overflow area in the frame's mOverflow.mVisualDeltas
2299 : * fields or as a frame property in the frame manager so that it can
2300 : * be retrieved later without reflowing the frame. Returns true if either of
2301 : * the overflow areas changed.
2302 : */
2303 : bool FinishAndStoreOverflow(nsOverflowAreas& aOverflowAreas,
2304 : nsSize aNewSize);
2305 :
2306 0 : bool FinishAndStoreOverflow(nsHTMLReflowMetrics* aMetrics) {
2307 : return FinishAndStoreOverflow(aMetrics->mOverflowAreas,
2308 0 : nsSize(aMetrics->width, aMetrics->height));
2309 : }
2310 :
2311 : /**
2312 : * Returns whether the frame has an overflow rect that is different from
2313 : * its border-box.
2314 : */
2315 : bool HasOverflowAreas() const {
2316 : return mOverflow.mType != NS_FRAME_OVERFLOW_NONE;
2317 : }
2318 :
2319 : /**
2320 : * Removes any stored overflow rects (visual and scrollable) from the frame.
2321 : * Returns true if the overflow changed.
2322 : */
2323 : bool ClearOverflowRects();
2324 :
2325 : /**
2326 : * Determine whether borders should not be painted on certain sides of the
2327 : * frame.
2328 : */
2329 0 : virtual PRIntn GetSkipSides() const { return 0; }
2330 :
2331 : /**
2332 : * @returns true if this frame is selected.
2333 : */
2334 0 : bool IsSelected() const {
2335 0 : return (GetContent() && GetContent()->IsSelectionDescendant()) ?
2336 0 : IsFrameSelected() : false;
2337 : }
2338 :
2339 : /**
2340 : * called to discover where this frame, or a parent frame has user-select style
2341 : * applied, which affects that way that it is selected.
2342 : *
2343 : * @param aIsSelectable out param. Set to true if the frame can be selected
2344 : * (i.e. is not affected by user-select: none)
2345 : * @param aSelectStyle out param. Returns the type of selection style found
2346 : * (using values defined in nsStyleConsts.h).
2347 : */
2348 : NS_IMETHOD IsSelectable(bool* aIsSelectable, PRUint8* aSelectStyle) const = 0;
2349 :
2350 : /**
2351 : * Called to retrieve the SelectionController associated with the frame.
2352 : * @param aSelCon will contain the selection controller associated with
2353 : * the frame.
2354 : */
2355 : NS_IMETHOD GetSelectionController(nsPresContext *aPresContext, nsISelectionController **aSelCon) = 0;
2356 :
2357 : /**
2358 : * Call to get nsFrameSelection for this frame.
2359 : */
2360 : already_AddRefed<nsFrameSelection> GetFrameSelection();
2361 :
2362 : /**
2363 : * GetConstFrameSelection returns an object which methods are safe to use for
2364 : * example in nsIFrame code.
2365 : */
2366 : const nsFrameSelection* GetConstFrameSelection() const;
2367 :
2368 : /**
2369 : * called to find the previous/next character, word, or line returns the actual
2370 : * nsIFrame and the frame offset. THIS DOES NOT CHANGE SELECTION STATE
2371 : * uses frame's begin selection state to start. if no selection on this frame will
2372 : * return NS_ERROR_FAILURE
2373 : * @param aPOS is defined in nsFrameSelection
2374 : */
2375 : NS_IMETHOD PeekOffset(nsPeekOffsetStruct *aPos);
2376 :
2377 : /**
2378 : * called to find the previous/next selectable leaf frame.
2379 : * @param aDirection [in] the direction to move in (eDirPrevious or eDirNext)
2380 : * @param aVisual [in] whether bidi caret behavior is visual (true) or logical (false)
2381 : * @param aJumpLines [in] whether to allow jumping across line boundaries
2382 : * @param aScrollViewStop [in] whether to stop when reaching a scroll frame boundary
2383 : * @param aOutFrame [out] the previous/next selectable leaf frame
2384 : * @param aOutOffset [out] 0 indicates that we arrived at the beginning of the output frame;
2385 : * -1 indicates that we arrived at its end.
2386 : * @param aOutJumpedLine [out] whether this frame and the returned frame are on different lines
2387 : */
2388 : nsresult GetFrameFromDirection(nsDirection aDirection, bool aVisual,
2389 : bool aJumpLines, bool aScrollViewStop,
2390 : nsIFrame** aOutFrame, PRInt32* aOutOffset, bool* aOutJumpedLine);
2391 :
2392 : /**
2393 : * called to see if the children of the frame are visible from indexstart to index end.
2394 : * this does not change any state. returns true only if the indexes are valid and any of
2395 : * the children are visible. for textframes this index is the character index.
2396 : * if aStart = aEnd result will be false
2397 : * @param aStart start index of first child from 0-N (number of children)
2398 : * @param aEnd end index of last child from 0-N
2399 : * @param aRecurse should this frame talk to siblings to get to the contents other children?
2400 : * @param aFinished did this frame have the aEndIndex? or is there more work to do
2401 : * @param _retval return value true or false. false = range is not rendered.
2402 : */
2403 : NS_IMETHOD CheckVisibility(nsPresContext* aContext, PRInt32 aStartIndex, PRInt32 aEndIndex, bool aRecurse, bool *aFinished, bool *_retval)=0;
2404 :
2405 : /**
2406 : * Called to tell a frame that one of its child frames is dirty (i.e.,
2407 : * has the NS_FRAME_IS_DIRTY *or* NS_FRAME_HAS_DIRTY_CHILDREN bit
2408 : * set). This should always set the NS_FRAME_HAS_DIRTY_CHILDREN on
2409 : * the frame, and may do other work.
2410 : */
2411 : virtual void ChildIsDirty(nsIFrame* aChild) = 0;
2412 :
2413 : /**
2414 : * Called to retrieve this frame's accessible.
2415 : * If this frame implements Accessibility return a valid accessible
2416 : * If not return NS_ERROR_NOT_IMPLEMENTED.
2417 : * Note: nsAccessible must be refcountable. Do not implement directly on your frame
2418 : * Use a mediatior of some kind.
2419 : */
2420 : #ifdef ACCESSIBILITY
2421 : virtual already_AddRefed<nsAccessible> CreateAccessible() = 0;
2422 : #endif
2423 :
2424 : /**
2425 : * Get the frame whose style context should be the parent of this
2426 : * frame's style context (i.e., provide the parent style context).
2427 : * This frame must either be an ancestor of this frame or a child. If
2428 : * this returns a child frame, then the child frame must be sure to
2429 : * return a grandparent or higher! Furthermore, if a child frame is
2430 : * returned it must have the same GetContent() as this frame.
2431 : *
2432 : * @return The frame whose style context should be the parent of this frame's
2433 : * style context. Null is permitted, and means that this frame's
2434 : * style context should be the root of the style context tree.
2435 : */
2436 : virtual nsIFrame* GetParentStyleContextFrame() const = 0;
2437 :
2438 : /**
2439 : * Determines whether a frame is visible for painting;
2440 : * taking into account whether it is painting a selection or printing.
2441 : */
2442 : bool IsVisibleForPainting(nsDisplayListBuilder* aBuilder);
2443 : /**
2444 : * Determines whether a frame is visible for painting or collapsed;
2445 : * taking into account whether it is painting a selection or printing,
2446 : */
2447 : bool IsVisibleOrCollapsedForPainting(nsDisplayListBuilder* aBuilder);
2448 : /**
2449 : * As above, but slower because we have to recompute some stuff that
2450 : * aBuilder already has.
2451 : */
2452 : bool IsVisibleForPainting();
2453 : /**
2454 : * Check whether this frame is visible in the current selection. Returns
2455 : * true if there is no current selection.
2456 : */
2457 : bool IsVisibleInSelection(nsDisplayListBuilder* aBuilder);
2458 :
2459 : /**
2460 : * Overridable function to determine whether this frame should be considered
2461 : * "in" the given non-null aSelection for visibility purposes.
2462 : */
2463 : virtual bool IsVisibleInSelection(nsISelection* aSelection);
2464 :
2465 : /**
2466 : * Determines whether this frame is a pseudo stacking context, looking
2467 : * only as style --- i.e., assuming that it's in-flow and not a replaced
2468 : * element.
2469 : */
2470 : bool IsPseudoStackingContextFromStyle() {
2471 : const nsStyleDisplay* disp = GetStyleDisplay();
2472 : return disp->mOpacity != 1.0f || disp->IsPositioned() || disp->IsFloating();
2473 : }
2474 :
2475 0 : virtual bool HonorPrintBackgroundSettings() { return true; }
2476 :
2477 : /**
2478 : * Determine whether the frame is logically empty, which is roughly
2479 : * whether the layout would be the same whether or not the frame is
2480 : * present. Placeholder frames should return true. Block frames
2481 : * should be considered empty whenever margins collapse through them,
2482 : * even though those margins are relevant. Text frames containing
2483 : * only whitespace that does not contribute to the height of the line
2484 : * should return true.
2485 : */
2486 : virtual bool IsEmpty() = 0;
2487 : /**
2488 : * Return the same as IsEmpty(). This may only be called after the frame
2489 : * has been reflowed and before any further style or content changes.
2490 : */
2491 : virtual bool CachedIsEmpty();
2492 : /**
2493 : * Determine whether the frame is logically empty, assuming that all
2494 : * its children are empty.
2495 : */
2496 : virtual bool IsSelfEmpty() = 0;
2497 :
2498 : /**
2499 : * IsGeneratedContentFrame returns whether a frame corresponds to
2500 : * generated content
2501 : *
2502 : * @return whether the frame correspods to generated content
2503 : */
2504 0 : bool IsGeneratedContentFrame() {
2505 0 : return (mState & NS_FRAME_GENERATED_CONTENT) != 0;
2506 : }
2507 :
2508 : /**
2509 : * IsPseudoFrame returns whether a frame is a pseudo frame (eg an
2510 : * anonymous table-row frame created for a CSS table-cell without an
2511 : * enclosing table-row.
2512 : *
2513 : * @param aParentContent the content node corresponding to the parent frame
2514 : * @return whether the frame is a pseudo frame
2515 : */
2516 0 : bool IsPseudoFrame(nsIContent* aParentContent) {
2517 0 : return mContent == aParentContent;
2518 : }
2519 :
2520 0 : FrameProperties Properties() const {
2521 0 : return FrameProperties(PresContext()->PropertyTable(), this);
2522 : }
2523 :
2524 : NS_DECLARE_FRAME_PROPERTY(BaseLevelProperty, nsnull)
2525 : NS_DECLARE_FRAME_PROPERTY(EmbeddingLevelProperty, nsnull)
2526 :
2527 : #define NS_GET_BASE_LEVEL(frame) \
2528 : NS_PTR_TO_INT32(frame->Properties().Get(nsIFrame::BaseLevelProperty()))
2529 :
2530 : #define NS_GET_EMBEDDING_LEVEL(frame) \
2531 : NS_PTR_TO_INT32(frame->Properties().Get(nsIFrame::EmbeddingLevelProperty()))
2532 :
2533 : /**
2534 : * Return true if and only if this frame obeys visibility:hidden.
2535 : * if it does not, then nsContainerFrame will hide its view even though
2536 : * this means children can't be made visible again.
2537 : */
2538 0 : virtual bool SupportsVisibilityHidden() { return true; }
2539 :
2540 : /**
2541 : * Returns true if the frame has a valid clip rect set via the 'clip'
2542 : * property, and the 'clip' property applies to this frame. The 'clip'
2543 : * property applies to HTML frames if they are absolutely positioned. The
2544 : * 'clip' property applies to SVG frames regardless of the value of the
2545 : * 'position' property.
2546 : *
2547 : * If this method returns true, then we also set aRect to the computed clip
2548 : * rect, with coordinates relative to this frame's origin. aRect must not be
2549 : * null!
2550 : */
2551 : bool GetClipPropClipRect(const nsStyleDisplay* aDisp, nsRect* aRect,
2552 : const nsSize& aSize) const;
2553 :
2554 : /**
2555 : * Check if this frame is focusable and in the current tab order.
2556 : * Tabbable is indicated by a nonnegative tabindex & is a subset of focusable.
2557 : * For example, only the selected radio button in a group is in the
2558 : * tab order, unless the radio group has no selection in which case
2559 : * all of the visible, non-disabled radio buttons in the group are
2560 : * in the tab order. On the other hand, all of the visible, non-disabled
2561 : * radio buttons are always focusable via clicking or script.
2562 : * Also, depending on the pref accessibility.tabfocus some widgets may be
2563 : * focusable but removed from the tab order. This is the default on
2564 : * Mac OS X, where fewer items are focusable.
2565 : * @param [in, optional] aTabIndex the computed tab index
2566 : * < 0 if not tabbable
2567 : * == 0 if in normal tab order
2568 : * > 0 can be tabbed to in the order specified by this value
2569 : * @param [in, optional] aWithMouse, is this focus query for mouse clicking
2570 : * @return whether the frame is focusable via mouse, kbd or script.
2571 : */
2572 : virtual bool IsFocusable(PRInt32 *aTabIndex = nsnull, bool aWithMouse = false);
2573 :
2574 : // BOX LAYOUT METHODS
2575 : // These methods have been migrated from nsIBox and are in the process of
2576 : // being refactored. DO NOT USE OUTSIDE OF XUL.
2577 0 : bool IsBoxFrame() const
2578 : {
2579 0 : return IsFrameOfType(nsIFrame::eXULBox);
2580 : }
2581 : bool IsBoxWrapped() const
2582 : { return (!IsBoxFrame() && mParent && mParent->IsBoxFrame()); }
2583 :
2584 : enum Halignment {
2585 : hAlign_Left,
2586 : hAlign_Right,
2587 : hAlign_Center
2588 : };
2589 :
2590 : enum Valignment {
2591 : vAlign_Top,
2592 : vAlign_Middle,
2593 : vAlign_BaseLine,
2594 : vAlign_Bottom
2595 : };
2596 :
2597 : /**
2598 : * This calculates the minimum size required for a box based on its state
2599 : * @param[in] aBoxLayoutState The desired state to calculate for
2600 : * @return The minimum size
2601 : */
2602 : virtual nsSize GetMinSize(nsBoxLayoutState& aBoxLayoutState) = 0;
2603 :
2604 : /**
2605 : * This calculates the preferred size of a box based on its state
2606 : * @param[in] aBoxLayoutState The desired state to calculate for
2607 : * @return The preferred size
2608 : */
2609 : virtual nsSize GetPrefSize(nsBoxLayoutState& aBoxLayoutState) = 0;
2610 :
2611 : /**
2612 : * This calculates the maximum size for a box based on its state
2613 : * @param[in] aBoxLayoutState The desired state to calculate for
2614 : * @return The maximum size
2615 : */
2616 : virtual nsSize GetMaxSize(nsBoxLayoutState& aBoxLayoutState) = 0;
2617 :
2618 : /**
2619 : * This returns the minimum size for the scroll area if this frame is
2620 : * being scrolled. Usually it's (0,0).
2621 : */
2622 : virtual nsSize GetMinSizeForScrollArea(nsBoxLayoutState& aBoxLayoutState) = 0;
2623 :
2624 : // Implemented in nsBox, used in nsBoxFrame
2625 : PRUint32 GetOrdinal(nsBoxLayoutState& aBoxLayoutState);
2626 :
2627 : virtual nscoord GetFlex(nsBoxLayoutState& aBoxLayoutState) = 0;
2628 : virtual nscoord GetBoxAscent(nsBoxLayoutState& aBoxLayoutState) = 0;
2629 : virtual bool IsCollapsed() = 0;
2630 : // This does not alter the overflow area. If the caller is changing
2631 : // the box size, the caller is responsible for updating the overflow
2632 : // area. It's enough to just call Layout or SyncLayout on the
2633 : // box. You can pass true to aRemoveOverflowArea as a
2634 : // convenience.
2635 : virtual void SetBounds(nsBoxLayoutState& aBoxLayoutState, const nsRect& aRect,
2636 : bool aRemoveOverflowAreas = false) = 0;
2637 : NS_HIDDEN_(nsresult) Layout(nsBoxLayoutState& aBoxLayoutState);
2638 : nsIBox* GetChildBox() const
2639 : {
2640 : // box layout ends at box-wrapped frames, so don't allow these frames
2641 : // to report child boxes.
2642 : return IsBoxFrame() ? GetFirstPrincipalChild() : nsnull;
2643 : }
2644 : nsIBox* GetNextBox() const
2645 : {
2646 : return (mParent && mParent->IsBoxFrame()) ? mNextSibling : nsnull;
2647 : }
2648 : nsIBox* GetParentBox() const
2649 : {
2650 : return (mParent && mParent->IsBoxFrame()) ? mParent : nsnull;
2651 : }
2652 : // Box methods. Note that these do NOT just get the CSS border, padding,
2653 : // etc. They also talk to nsITheme.
2654 : NS_IMETHOD GetBorderAndPadding(nsMargin& aBorderAndPadding);
2655 : NS_IMETHOD GetBorder(nsMargin& aBorder)=0;
2656 : NS_IMETHOD GetPadding(nsMargin& aBorderAndPadding)=0;
2657 : NS_IMETHOD GetMargin(nsMargin& aMargin)=0;
2658 0 : virtual void SetLayoutManager(nsBoxLayout* aLayout) { }
2659 0 : virtual nsBoxLayout* GetLayoutManager() { return nsnull; }
2660 : NS_HIDDEN_(nsresult) GetClientRect(nsRect& aContentRect);
2661 :
2662 : // For nsSprocketLayout
2663 : virtual Valignment GetVAlign() const = 0;
2664 : virtual Halignment GetHAlign() const = 0;
2665 :
2666 : bool IsHorizontal() const { return (mState & NS_STATE_IS_HORIZONTAL) != 0; }
2667 : bool IsNormalDirection() const { return (mState & NS_STATE_IS_DIRECTION_NORMAL) != 0; }
2668 :
2669 : NS_HIDDEN_(nsresult) Redraw(nsBoxLayoutState& aState, const nsRect* aRect = nsnull);
2670 : NS_IMETHOD RelayoutChildAtOrdinal(nsBoxLayoutState& aState, nsIBox* aChild)=0;
2671 : // XXX take this out after we've branched
2672 0 : virtual bool GetMouseThrough() const { return false; };
2673 :
2674 : #ifdef DEBUG_LAYOUT
2675 : NS_IMETHOD SetDebug(nsBoxLayoutState& aState, bool aDebug)=0;
2676 : NS_IMETHOD GetDebug(bool& aDebug)=0;
2677 :
2678 : NS_IMETHOD DumpBox(FILE* out)=0;
2679 : #endif
2680 :
2681 : /**
2682 : * @return true if this text frame ends with a newline character. It
2683 : * should return false if this is not a text frame.
2684 : */
2685 : virtual bool HasTerminalNewline() const;
2686 :
2687 : static bool AddCSSPrefSize(nsIBox* aBox, nsSize& aSize, bool& aWidth, bool& aHeightSet);
2688 : static bool AddCSSMinSize(nsBoxLayoutState& aState, nsIBox* aBox,
2689 : nsSize& aSize, bool& aWidth, bool& aHeightSet);
2690 : static bool AddCSSMaxSize(nsIBox* aBox, nsSize& aSize, bool& aWidth, bool& aHeightSet);
2691 : static bool AddCSSFlex(nsBoxLayoutState& aState, nsIBox* aBox, nscoord& aFlex);
2692 :
2693 : // END OF BOX LAYOUT METHODS
2694 : // The above methods have been migrated from nsIBox and are in the process of
2695 : // being refactored. DO NOT USE OUTSIDE OF XUL.
2696 :
2697 : /**
2698 : * gets the first or last possible caret position within the frame
2699 : *
2700 : * @param [in] aStart
2701 : * true for getting the first possible caret position
2702 : * false for getting the last possible caret position
2703 : * @return The caret position in an nsPeekOffsetStruct (the
2704 : * fields set are mResultContent and mContentOffset;
2705 : * the returned value is a 'best effort' in case errors
2706 : * are encountered rummaging through the frame.
2707 : */
2708 : nsPeekOffsetStruct GetExtremeCaretPosition(bool aStart);
2709 :
2710 : /**
2711 : * Same thing as nsFrame::CheckInvalidateSizeChange, but more flexible. The
2712 : * implementation of this method must not depend on the mRect or
2713 : * GetVisualOverflowRect() of the frame! Note that it's safe to
2714 : * assume in this method that the frame origin didn't change. If it
2715 : * did, whoever moved the frame will invalidate as needed anyway.
2716 : */
2717 : void CheckInvalidateSizeChange(const nsRect& aOldRect,
2718 : const nsRect& aOldVisualOverflowRect,
2719 : const nsSize& aNewDesiredSize);
2720 :
2721 : /**
2722 : * Get a line iterator for this frame, if supported.
2723 : *
2724 : * @return nsnull if no line iterator is supported.
2725 : * @note dispose the line iterator using nsILineIterator::DisposeLineIterator
2726 : */
2727 : virtual nsILineIterator* GetLineIterator() = 0;
2728 :
2729 : /**
2730 : * If this frame is a next-in-flow, and its prev-in-flow has something on its
2731 : * overflow list, pull those frames into the child list of this one.
2732 : */
2733 0 : virtual void PullOverflowsFromPrevInFlow() {}
2734 :
2735 : /**
2736 : * Clear the list of child PresShells generated during the last paint
2737 : * so that we can begin generating a new one.
2738 : */
2739 : void ClearPresShellsFromLastPaint() {
2740 : PaintedPresShellList()->Clear();
2741 : }
2742 :
2743 : /**
2744 : * Flag a child PresShell as painted so that it will get its paint count
2745 : * incremented during empty transactions.
2746 : */
2747 : void AddPaintedPresShell(nsIPresShell* shell) {
2748 : PaintedPresShellList()->AppendElement(do_GetWeakReference(shell));
2749 : }
2750 :
2751 : /**
2752 : * Increment the paint count of all child PresShells that were painted during
2753 : * the last repaint.
2754 : */
2755 : void UpdatePaintCountForPaintedPresShells() {
2756 : nsTArray<nsWeakPtr> * list = PaintedPresShellList();
2757 : for (int i = 0, l = list->Length(); i < l; i++) {
2758 : nsCOMPtr<nsIPresShell> shell = do_QueryReferent(list->ElementAt(i));
2759 :
2760 : if (shell) {
2761 : shell->IncrementPaintCount();
2762 : }
2763 : }
2764 : }
2765 :
2766 : /**
2767 : * Accessors for the absolute containing block.
2768 : */
2769 : bool IsAbsoluteContainer() const { return !!(mState & NS_FRAME_HAS_ABSPOS_CHILDREN); }
2770 : bool HasAbsolutelyPositionedChildren() const;
2771 : nsAbsoluteContainingBlock* GetAbsoluteContainingBlock() const;
2772 : virtual void MarkAsAbsoluteContainingBlock();
2773 : // Child frame types override this function to select their own child list name
2774 0 : virtual mozilla::layout::FrameChildListID GetAbsoluteListID() const { return kAbsoluteList; }
2775 :
2776 : // Checks if we (or any of our descendents) have NS_FRAME_PAINTED_THEBES set, and
2777 : // clears this bit if so.
2778 : bool CheckAndClearPaintedState();
2779 :
2780 : // CSS visibility just doesn't cut it because it doesn't inherit through
2781 : // documents. Also if this frame is in a hidden card of a deck then it isn't
2782 : // visible either and that isn't expressed using CSS visibility. Also if it
2783 : // is in a hidden view (there are a few cases left and they are hopefully
2784 : // going away soon).
2785 : // If the VISIBILITY_CROSS_CHROME_CONTENT_BOUNDARY flag is passed then we
2786 : // ignore the chrome/content boundary, otherwise we stop looking when we
2787 : // reach it.
2788 : enum {
2789 : VISIBILITY_CROSS_CHROME_CONTENT_BOUNDARY = 0x01
2790 : };
2791 : bool IsVisibleConsideringAncestors(PRUint32 aFlags = 0) const;
2792 :
2793 : protected:
2794 : // Members
2795 : nsRect mRect;
2796 : nsIContent* mContent;
2797 : nsStyleContext* mStyleContext;
2798 : nsIFrame* mParent;
2799 : private:
2800 : nsIFrame* mNextSibling; // doubly-linked list of frames
2801 : nsIFrame* mPrevSibling; // Do not touch outside SetNextSibling!
2802 :
2803 : void MarkAbsoluteFramesForDisplayList(nsDisplayListBuilder* aBuilder, const nsRect& aDirtyRect);
2804 :
2805 : static void DestroyPaintedPresShellList(void* propertyValue) {
2806 : nsTArray<nsWeakPtr>* list = static_cast<nsTArray<nsWeakPtr>*>(propertyValue);
2807 : list->Clear();
2808 : delete list;
2809 : }
2810 :
2811 : // Stores weak references to all the PresShells that were painted during
2812 : // the last paint event so that we can increment their paint count during
2813 : // empty transactions
2814 : NS_DECLARE_FRAME_PROPERTY(PaintedPresShellsProperty, DestroyPaintedPresShellList)
2815 :
2816 : nsTArray<nsWeakPtr>* PaintedPresShellList() {
2817 : nsTArray<nsWeakPtr>* list = static_cast<nsTArray<nsWeakPtr>*>(
2818 : Properties().Get(PaintedPresShellsProperty())
2819 : );
2820 :
2821 : if (!list) {
2822 : list = new nsTArray<nsWeakPtr>();
2823 : Properties().Set(PaintedPresShellsProperty(), list);
2824 : }
2825 :
2826 : return list;
2827 : }
2828 :
2829 : protected:
2830 : nsFrameState mState;
2831 :
2832 : // When there is an overflow area only slightly larger than mRect,
2833 : // we store a set of four 1-byte deltas from the edges of mRect
2834 : // rather than allocating a whole separate rectangle property.
2835 : // Note that these are unsigned values, all measured "outwards"
2836 : // from the edges of mRect, so /mLeft/ and /mTop/ are reversed from
2837 : // our normal coordinate system.
2838 : // If mOverflow.mType == NS_FRAME_OVERFLOW_LARGE, then the
2839 : // delta values are not meaningful and the overflow area is stored
2840 : // as a separate rect property.
2841 : struct VisualDeltas {
2842 : PRUint8 mLeft;
2843 : PRUint8 mTop;
2844 : PRUint8 mRight;
2845 : PRUint8 mBottom;
2846 : bool operator==(const VisualDeltas& aOther) const
2847 : {
2848 : return mLeft == aOther.mLeft && mTop == aOther.mTop &&
2849 : mRight == aOther.mRight && mBottom == aOther.mBottom;
2850 : }
2851 : bool operator!=(const VisualDeltas& aOther) const
2852 : {
2853 : return !(*this == aOther);
2854 : }
2855 : };
2856 : union {
2857 : PRUint32 mType;
2858 : VisualDeltas mVisualDeltas;
2859 : } mOverflow;
2860 :
2861 : // Helpers
2862 : /**
2863 : * For frames that have top-level windows (top-level viewports,
2864 : * comboboxes, menupoups) this function will invalidate the window.
2865 : */
2866 : void InvalidateRoot(const nsRect& aDamageRect, PRUint32 aFlags);
2867 :
2868 : /**
2869 : * Can we stop inside this frame when we're skipping non-rendered whitespace?
2870 : * @param aForward [in] Are we moving forward (or backward) in content order.
2871 : * @param aOffset [in/out] At what offset into the frame to start looking.
2872 : * on output - what offset was reached (whether or not we found a place to stop).
2873 : * @return true: An appropriate offset was found within this frame,
2874 : * and is given by aOffset.
2875 : * false: Not found within this frame, need to try the next frame.
2876 : */
2877 : virtual bool PeekOffsetNoAmount(bool aForward, PRInt32* aOffset) = 0;
2878 :
2879 : /**
2880 : * Search the frame for the next character
2881 : * @param aForward [in] Are we moving forward (or backward) in content order.
2882 : * @param aOffset [in/out] At what offset into the frame to start looking.
2883 : * on output - what offset was reached (whether or not we found a place to stop).
2884 : * @param aRespectClusters [in] Whether to restrict result to valid cursor locations
2885 : * (between grapheme clusters) - default TRUE maintains "normal" behavior,
2886 : * FALSE is used for selection by "code unit" (instead of "character")
2887 : * @return true: An appropriate offset was found within this frame,
2888 : * and is given by aOffset.
2889 : * false: Not found within this frame, need to try the next frame.
2890 : */
2891 : virtual bool PeekOffsetCharacter(bool aForward, PRInt32* aOffset,
2892 : bool aRespectClusters = true) = 0;
2893 :
2894 : /**
2895 : * Search the frame for the next word boundary
2896 : * @param aForward [in] Are we moving forward (or backward) in content order.
2897 : * @param aWordSelectEatSpace [in] true: look for non-whitespace following
2898 : * whitespace (in the direction of movement).
2899 : * false: look for whitespace following non-whitespace (in the
2900 : * direction of movement).
2901 : * @param aIsKeyboardSelect [in] Was the action initiated by a keyboard operation?
2902 : * If true, punctuation immediately following a word is considered part
2903 : * of that word. Otherwise, a sequence of punctuation is always considered
2904 : * as a word on its own.
2905 : * @param aOffset [in/out] At what offset into the frame to start looking.
2906 : * on output - what offset was reached (whether or not we found a place to stop).
2907 : * @param aState [in/out] the state that is carried from frame to frame
2908 : * @return true: An appropriate offset was found within this frame,
2909 : * and is given by aOffset.
2910 : * false: Not found within this frame, need to try the next frame.
2911 : */
2912 : struct PeekWordState {
2913 : // true when we're still at the start of the search, i.e., we can't return
2914 : // this point as a valid offset!
2915 : bool mAtStart;
2916 : // true when we've encountered at least one character of the pre-boundary type
2917 : // (whitespace if aWordSelectEatSpace is true, non-whitespace otherwise)
2918 : bool mSawBeforeType;
2919 : // true when the last character encountered was punctuation
2920 : bool mLastCharWasPunctuation;
2921 : // true when the last character encountered was whitespace
2922 : bool mLastCharWasWhitespace;
2923 : // true when we've seen non-punctuation since the last whitespace
2924 : bool mSeenNonPunctuationSinceWhitespace;
2925 : // text that's *before* the current frame when aForward is true, *after*
2926 : // the current frame when aForward is false. Only includes the text
2927 : // on the current line.
2928 : nsAutoString mContext;
2929 :
2930 : PeekWordState() : mAtStart(true), mSawBeforeType(false),
2931 : mLastCharWasPunctuation(false), mLastCharWasWhitespace(false),
2932 : mSeenNonPunctuationSinceWhitespace(false) {}
2933 : void SetSawBeforeType() { mSawBeforeType = true; }
2934 : void Update(bool aAfterPunctuation, bool aAfterWhitespace) {
2935 : mLastCharWasPunctuation = aAfterPunctuation;
2936 : mLastCharWasWhitespace = aAfterWhitespace;
2937 : if (aAfterWhitespace) {
2938 : mSeenNonPunctuationSinceWhitespace = false;
2939 : } else if (!aAfterPunctuation) {
2940 : mSeenNonPunctuationSinceWhitespace = true;
2941 : }
2942 : mAtStart = false;
2943 : }
2944 : };
2945 : virtual bool PeekOffsetWord(bool aForward, bool aWordSelectEatSpace, bool aIsKeyboardSelect,
2946 : PRInt32* aOffset, PeekWordState* aState) = 0;
2947 :
2948 : /**
2949 : * Search for the first paragraph boundary before or after the given position
2950 : * @param aPos See description in nsFrameSelection.h. The following fields are
2951 : * used by this method:
2952 : * Input: mDirection
2953 : * Output: mResultContent, mContentOffset
2954 : */
2955 : nsresult PeekOffsetParagraph(nsPeekOffsetStruct *aPos);
2956 :
2957 : private:
2958 : nsOverflowAreas* GetOverflowAreasProperty();
2959 : nsRect GetVisualOverflowFromDeltas() const {
2960 : NS_ABORT_IF_FALSE(mOverflow.mType != NS_FRAME_OVERFLOW_LARGE,
2961 : "should not be called when overflow is in a property");
2962 : // Calculate the rect using deltas from the frame's border rect.
2963 : // Note that the mOverflow.mDeltas fields are unsigned, but we will often
2964 : // need to return negative values for the left and top, so take care
2965 : // to cast away the unsigned-ness.
2966 : return nsRect(-(PRInt32)mOverflow.mVisualDeltas.mLeft,
2967 : -(PRInt32)mOverflow.mVisualDeltas.mTop,
2968 : mRect.width + mOverflow.mVisualDeltas.mRight +
2969 : mOverflow.mVisualDeltas.mLeft,
2970 : mRect.height + mOverflow.mVisualDeltas.mBottom +
2971 : mOverflow.mVisualDeltas.mTop);
2972 : }
2973 : /**
2974 : * Returns true if any overflow changed.
2975 : */
2976 : bool SetOverflowAreas(const nsOverflowAreas& aOverflowAreas);
2977 : nsPoint GetOffsetToCrossDoc(const nsIFrame* aOther, const PRInt32 aAPD) const;
2978 :
2979 : #ifdef NS_DEBUG
2980 : public:
2981 : // Formerly nsIFrameDebug
2982 : NS_IMETHOD List(FILE* out, PRInt32 aIndent) const = 0;
2983 : NS_IMETHOD GetFrameName(nsAString& aResult) const = 0;
2984 : NS_IMETHOD_(nsFrameState) GetDebugStateBits() const = 0;
2985 : NS_IMETHOD DumpRegressionData(nsPresContext* aPresContext,
2986 : FILE* out, PRInt32 aIndent) = 0;
2987 : #endif
2988 : };
2989 :
2990 : //----------------------------------------------------------------------
2991 :
2992 : /**
2993 : * nsWeakFrame can be used to keep a reference to a nsIFrame in a safe way.
2994 : * Whenever an nsIFrame object is deleted, the nsWeakFrames pointing
2995 : * to it will be cleared.
2996 : *
2997 : * Create nsWeakFrame object when it is sure that nsIFrame object
2998 : * is alive and after some operations which may destroy the nsIFrame
2999 : * (for example any DOM modifications) use IsAlive() or GetFrame() methods to
3000 : * check whether it is safe to continue to use the nsIFrame object.
3001 : *
3002 : * @note The usage of this class should be kept to a minimum.
3003 : */
3004 :
3005 : class nsWeakFrame {
3006 : public:
3007 0 : nsWeakFrame() : mPrev(nsnull), mFrame(nsnull) { }
3008 :
3009 : nsWeakFrame(const nsWeakFrame& aOther) : mPrev(nsnull), mFrame(nsnull)
3010 : {
3011 : Init(aOther.GetFrame());
3012 : }
3013 :
3014 2928 : nsWeakFrame(nsIFrame* aFrame) : mPrev(nsnull), mFrame(nsnull)
3015 : {
3016 2928 : Init(aFrame);
3017 2928 : }
3018 :
3019 0 : nsWeakFrame& operator=(nsWeakFrame& aOther) {
3020 0 : Init(aOther.GetFrame());
3021 0 : return *this;
3022 : }
3023 :
3024 0 : nsWeakFrame& operator=(nsIFrame* aFrame) {
3025 0 : Init(aFrame);
3026 0 : return *this;
3027 : }
3028 :
3029 0 : nsIFrame* operator->()
3030 : {
3031 0 : return mFrame;
3032 : }
3033 :
3034 0 : operator nsIFrame*()
3035 : {
3036 0 : return mFrame;
3037 : }
3038 :
3039 5902 : void Clear(nsIPresShell* aShell) {
3040 5902 : if (aShell) {
3041 0 : aShell->RemoveWeakFrame(this);
3042 : }
3043 5902 : mFrame = nsnull;
3044 5902 : mPrev = nsnull;
3045 5902 : }
3046 :
3047 0 : bool IsAlive() { return !!mFrame; }
3048 :
3049 0 : nsIFrame* GetFrame() const { return mFrame; }
3050 :
3051 : nsWeakFrame* GetPreviousWeakFrame() { return mPrev; }
3052 :
3053 : void SetPreviousWeakFrame(nsWeakFrame* aPrev) { mPrev = aPrev; }
3054 :
3055 2974 : ~nsWeakFrame()
3056 : {
3057 2974 : Clear(mFrame ? mFrame->PresContext()->GetPresShell() : nsnull);
3058 2974 : }
3059 : private:
3060 : void InitInternal(nsIFrame* aFrame);
3061 :
3062 : void InitExternal(nsIFrame* aFrame) {
3063 : Clear(mFrame ? mFrame->PresContext()->GetPresShell() : nsnull);
3064 : mFrame = aFrame;
3065 : if (mFrame) {
3066 : nsIPresShell* shell = mFrame->PresContext()->GetPresShell();
3067 : NS_WARN_IF_FALSE(shell, "Null PresShell in nsWeakFrame!");
3068 : if (shell) {
3069 : shell->AddWeakFrame(this);
3070 : } else {
3071 : mFrame = nsnull;
3072 : }
3073 : }
3074 : }
3075 :
3076 2928 : void Init(nsIFrame* aFrame) {
3077 : #ifdef _IMPL_NS_LAYOUT
3078 2928 : InitInternal(aFrame);
3079 : #else
3080 : InitExternal(aFrame);
3081 : #endif
3082 2928 : }
3083 :
3084 : nsWeakFrame* mPrev;
3085 : nsIFrame* mFrame;
3086 : };
3087 :
3088 : inline void
3089 0 : nsFrameList::Enumerator::Next()
3090 : {
3091 0 : NS_ASSERTION(!AtEnd(), "Should have checked AtEnd()!");
3092 0 : mFrame = mFrame->GetNextSibling();
3093 0 : }
3094 :
3095 : inline
3096 : nsFrameList::FrameLinkEnumerator::
3097 : FrameLinkEnumerator(const nsFrameList& aList, nsIFrame* aPrevFrame)
3098 : : Enumerator(aList)
3099 : {
3100 : mPrev = aPrevFrame;
3101 : mFrame = aPrevFrame ? aPrevFrame->GetNextSibling() : aList.FirstChild();
3102 : }
3103 : #endif /* nsIFrame_h___ */
|