Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
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 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 /* interface for all rendering objects */
9 #ifndef nsIFrame_h___
10 #define nsIFrame_h___
12 #ifndef MOZILLA_INTERNAL_API
13 #error This header/class should only be used within Mozilla code. It should not be used by extensions.
14 #endif
16 #define MAX_REFLOW_DEPTH 200
18 /* nsIFrame is in the process of being deCOMtaminated, i.e., this file is eventually
19 going to be eliminated, and all callers will use nsFrame instead. At the moment
20 we're midway through this process, so you will see inlined functions and member
21 variables in this file. -dwh */
23 #include <stdio.h>
24 #include "nsQueryFrame.h"
25 #include "nsStyleContext.h"
26 #include "nsStyleStruct.h"
27 #include "nsHTMLReflowMetrics.h"
28 #include "nsFrameList.h"
29 #include "mozilla/layout/FrameChildList.h"
30 #include "FramePropertyTable.h"
31 #include "mozilla/TypedEnum.h"
32 #include "nsDirection.h"
33 #include "WritingModes.h"
34 #include <algorithm>
35 #include "nsITheme.h"
36 #include "gfx3DMatrix.h"
37 #include "nsLayoutUtils.h"
38 #include "nsFrameState.h"
40 #ifdef ACCESSIBILITY
41 #include "mozilla/a11y/AccTypes.h"
42 #endif
44 /**
45 * New rules of reflow:
46 * 1. you get a WillReflow() followed by a Reflow() followed by a DidReflow() in order
47 * (no separate pass over the tree)
48 * 2. it's the parent frame's responsibility to size/position the child's view (not
49 * the child frame's responsibility as it is today) during reflow (and before
50 * sending the DidReflow() notification)
51 * 3. positioning of child frames (and their views) is done on the way down the tree,
52 * and sizing of child frames (and their views) on the way back up
53 * 4. if you move a frame (outside of the reflow process, or after reflowing it),
54 * then you must make sure that its view (or its child frame's views) are re-positioned
55 * as well. It's reasonable to not position the view until after all reflowing the
56 * entire line, for example, but the frame should still be positioned and sized (and
57 * the view sized) during the reflow (i.e., before sending the DidReflow() notification)
58 * 5. the view system handles moving of widgets, i.e., it's not our problem
59 */
61 struct nsHTMLReflowState;
62 class nsHTMLReflowCommand;
64 struct gfxMatrix;
65 class nsIAtom;
66 class nsPresContext;
67 class nsIPresShell;
68 class nsRenderingContext;
69 class nsView;
70 class nsIWidget;
71 class nsIDOMRange;
72 class nsISelectionController;
73 class nsBoxLayoutState;
74 class nsBoxLayout;
75 class nsILineIterator;
76 class nsDisplayListBuilder;
77 class nsDisplayListSet;
78 class nsDisplayList;
79 class gfxSkipChars;
80 class gfxSkipCharsIterator;
81 class gfxContext;
82 class nsLineList_iterator;
83 class nsAbsoluteContainingBlock;
84 class nsIContent;
86 struct nsPeekOffsetStruct;
87 struct nsPoint;
88 struct nsRect;
89 struct nsSize;
90 struct nsMargin;
91 struct CharacterDataChangeInfo;
93 namespace mozilla {
95 class EventStates;
97 namespace layers {
98 class Layer;
99 }
101 namespace gfx {
102 class Matrix;
103 }
104 }
106 /**
107 * Indication of how the frame can be split. This is used when doing runaround
108 * of floats, and when pulling up child frames from a next-in-flow.
109 *
110 * The choices are splittable, not splittable at all, and splittable in
111 * a non-rectangular fashion. This last type only applies to block-level
112 * elements, and indicates whether splitting can be used when doing runaround.
113 * If you can split across page boundaries, but you expect each continuing
114 * frame to be the same width then return frSplittable and not
115 * frSplittableNonRectangular.
116 *
117 * @see #GetSplittableType()
118 */
119 typedef uint32_t nsSplittableType;
121 #define NS_FRAME_NOT_SPLITTABLE 0 // Note: not a bit!
122 #define NS_FRAME_SPLITTABLE 0x1
123 #define NS_FRAME_SPLITTABLE_NON_RECTANGULAR 0x3
125 #define NS_FRAME_IS_SPLITTABLE(type)\
126 (0 != ((type) & NS_FRAME_SPLITTABLE))
128 #define NS_FRAME_IS_NOT_SPLITTABLE(type)\
129 (0 == ((type) & NS_FRAME_SPLITTABLE))
131 #define NS_INTRINSIC_WIDTH_UNKNOWN nscoord_MIN
133 //----------------------------------------------------------------------
135 #define NS_SUBTREE_DIRTY(_frame) \
136 (((_frame)->GetStateBits() & \
137 (NS_FRAME_IS_DIRTY | NS_FRAME_HAS_DIRTY_CHILDREN)) != 0)
139 /**
140 * Constant used to indicate an unconstrained size.
141 *
142 * @see #Reflow()
143 */
144 #define NS_UNCONSTRAINEDSIZE NS_MAXSIZE
146 #define NS_INTRINSICSIZE NS_UNCONSTRAINEDSIZE
147 #define NS_AUTOHEIGHT NS_UNCONSTRAINEDSIZE
148 #define NS_AUTOMARGIN NS_UNCONSTRAINEDSIZE
149 #define NS_AUTOOFFSET NS_UNCONSTRAINEDSIZE
150 // NOTE: there are assumptions all over that these have the same value, namely NS_UNCONSTRAINEDSIZE
151 // if any are changed to be a value other than NS_UNCONSTRAINEDSIZE
152 // at least update AdjustComputedHeight/Width and test ad nauseum
154 //----------------------------------------------------------------------
156 enum nsSelectionAmount {
157 eSelectCharacter = 0, // a single Unicode character;
158 // do not use this (prefer Cluster) unless you
159 // are really sure it's what you want
160 eSelectCluster = 1, // a grapheme cluster: this is usually the right
161 // choice for movement or selection by "character"
162 // as perceived by the user
163 eSelectWord = 2,
164 eSelectLine = 3, // previous drawn line in flow.
165 eSelectBeginLine = 4,
166 eSelectEndLine = 5,
167 eSelectNoAmount = 6, // just bounce back current offset.
168 eSelectParagraph = 7, // select a "paragraph"
169 eSelectWordNoSpace = 8 // select a "word" without selecting the following
170 // space, no matter what the default platform
171 // behavior is
172 };
174 enum nsSpread {
175 eSpreadNone = 0,
176 eSpreadAcross = 1,
177 eSpreadDown = 2
178 };
180 // Carried out margin flags
181 #define NS_CARRIED_TOP_MARGIN_IS_AUTO 0x1
182 #define NS_CARRIED_BOTTOM_MARGIN_IS_AUTO 0x2
184 //----------------------------------------------------------------------
186 /**
187 * Reflow status returned by the reflow methods. There are three
188 * completion statuses, represented by two bit flags.
189 *
190 * NS_FRAME_COMPLETE means the frame is fully complete.
191 *
192 * NS_FRAME_NOT_COMPLETE bit flag means the frame does not map all its
193 * content, and that the parent frame should create a continuing frame.
194 * If this bit isn't set it means the frame does map all its content.
195 * This bit is mutually exclusive with NS_FRAME_OVERFLOW_INCOMPLETE.
196 *
197 * NS_FRAME_OVERFLOW_INCOMPLETE bit flag means that the frame has
198 * overflow that is not complete, but its own box is complete.
199 * (This happens when content overflows a fixed-height box.)
200 * The reflower should place and size the frame and continue its reflow,
201 * but needs to create an overflow container as a continuation for this
202 * frame. See nsContainerFrame.h for more information.
203 * This bit is mutually exclusive with NS_FRAME_NOT_COMPLETE.
204 *
205 * Please use the SET macro for handling
206 * NS_FRAME_NOT_COMPLETE and NS_FRAME_OVERFLOW_INCOMPLETE.
207 *
208 * NS_FRAME_REFLOW_NEXTINFLOW bit flag means that the next-in-flow is
209 * dirty, and also needs to be reflowed. This status only makes sense
210 * for a frame that is not complete, i.e. you wouldn't set both
211 * NS_FRAME_COMPLETE and NS_FRAME_REFLOW_NEXTINFLOW.
212 *
213 * The low 8 bits of the nsReflowStatus are reserved for future extensions;
214 * the remaining 24 bits are zero (and available for extensions; however
215 * API's that accept/return nsReflowStatus must not receive/return any
216 * extension bits).
217 *
218 * @see #Reflow()
219 */
220 typedef uint32_t nsReflowStatus;
222 #define NS_FRAME_COMPLETE 0 // Note: not a bit!
223 #define NS_FRAME_NOT_COMPLETE 0x1
224 #define NS_FRAME_REFLOW_NEXTINFLOW 0x2
225 #define NS_FRAME_OVERFLOW_INCOMPLETE 0x4
227 #define NS_FRAME_IS_COMPLETE(status) \
228 (0 == ((status) & NS_FRAME_NOT_COMPLETE))
230 #define NS_FRAME_IS_NOT_COMPLETE(status) \
231 (0 != ((status) & NS_FRAME_NOT_COMPLETE))
233 #define NS_FRAME_OVERFLOW_IS_INCOMPLETE(status) \
234 (0 != ((status) & NS_FRAME_OVERFLOW_INCOMPLETE))
236 #define NS_FRAME_IS_FULLY_COMPLETE(status) \
237 (NS_FRAME_IS_COMPLETE(status) && !NS_FRAME_OVERFLOW_IS_INCOMPLETE(status))
239 // These macros set or switch incomplete statuses without touching the
240 // NS_FRAME_REFLOW_NEXTINFLOW bit.
241 #define NS_FRAME_SET_INCOMPLETE(status) \
242 status = (status & ~NS_FRAME_OVERFLOW_INCOMPLETE) | NS_FRAME_NOT_COMPLETE
244 #define NS_FRAME_SET_OVERFLOW_INCOMPLETE(status) \
245 status = (status & ~NS_FRAME_NOT_COMPLETE) | NS_FRAME_OVERFLOW_INCOMPLETE
247 // This macro tests to see if an nsReflowStatus is an error value
248 // or just a regular return value
249 #define NS_IS_REFLOW_ERROR(_status) (int32_t(_status) < 0)
251 /**
252 * Extensions to the reflow status bits defined by nsIFrameReflow
253 */
255 // This bit is set, when a break is requested. This bit is orthogonal
256 // to the nsIFrame::nsReflowStatus completion bits.
257 #define NS_INLINE_BREAK 0x0100
259 // When a break is requested, this bit when set indicates that the
260 // break should occur after the frame just reflowed; when the bit is
261 // clear the break should occur before the frame just reflowed.
262 #define NS_INLINE_BREAK_BEFORE 0x0000
263 #define NS_INLINE_BREAK_AFTER 0x0200
265 // The type of break requested can be found in these bits.
266 #define NS_INLINE_BREAK_TYPE_MASK 0xF000
268 // Set when a break was induced by completion of a first-letter
269 #define NS_INLINE_BREAK_FIRST_LETTER_COMPLETE 0x10000
271 //----------------------------------------
272 // Macros that use those bits
274 #define NS_INLINE_IS_BREAK(_status) \
275 (0 != ((_status) & NS_INLINE_BREAK))
277 #define NS_INLINE_IS_BREAK_AFTER(_status) \
278 (0 != ((_status) & NS_INLINE_BREAK_AFTER))
280 #define NS_INLINE_IS_BREAK_BEFORE(_status) \
281 (NS_INLINE_BREAK == ((_status) & (NS_INLINE_BREAK|NS_INLINE_BREAK_AFTER)))
283 #define NS_INLINE_GET_BREAK_TYPE(_status) (((_status) >> 12) & 0xF)
285 #define NS_INLINE_MAKE_BREAK_TYPE(_type) ((_type) << 12)
287 // Construct a line-break-before status. Note that there is no
288 // completion status for a line-break before because we *know* that
289 // the frame will be reflowed later and hence its current completion
290 // status doesn't matter.
291 #define NS_INLINE_LINE_BREAK_BEFORE() \
292 (NS_INLINE_BREAK | NS_INLINE_BREAK_BEFORE | \
293 NS_INLINE_MAKE_BREAK_TYPE(NS_STYLE_CLEAR_LINE))
295 // Take a completion status and add to it the desire to have a
296 // line-break after. For this macro we do need the completion status
297 // because the user of the status will need to know whether to
298 // continue the frame or not.
299 #define NS_INLINE_LINE_BREAK_AFTER(_completionStatus) \
300 ((_completionStatus) | NS_INLINE_BREAK | NS_INLINE_BREAK_AFTER | \
301 NS_INLINE_MAKE_BREAK_TYPE(NS_STYLE_CLEAR_LINE))
303 // A frame is "truncated" if the part of the frame before the first
304 // possible break point was unable to fit in the available vertical
305 // space. Therefore, the entire frame should be moved to the next page.
306 // A frame that begins at the top of the page must never be "truncated".
307 // Doing so would likely cause an infinite loop.
308 #define NS_FRAME_TRUNCATED 0x0010
309 #define NS_FRAME_IS_TRUNCATED(status) \
310 (0 != ((status) & NS_FRAME_TRUNCATED))
311 #define NS_FRAME_SET_TRUNCATION(status, aReflowState, aMetrics) \
312 aReflowState.SetTruncated(aMetrics, &status);
314 // Merge the incompleteness, truncation and NS_FRAME_REFLOW_NEXTINFLOW
315 // status from aSecondary into aPrimary.
316 void NS_MergeReflowStatusInto(nsReflowStatus* aPrimary,
317 nsReflowStatus aSecondary);
319 //----------------------------------------------------------------------
321 /**
322 * DidReflow status values.
323 */
324 MOZ_BEGIN_ENUM_CLASS(nsDidReflowStatus, uint32_t)
325 NOT_FINISHED,
326 FINISHED
327 MOZ_END_ENUM_CLASS(nsDidReflowStatus)
329 /**
330 * When there is no scrollable overflow rect, the visual overflow rect
331 * may be stored as four 1-byte deltas each strictly LESS THAN 0xff, for
332 * the four edges of the rectangle, or the four bytes may be read as a
333 * single 32-bit "overflow-rect type" value including at least one 0xff
334 * byte as an indicator that the value does NOT represent four deltas.
335 * If all four deltas are zero, this means that no overflow rect has
336 * actually been set (this is the initial state of newly-created frames).
337 */
338 #define NS_FRAME_OVERFLOW_DELTA_MAX 0xfe // max delta we can store
340 #define NS_FRAME_OVERFLOW_NONE 0x00000000 // there are no overflow rects;
341 // code relies on this being
342 // the all-zero value
344 #define NS_FRAME_OVERFLOW_LARGE 0x000000ff // overflow is stored as a
345 // separate rect property
347 namespace mozilla {
348 /*
349 * For replaced elements only. Gets the intrinsic dimensions of this element.
350 * The dimensions may only be one of the following two types:
351 *
352 * eStyleUnit_Coord - a length in app units
353 * eStyleUnit_None - the element has no intrinsic size in this dimension
354 */
355 struct IntrinsicSize {
356 nsStyleCoord width, height;
358 IntrinsicSize()
359 : width(eStyleUnit_None), height(eStyleUnit_None)
360 {}
361 IntrinsicSize(const IntrinsicSize& rhs)
362 : width(rhs.width), height(rhs.height)
363 {}
364 IntrinsicSize& operator=(const IntrinsicSize& rhs) {
365 width = rhs.width; height = rhs.height; return *this;
366 }
367 bool operator==(const IntrinsicSize& rhs) {
368 return width == rhs.width && height == rhs.height;
369 }
370 bool operator!=(const IntrinsicSize& rhs) {
371 return !(*this == rhs);
372 }
373 };
374 }
376 //----------------------------------------------------------------------
378 /**
379 * A frame in the layout model. This interface is supported by all frame
380 * objects.
381 *
382 * Frames can have multiple child lists: the default child list
383 * (referred to as the <i>principal</i> child list, and additional named
384 * child lists. There is an ordering of frames within a child list, but
385 * there is no order defined between frames in different child lists of
386 * the same parent frame.
387 *
388 * Frames are NOT reference counted. Use the Destroy() member function
389 * to destroy a frame. The lifetime of the frame hierarchy is bounded by the
390 * lifetime of the presentation shell which owns the frames.
391 *
392 * nsIFrame is a private Gecko interface. If you are not Gecko then you
393 * should not use it. If you're not in layout, then you won't be able to
394 * link to many of the functions defined here. Too bad.
395 *
396 * If you're not in layout but you must call functions in here, at least
397 * restrict yourself to calling virtual methods, which won't hurt you as badly.
398 */
399 class nsIFrame : public nsQueryFrame
400 {
401 public:
402 typedef mozilla::FramePropertyDescriptor FramePropertyDescriptor;
403 typedef mozilla::FrameProperties FrameProperties;
404 typedef mozilla::layers::Layer Layer;
405 typedef mozilla::layout::FrameChildList ChildList;
406 typedef mozilla::layout::FrameChildListID ChildListID;
407 typedef mozilla::layout::FrameChildListIDs ChildListIDs;
408 typedef mozilla::layout::FrameChildListIterator ChildListIterator;
409 typedef mozilla::layout::FrameChildListArrayIterator ChildListArrayIterator;
410 typedef mozilla::gfx::Matrix Matrix;
412 NS_DECL_QUERYFRAME_TARGET(nsIFrame)
414 nsPresContext* PresContext() const {
415 return StyleContext()->RuleNode()->PresContext();
416 }
418 /**
419 * Called to initialize the frame. This is called immediately after creating
420 * the frame.
421 *
422 * If the frame is a continuing frame, then aPrevInFlow indicates the previous
423 * frame (the frame that was split).
424 *
425 * If you want a view associated with your frame, you should create the view
426 * after Init() has returned.
427 *
428 * @param aContent the content object associated with the frame
429 * @param aParent the parent frame
430 * @param aPrevInFlow the prev-in-flow frame
431 */
432 virtual void Init(nsIContent* aContent,
433 nsIFrame* aParent,
434 nsIFrame* aPrevInFlow) = 0;
436 /**
437 * Destroys this frame and each of its child frames (recursively calls
438 * Destroy() for each child). If this frame is a first-continuation, this
439 * also removes the frame from the primary frame map and clears undisplayed
440 * content for its content node.
441 * If the frame is a placeholder, it also ensures the out-of-flow frame's
442 * removal and destruction.
443 */
444 void Destroy() { DestroyFrom(this); }
446 /** Flags for PeekOffsetCharacter, PeekOffsetNoAmount, PeekOffsetWord return values.
447 */
448 enum FrameSearchResult {
449 // Peek found a appropriate offset within frame.
450 FOUND = 0x00,
451 // try next frame for offset.
452 CONTINUE = 0x1,
453 // offset not found because the frame was empty of text.
454 CONTINUE_EMPTY = 0x2 | CONTINUE,
455 // offset not found because the frame didn't contain any text that could be selected.
456 CONTINUE_UNSELECTABLE = 0x4 | CONTINUE,
457 };
459 protected:
460 /**
461 * Return true if the frame is part of a Selection.
462 * Helper method to implement the public IsSelected() API.
463 */
464 virtual bool IsFrameSelected() const;
466 /**
467 * Implements Destroy(). Do not call this directly except from within a
468 * DestroyFrom() implementation.
469 *
470 * @note This will always be called, so it is not necessary to override
471 * Destroy() in subclasses of nsFrame, just DestroyFrom().
472 *
473 * @param aDestructRoot is the root of the subtree being destroyed
474 */
475 virtual void DestroyFrom(nsIFrame* aDestructRoot) = 0;
476 friend class nsFrameList; // needed to pass aDestructRoot through to children
477 friend class nsLineBox; // needed to pass aDestructRoot through to children
478 friend class nsContainerFrame; // needed to pass aDestructRoot through to children
479 public:
481 /**
482 * Called to set the initial list of frames. This happens after the frame
483 * has been initialized.
484 *
485 * This is only called once for a given child list, and won't be called
486 * at all for child lists with no initial list of frames.
487 *
488 * @param aListID the child list identifier.
489 * @param aChildList list of child frames. Each of the frames has its
490 * NS_FRAME_IS_DIRTY bit set. Must not be empty.
491 * This method cannot handle the child list returned by
492 * GetAbsoluteListID().
493 * @return NS_ERROR_INVALID_ARG if there is no child list with the specified
494 * name,
495 * NS_ERROR_UNEXPECTED if the frame is an atomic frame or if the
496 * initial list of frames has already been set for that child list,
497 * NS_OK otherwise. In this case, SetInitialChildList empties out
498 * aChildList in the process of moving the frames over to its own
499 * child list.
500 * @see #Init()
501 */
502 virtual nsresult SetInitialChildList(ChildListID aListID,
503 nsFrameList& aChildList) = 0;
505 /**
506 * This method is responsible for appending frames to the frame
507 * list. The implementation should append the frames to the specified
508 * child list and then generate a reflow command.
509 *
510 * @param aListID the child list identifier.
511 * @param aFrameList list of child frames to append. Each of the frames has
512 * its NS_FRAME_IS_DIRTY bit set. Must not be empty.
513 * @return NS_ERROR_INVALID_ARG if there is no child list with the specified
514 * name,
515 * NS_ERROR_UNEXPECTED if the frame is an atomic frame,
516 * NS_OK otherwise. In this case, AppendFrames empties out
517 * aFrameList in the process of moving the frames over to its own
518 * child list.
519 */
520 virtual nsresult AppendFrames(ChildListID aListID,
521 nsFrameList& aFrameList) = 0;
523 /**
524 * This method is responsible for inserting frames into the frame
525 * list. The implementation should insert the new frames into the specified
526 * child list and then generate a reflow command.
527 *
528 * @param aListID the child list identifier.
529 * @param aPrevFrame the frame to insert frames <b>after</b>
530 * @param aFrameList list of child frames to insert <b>after</b> aPrevFrame.
531 * Each of the frames has its NS_FRAME_IS_DIRTY bit set
532 * @return NS_ERROR_INVALID_ARG if there is no child list with the specified
533 * name,
534 * NS_ERROR_UNEXPECTED if the frame is an atomic frame,
535 * NS_OK otherwise. In this case, InsertFrames empties out
536 * aFrameList in the process of moving the frames over to its own
537 * child list.
538 */
539 virtual nsresult InsertFrames(ChildListID aListID,
540 nsIFrame* aPrevFrame,
541 nsFrameList& aFrameList) = 0;
543 /**
544 * This method is responsible for removing a frame in the frame
545 * list. The implementation should do something with the removed frame
546 * and then generate a reflow command. The implementation is responsible
547 * for destroying aOldFrame (the caller mustn't destroy aOldFrame).
548 *
549 * @param aListID the child list identifier.
550 * @param aOldFrame the frame to remove
551 * @return NS_ERROR_INVALID_ARG if there is no child list with the specified
552 * name,
553 * NS_ERROR_FAILURE if the child frame is not in the specified
554 * child list,
555 * NS_ERROR_UNEXPECTED if the frame is an atomic frame,
556 * NS_OK otherwise
557 */
558 virtual nsresult RemoveFrame(ChildListID aListID,
559 nsIFrame* aOldFrame) = 0;
561 /**
562 * Get the content object associated with this frame. Does not add a reference.
563 */
564 nsIContent* GetContent() const { return mContent; }
566 /**
567 * Get the frame that should be the parent for the frames of child elements
568 * May return nullptr during reflow
569 */
570 virtual nsIFrame* GetContentInsertionFrame() { return this; }
572 /**
573 * Move any frames on our overflow list to the end of our principal list.
574 * @return true if there were any overflow frames
575 */
576 virtual bool DrainSelfOverflowList() { return false; }
578 /**
579 * Get the frame that should be scrolled if the content associated
580 * with this frame is targeted for scrolling. For frames implementing
581 * nsIScrollableFrame this will return the frame itself. For frames
582 * like nsTextControlFrame that contain a scrollframe, will return
583 * that scrollframe.
584 */
585 virtual nsIScrollableFrame* GetScrollTargetFrame() { return nullptr; }
587 /**
588 * Get the offsets of the frame. most will be 0,0
589 *
590 */
591 virtual nsresult GetOffsets(int32_t &start, int32_t &end) const = 0;
593 /**
594 * Reset the offsets when splitting frames during Bidi reordering
595 *
596 */
597 virtual void AdjustOffsetsForBidi(int32_t aStart, int32_t aEnd) {}
599 /**
600 * Get the style context associated with this frame.
601 */
602 nsStyleContext* StyleContext() const { return mStyleContext; }
603 void SetStyleContext(nsStyleContext* aContext)
604 {
605 if (aContext != mStyleContext) {
606 nsStyleContext* oldStyleContext = mStyleContext;
607 mStyleContext = aContext;
608 aContext->AddRef();
609 DidSetStyleContext(oldStyleContext);
610 oldStyleContext->Release();
611 }
612 }
614 /**
615 * SetStyleContextWithoutNotification is for changes to the style
616 * context that should suppress style change processing, in other
617 * words, those that aren't really changes. This generally means only
618 * changes that happen during frame construction.
619 */
620 void SetStyleContextWithoutNotification(nsStyleContext* aContext)
621 {
622 if (aContext != mStyleContext) {
623 mStyleContext->Release();
624 mStyleContext = aContext;
625 aContext->AddRef();
626 }
627 }
629 // Style post processing hook
630 // Attention: the old style context is the one we're forgetting,
631 // and hence possibly completely bogus for GetStyle* purposes.
632 // Use PeekStyleData instead.
633 virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext) = 0;
635 /**
636 * Define typesafe getter functions for each style struct by
637 * preprocessing the list of style structs. These functions are the
638 * preferred way to get style data. The macro creates functions like:
639 * const nsStyleBorder* StyleBorder();
640 * const nsStyleColor* StyleColor();
641 *
642 * Callers outside of libxul should use nsIDOMWindow::GetComputedStyle()
643 * instead of these accessors.
644 */
645 #define STYLE_STRUCT(name_, checkdata_cb_) \
646 const nsStyle##name_ * Style##name_ () const { \
647 NS_ASSERTION(mStyleContext, "No style context found!"); \
648 return mStyleContext->Style##name_ (); \
649 }
650 #include "nsStyleStructList.h"
651 #undef STYLE_STRUCT
653 /** Also forward GetVisitedDependentColor to the style context */
654 nscolor GetVisitedDependentColor(nsCSSProperty aProperty)
655 { return mStyleContext->GetVisitedDependentColor(aProperty); }
657 /**
658 * These methods are to access any additional style contexts that
659 * the frame may be holding. These are contexts that are children
660 * of the frame's primary context and are NOT used as style contexts
661 * for any child frames. These contexts also MUST NOT have any child
662 * contexts whatsoever. If you need to insert style contexts into the
663 * style tree, then you should create pseudo element frames to own them
664 * The indicies must be consecutive and implementations MUST return an
665 * NS_ERROR_INVALID_ARG if asked for an index that is out of range.
666 */
667 virtual nsStyleContext* GetAdditionalStyleContext(int32_t aIndex) const = 0;
669 virtual void SetAdditionalStyleContext(int32_t aIndex,
670 nsStyleContext* aStyleContext) = 0;
672 /**
673 * Accessor functions for geometric parent
674 */
675 nsIFrame* GetParent() const { return mParent; }
676 /**
677 * Set this frame's parent to aParent.
678 * If the frame may have moved into or out of a scrollframe's
679 * frame subtree, StickyScrollContainer::NotifyReparentedFrameAcrossScrollFrameBoundary
680 * must also be called.
681 */
682 virtual void SetParent(nsIFrame* aParent) = 0;
684 /**
685 * The frame's writing-mode, used for logical layout computations.
686 */
687 mozilla::WritingMode GetWritingMode() const {
688 return mozilla::WritingMode(StyleVisibility());
689 }
691 /**
692 * Get the writing mode of this frame, but if it is styled with
693 * unicode-bidi: plaintext, reset the direction to the resolved paragraph
694 * level of the given subframe (typically the first frame on the line),
695 * not this frame's writing mode, because the container frame could be split
696 * by hard line breaks into multiple paragraphs with different base direction.
697 */
698 mozilla::WritingMode GetWritingMode(nsIFrame* aSubFrame) const;
700 /**
701 * Bounding rect of the frame. The values are in app units, and the origin is
702 * relative to the upper-left of the geometric parent. The size includes the
703 * content area, borders, and padding.
704 *
705 * Note: moving or sizing the frame does not affect the view's size or
706 * position.
707 */
708 nsRect GetRect() const { return mRect; }
709 nsPoint GetPosition() const { return mRect.TopLeft(); }
710 nsSize GetSize() const { return mRect.Size(); }
711 nsRect GetRectRelativeToSelf() const {
712 return nsRect(nsPoint(0, 0), mRect.Size());
713 }
714 /**
715 * Dimensions and position in logical coordinates in the frame's writing mode
716 * or another writing mode
717 */
718 mozilla::LogicalRect GetLogicalRect(nscoord aContainerWidth) const {
719 return GetLogicalRect(GetWritingMode(), aContainerWidth);
720 }
721 mozilla::LogicalPoint GetLogicalPosition(nscoord aContainerWidth) const {
722 return GetLogicalPosition(GetWritingMode(), aContainerWidth);
723 }
724 mozilla::LogicalSize GetLogicalSize() const {
725 return GetLogicalSize(GetWritingMode());
726 }
727 mozilla::LogicalRect GetLogicalRect(mozilla::WritingMode aWritingMode,
728 nscoord aContainerWidth) const {
729 return mozilla::LogicalRect(aWritingMode, GetRect(), aContainerWidth);
730 }
731 mozilla::LogicalPoint GetLogicalPosition(mozilla::WritingMode aWritingMode,
732 nscoord aContainerWidth) const {
733 return GetLogicalRect(aWritingMode, aContainerWidth).Origin(aWritingMode);
734 }
735 mozilla::LogicalSize GetLogicalSize(mozilla::WritingMode aWritingMode) const {
736 return mozilla::LogicalSize(aWritingMode, GetSize());
737 }
738 nscoord IStart(nscoord aContainerWidth) const {
739 return IStart(GetWritingMode(), aContainerWidth);
740 }
741 nscoord IStart(mozilla::WritingMode aWritingMode,
742 nscoord aContainerWidth) const {
743 return GetLogicalPosition(aWritingMode, aContainerWidth).I(aWritingMode);
744 }
745 nscoord BStart(nscoord aContainerWidth) const {
746 return BStart(GetWritingMode(), aContainerWidth);
747 }
748 nscoord BStart(mozilla::WritingMode aWritingMode,
749 nscoord aContainerWidth) const {
750 return GetLogicalPosition(aWritingMode, aContainerWidth).B(aWritingMode);
751 }
752 nscoord ISize() const { return ISize(GetWritingMode()); }
753 nscoord ISize(mozilla::WritingMode aWritingMode) const {
754 return GetLogicalSize(aWritingMode).ISize(aWritingMode);
755 }
756 nscoord BSize() const { return BSize(GetWritingMode()); }
757 nscoord BSize(mozilla::WritingMode aWritingMode) const {
758 return GetLogicalSize(aWritingMode).BSize(aWritingMode);
759 }
761 /**
762 * When we change the size of the frame's border-box rect, we may need to
763 * reset the overflow rect if it was previously stored as deltas.
764 * (If it is currently a "large" overflow and could be re-packed as deltas,
765 * we don't bother as the cost of the allocation has already been paid.)
766 */
767 void SetRect(const nsRect& aRect) {
768 if (mOverflow.mType != NS_FRAME_OVERFLOW_LARGE &&
769 mOverflow.mType != NS_FRAME_OVERFLOW_NONE) {
770 nsOverflowAreas overflow = GetOverflowAreas();
771 mRect = aRect;
772 SetOverflowAreas(overflow);
773 } else {
774 mRect = aRect;
775 }
776 }
777 /**
778 * Set this frame's rect from a logical rect in its own writing direction
779 */
780 void SetRect(const mozilla::LogicalRect& aRect, nscoord aContainerWidth) {
781 SetRect(GetWritingMode(), aRect, aContainerWidth);
782 }
783 /**
784 * Set this frame's rect from a logical rect in a different writing direction
785 * (GetPhysicalRect will assert if the writing mode doesn't match)
786 */
787 void SetRect(mozilla::WritingMode aWritingMode,
788 const mozilla::LogicalRect& aRect,
789 nscoord aContainerWidth) {
790 SetRect(aRect.GetPhysicalRect(aWritingMode, aContainerWidth));
791 }
792 void SetSize(const nsSize& aSize) {
793 SetRect(nsRect(mRect.TopLeft(), aSize));
794 }
795 void SetPosition(const nsPoint& aPt) { mRect.MoveTo(aPt); }
797 /**
798 * Move the frame, accounting for relative positioning. Use this when
799 * adjusting the frame's position by a known amount, to properly update its
800 * saved normal position (see GetNormalPosition below).
801 *
802 * This must be used only when moving a frame *after*
803 * nsHTMLReflowState::ApplyRelativePositioning is called. When moving
804 * a frame during the reflow process prior to calling
805 * nsHTMLReflowState::ApplyRelativePositioning, the position should
806 * simply be adjusted directly (e.g., using SetPosition()).
807 */
808 void MovePositionBy(const nsPoint& aTranslation);
810 /**
811 * Return frame's position without relative positioning
812 */
813 nsPoint GetNormalPosition() const;
814 mozilla::LogicalPoint
815 GetLogicalNormalPosition(mozilla::WritingMode aWritingMode,
816 nscoord aContainerWidth) const
817 {
818 return mozilla::LogicalPoint(aWritingMode,
819 GetNormalPosition(), aContainerWidth);
820 }
822 virtual nsPoint GetPositionOfChildIgnoringScrolling(nsIFrame* aChild)
823 { return aChild->GetPosition(); }
825 nsPoint GetPositionIgnoringScrolling() {
826 return mParent ? mParent->GetPositionOfChildIgnoringScrolling(this)
827 : GetPosition();
828 }
830 static void DestroyRegion(void* aPropertyValue);
832 static void DestroyMargin(void* aPropertyValue)
833 {
834 delete static_cast<nsMargin*>(aPropertyValue);
835 }
837 static void DestroyRect(void* aPropertyValue)
838 {
839 delete static_cast<nsRect*>(aPropertyValue);
840 }
842 static void DestroyPoint(void* aPropertyValue)
843 {
844 delete static_cast<nsPoint*>(aPropertyValue);
845 }
847 static void DestroyOverflowAreas(void* aPropertyValue)
848 {
849 delete static_cast<nsOverflowAreas*>(aPropertyValue);
850 }
852 static void DestroySurface(void* aPropertyValue);
853 static void DestroyDT(void* aPropertyValue);
855 #ifdef _MSC_VER
856 // XXX Workaround MSVC issue by making the static FramePropertyDescriptor
857 // non-const. See bug 555727.
858 #define NS_PROPERTY_DESCRIPTOR_CONST
859 #else
860 #define NS_PROPERTY_DESCRIPTOR_CONST const
861 #endif
863 #define NS_DECLARE_FRAME_PROPERTY(prop, dtor) \
864 static const FramePropertyDescriptor* prop() { \
865 static NS_PROPERTY_DESCRIPTOR_CONST FramePropertyDescriptor descriptor = { dtor, nullptr }; \
866 return &descriptor; \
867 }
868 // Don't use this unless you really know what you're doing!
869 #define NS_DECLARE_FRAME_PROPERTY_WITH_FRAME_IN_DTOR(prop, dtor) \
870 static const FramePropertyDescriptor* prop() { \
871 static NS_PROPERTY_DESCRIPTOR_CONST FramePropertyDescriptor descriptor = { nullptr, dtor }; \
872 return &descriptor; \
873 }
875 NS_DECLARE_FRAME_PROPERTY(IBSplitSibling, nullptr)
876 NS_DECLARE_FRAME_PROPERTY(IBSplitPrevSibling, nullptr)
878 NS_DECLARE_FRAME_PROPERTY(NormalPositionProperty, DestroyPoint)
879 NS_DECLARE_FRAME_PROPERTY(ComputedOffsetProperty, DestroyMargin)
881 NS_DECLARE_FRAME_PROPERTY(OutlineInnerRectProperty, DestroyRect)
882 NS_DECLARE_FRAME_PROPERTY(PreEffectsBBoxProperty, DestroyRect)
883 NS_DECLARE_FRAME_PROPERTY(PreTransformOverflowAreasProperty,
884 DestroyOverflowAreas)
886 // The initial overflow area passed to FinishAndStoreOverflow. This is only set
887 // on frames that Preserve3D() or HasPerspective() or IsTransformed(), and
888 // when at least one of the overflow areas differs from the frame bound rect.
889 NS_DECLARE_FRAME_PROPERTY(InitialOverflowProperty, DestroyOverflowAreas)
891 #ifdef DEBUG
892 // InitialOverflowPropertyDebug is added to the frame to indicate that either
893 // the InitialOverflowProperty has been stored or the InitialOverflowProperty
894 // has been suppressed due to being set to the default value (frame bounds)
895 NS_DECLARE_FRAME_PROPERTY(DebugInitialOverflowPropertyApplied, nullptr)
896 #endif
898 NS_DECLARE_FRAME_PROPERTY(UsedMarginProperty, DestroyMargin)
899 NS_DECLARE_FRAME_PROPERTY(UsedPaddingProperty, DestroyMargin)
900 NS_DECLARE_FRAME_PROPERTY(UsedBorderProperty, DestroyMargin)
902 NS_DECLARE_FRAME_PROPERTY(ScrollLayerCount, nullptr)
904 NS_DECLARE_FRAME_PROPERTY(LineBaselineOffset, nullptr)
906 NS_DECLARE_FRAME_PROPERTY(CachedBackgroundImage, DestroySurface)
907 NS_DECLARE_FRAME_PROPERTY(CachedBackgroundImageDT, DestroyDT)
909 NS_DECLARE_FRAME_PROPERTY(InvalidationRect, DestroyRect)
911 NS_DECLARE_FRAME_PROPERTY(RefusedAsyncAnimation, nullptr)
913 /**
914 * Return the distance between the border edge of the frame and the
915 * margin edge of the frame. Like GetRect(), returns the dimensions
916 * as of the most recent reflow.
917 *
918 * This doesn't include any margin collapsing that may have occurred.
919 *
920 * It also treats 'auto' margins as zero, and treats any margins that
921 * should have been turned into 'auto' because of overconstraint as
922 * having their original values.
923 */
924 virtual nsMargin GetUsedMargin() const;
925 virtual mozilla::LogicalMargin
926 GetLogicalUsedMargin(mozilla::WritingMode aWritingMode) const {
927 return mozilla::LogicalMargin(aWritingMode, GetUsedMargin());
928 }
930 /**
931 * Return the distance between the border edge of the frame (which is
932 * its rect) and the padding edge of the frame. Like GetRect(), returns
933 * the dimensions as of the most recent reflow.
934 *
935 * Note that this differs from StyleBorder()->GetBorder() in that
936 * this describes region of the frame's box, and
937 * StyleBorder()->GetBorder() describes a border. They differ only
938 * for tables, particularly border-collapse tables.
939 */
940 virtual nsMargin GetUsedBorder() const;
941 virtual mozilla::LogicalMargin
942 GetLogicalUsedBorder(mozilla::WritingMode aWritingMode) const {
943 return mozilla::LogicalMargin(aWritingMode, GetUsedBorder());
944 }
946 /**
947 * Return the distance between the padding edge of the frame and the
948 * content edge of the frame. Like GetRect(), returns the dimensions
949 * as of the most recent reflow.
950 */
951 virtual nsMargin GetUsedPadding() const;
952 virtual mozilla::LogicalMargin
953 GetLogicalUsedPadding(mozilla::WritingMode aWritingMode) const {
954 return mozilla::LogicalMargin(aWritingMode, GetUsedPadding());
955 }
957 nsMargin GetUsedBorderAndPadding() const {
958 return GetUsedBorder() + GetUsedPadding();
959 }
960 mozilla::LogicalMargin
961 GetLogicalUsedBorderAndPadding(mozilla::WritingMode aWritingMode) const {
962 return mozilla::LogicalMargin(aWritingMode, GetUsedBorderAndPadding());
963 }
965 /**
966 * Apply the result of GetSkipSides() on this frame to an nsMargin by
967 * setting to zero any sides that are skipped.
968 *
969 * @param aMargin The margin to apply the result of GetSkipSides() to.
970 * @param aReflowState An optional reflow state parameter, which is used if
971 * ApplySkipSides() is being called in the middle of reflow.
972 *
973 * @note (See also bug 743402, comment 11) GetSkipSides() and its sister
974 * method, ApplySkipSides() checks to see if this frame has a previous
975 * or next continuation to determine if a side should be skipped.
976 * Unfortunately, this only works after reflow has been completed. In
977 * lieu of this, during reflow, an nsHTMLReflowState parameter can be
978 * passed in, indicating that it should be used to determine if sides
979 * should be skipped during reflow.
980 */
981 void ApplySkipSides(nsMargin& aMargin,
982 const nsHTMLReflowState* aReflowState = nullptr) const;
983 void ApplyLogicalSkipSides(mozilla::LogicalMargin& aMargin,
984 const nsHTMLReflowState* aReflowState = nullptr) const;
986 /**
987 * Like the frame's rect (see |GetRect|), which is the border rect,
988 * other rectangles of the frame, in app units, relative to the parent.
989 */
990 nsRect GetPaddingRect() const;
991 nsRect GetPaddingRectRelativeToSelf() const;
992 nsRect GetContentRect() const;
993 nsRect GetContentRectRelativeToSelf() const;
994 nsRect GetMarginRectRelativeToSelf() const;
996 /**
997 * The area to paint box-shadows around. The default is the border rect.
998 * (nsFieldSetFrame overrides this).
999 */
1000 virtual nsRect VisualBorderRectRelativeToSelf() const {
1001 return nsRect(0, 0, mRect.width, mRect.height);
1002 }
1004 /**
1005 * Get the size, in app units, of the border radii. It returns FALSE iff all
1006 * returned radii == 0 (so no border radii), TRUE otherwise.
1007 * For the aRadii indexes, use the NS_CORNER_* constants in nsStyleConsts.h
1008 * If a side is skipped via aSkipSides, its corners are forced to 0.
1009 *
1010 * All corner radii are then adjusted so they do not require more
1011 * space than aBorderArea, according to the algorithm in css3-background.
1012 *
1013 * aFrameSize is used as the basis for percentage widths and heights.
1014 * aBorderArea is used for the adjustment of radii that might be too
1015 * large.
1016 * FIXME: In the long run, we can probably get away with only one of
1017 * these, especially if we change the way we handle outline-radius (by
1018 * removing it and inflating the border radius)
1019 *
1020 * Return whether any radii are nonzero.
1021 */
1022 static bool ComputeBorderRadii(const nsStyleCorners& aBorderRadius,
1023 const nsSize& aFrameSize,
1024 const nsSize& aBorderArea,
1025 int aSkipSides,
1026 nscoord aRadii[8]);
1028 /*
1029 * Given a set of border radii for one box (e.g., border box), convert
1030 * it to the equivalent set of radii for another box (e.g., in to
1031 * padding box, out to outline box) by reducing radii or increasing
1032 * nonzero radii as appropriate.
1033 *
1034 * Indices into aRadii are the NS_CORNER_* constants in nsStyleConsts.h
1035 *
1036 * Note that InsetBorderRadii is lossy, since it can turn nonzero
1037 * radii into zero, and OutsetBorderRadii does not inflate zero radii.
1038 * Therefore, callers should always inset or outset directly from the
1039 * original value coming from style.
1040 */
1041 static void InsetBorderRadii(nscoord aRadii[8], const nsMargin &aOffsets);
1042 static void OutsetBorderRadii(nscoord aRadii[8], const nsMargin &aOffsets);
1044 /**
1045 * Fill in border radii for this frame. Return whether any are
1046 * nonzero.
1047 *
1048 * Indices into aRadii are the NS_CORNER_* constants in nsStyleConsts.h
1049 */
1050 virtual bool GetBorderRadii(nscoord aRadii[8]) const;
1052 bool GetPaddingBoxBorderRadii(nscoord aRadii[8]) const;
1053 bool GetContentBoxBorderRadii(nscoord aRadii[8]) const;
1055 /**
1056 * Get the position of the frame's baseline, relative to the top of
1057 * the frame (its top border edge). Only valid when Reflow is not
1058 * needed.
1059 */
1060 virtual nscoord GetBaseline() const = 0;
1062 /**
1063 * Get the position of the baseline on which the caret needs to be placed,
1064 * relative to the top of the frame. This is mostly needed for frames
1065 * which return a baseline from GetBaseline which is not useful for
1066 * caret positioning.
1067 */
1068 virtual nscoord GetCaretBaseline() const {
1069 return GetBaseline();
1070 }
1072 /**
1073 * Get the specified child list.
1074 *
1075 * @param aListID identifies the requested child list.
1076 * @return the child list. If the requested list is unsupported by this
1077 * frame type, an empty list will be returned.
1078 */
1079 virtual const nsFrameList& GetChildList(ChildListID aListID) const = 0;
1080 const nsFrameList& PrincipalChildList() { return GetChildList(kPrincipalList); }
1081 virtual void GetChildLists(nsTArray<ChildList>* aLists) const = 0;
1083 /**
1084 * Gets the child lists for this frame, including
1085 * ones belong to a child document.
1086 */
1087 void GetCrossDocChildLists(nsTArray<ChildList>* aLists);
1089 // XXXbz this method should go away
1090 nsIFrame* GetFirstChild(ChildListID aListID) const {
1091 return GetChildList(aListID).FirstChild();
1092 }
1093 // XXXmats this method should also go away then
1094 nsIFrame* GetLastChild(ChildListID aListID) const {
1095 return GetChildList(aListID).LastChild();
1096 }
1097 nsIFrame* GetFirstPrincipalChild() const {
1098 return GetFirstChild(kPrincipalList);
1099 }
1101 // The individual concrete child lists.
1102 static const ChildListID kPrincipalList = mozilla::layout::kPrincipalList;
1103 static const ChildListID kAbsoluteList = mozilla::layout::kAbsoluteList;
1104 static const ChildListID kBulletList = mozilla::layout::kBulletList;
1105 static const ChildListID kCaptionList = mozilla::layout::kCaptionList;
1106 static const ChildListID kColGroupList = mozilla::layout::kColGroupList;
1107 static const ChildListID kExcessOverflowContainersList = mozilla::layout::kExcessOverflowContainersList;
1108 static const ChildListID kFixedList = mozilla::layout::kFixedList;
1109 static const ChildListID kFloatList = mozilla::layout::kFloatList;
1110 static const ChildListID kOverflowContainersList = mozilla::layout::kOverflowContainersList;
1111 static const ChildListID kOverflowList = mozilla::layout::kOverflowList;
1112 static const ChildListID kOverflowOutOfFlowList = mozilla::layout::kOverflowOutOfFlowList;
1113 static const ChildListID kPopupList = mozilla::layout::kPopupList;
1114 static const ChildListID kPushedFloatsList = mozilla::layout::kPushedFloatsList;
1115 static const ChildListID kSelectPopupList = mozilla::layout::kSelectPopupList;
1116 // A special alias for kPrincipalList that do not request reflow.
1117 static const ChildListID kNoReflowPrincipalList = mozilla::layout::kNoReflowPrincipalList;
1119 /**
1120 * Child frames are linked together in a doubly-linked list
1121 */
1122 nsIFrame* GetNextSibling() const { return mNextSibling; }
1123 void SetNextSibling(nsIFrame* aNextSibling) {
1124 NS_ASSERTION(this != aNextSibling, "Creating a circular frame list, this is very bad.");
1125 if (mNextSibling && mNextSibling->GetPrevSibling() == this) {
1126 mNextSibling->mPrevSibling = nullptr;
1127 }
1128 mNextSibling = aNextSibling;
1129 if (mNextSibling) {
1130 mNextSibling->mPrevSibling = this;
1131 }
1132 }
1134 nsIFrame* GetPrevSibling() const { return mPrevSibling; }
1136 /**
1137 * Builds the display lists for the content represented by this frame
1138 * and its descendants. The background+borders of this element must
1139 * be added first, before any other content.
1140 *
1141 * This should only be called by methods in nsFrame. Instead of calling this
1142 * directly, call either BuildDisplayListForStackingContext or
1143 * BuildDisplayListForChild.
1144 *
1145 * See nsDisplayList.h for more information about display lists.
1146 *
1147 * @param aDirtyRect content outside this rectangle can be ignored; the
1148 * rectangle is in frame coordinates
1149 */
1150 virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
1151 const nsRect& aDirtyRect,
1152 const nsDisplayListSet& aLists) {}
1153 /**
1154 * Displays the caret onto the given display list builder. The caret is
1155 * painted on top of the rest of the display list items.
1156 *
1157 * @param aDirtyRect is the dirty rectangle that we're repainting.
1158 */
1159 void DisplayCaret(nsDisplayListBuilder* aBuilder,
1160 const nsRect& aDirtyRect,
1161 nsDisplayList* aList);
1163 /**
1164 * Get the preferred caret color at the offset.
1165 *
1166 * @param aOffset is offset of the content.
1167 */
1168 virtual nscolor GetCaretColorAt(int32_t aOffset);
1171 bool IsThemed(nsITheme::Transparency* aTransparencyState = nullptr) const {
1172 return IsThemed(StyleDisplay(), aTransparencyState);
1173 }
1174 bool IsThemed(const nsStyleDisplay* aDisp,
1175 nsITheme::Transparency* aTransparencyState = nullptr) const {
1176 nsIFrame* mutable_this = const_cast<nsIFrame*>(this);
1177 if (!aDisp->mAppearance)
1178 return false;
1179 nsPresContext* pc = PresContext();
1180 nsITheme *theme = pc->GetTheme();
1181 if(!theme ||
1182 !theme->ThemeSupportsWidget(pc, mutable_this, aDisp->mAppearance))
1183 return false;
1184 if (aTransparencyState) {
1185 *aTransparencyState =
1186 theme->GetWidgetTransparency(mutable_this, aDisp->mAppearance);
1187 }
1188 return true;
1189 }
1191 /**
1192 * Builds a display list for the content represented by this frame,
1193 * treating this frame as the root of a stacking context.
1194 * @param aDirtyRect content outside this rectangle can be ignored; the
1195 * rectangle is in frame coordinates
1196 */
1197 void BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
1198 const nsRect& aDirtyRect,
1199 nsDisplayList* aList);
1201 enum {
1202 DISPLAY_CHILD_FORCE_PSEUDO_STACKING_CONTEXT = 0x01,
1203 DISPLAY_CHILD_FORCE_STACKING_CONTEXT = 0x02,
1204 DISPLAY_CHILD_INLINE = 0x04
1205 };
1206 /**
1207 * Adjusts aDirtyRect for the child's offset, checks that the dirty rect
1208 * actually intersects the child (or its descendants), calls BuildDisplayList
1209 * on the child if necessary, and puts things in the right lists if the child
1210 * is positioned.
1211 *
1212 * @param aFlags combination of DISPLAY_CHILD_FORCE_PSEUDO_STACKING_CONTEXT,
1213 * DISPLAY_CHILD_FORCE_STACKING_CONTEXT and DISPLAY_CHILD_INLINE
1214 */
1215 void BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
1216 nsIFrame* aChild,
1217 const nsRect& aDirtyRect,
1218 const nsDisplayListSet& aLists,
1219 uint32_t aFlags = 0);
1221 /**
1222 * Does this frame need a view?
1223 */
1224 virtual bool NeedsView() { return false; }
1226 /**
1227 * Returns true if this frame is transformed (e.g. has CSS or SVG transforms)
1228 * or if its parent is an SVG frame that has children-only transforms (e.g.
1229 * an SVG viewBox attribute).
1230 */
1231 bool IsTransformed() const;
1233 /**
1234 * Returns true if the frame is translucent for the purposes of creating a
1235 * stacking context.
1236 */
1237 bool HasOpacity() const
1238 {
1239 return HasOpacityInternal(1.0f);
1240 }
1241 /**
1242 * Returns true if the frame is translucent for display purposes.
1243 */
1244 bool HasVisualOpacity() const
1245 {
1246 // Treat an opacity value of 0.99 and above as opaque. This is an
1247 // optimization aimed at Web content which use opacity:0.99 as a hint for
1248 // creating a stacking context only.
1249 return HasOpacityInternal(0.99f);
1250 }
1252 /**
1253 * Return true if this frame might be using a transform getter.
1254 */
1255 virtual bool HasTransformGetter() const { return false; }
1257 /**
1258 * Returns true if this frame is an SVG frame that has SVG transforms applied
1259 * to it, or if its parent frame is an SVG frame that has children-only
1260 * transforms (e.g. an SVG viewBox attribute).
1261 * If aOwnTransforms is non-null and the frame has its own SVG transforms,
1262 * aOwnTransforms will be set to these transforms. If aFromParentTransforms
1263 * is non-null and the frame has an SVG parent with children-only transforms,
1264 * then aFromParentTransforms will be set to these transforms.
1265 */
1266 virtual bool IsSVGTransformed(Matrix *aOwnTransforms = nullptr,
1267 Matrix *aFromParentTransforms = nullptr) const;
1269 /**
1270 * Returns whether this frame will attempt to preserve the 3d transforms of its
1271 * children. This requires transform-style: preserve-3d, as well as no clipping
1272 * or svg effects.
1273 */
1274 bool Preserves3DChildren() const;
1276 /**
1277 * Returns whether this frame has a parent that Preserves3DChildren() and has
1278 * its own transform (or hidden backface) to be combined with the parent's
1279 * transform.
1280 */
1281 bool Preserves3D() const;
1283 bool HasPerspective() const;
1285 bool ChildrenHavePerspective() const;
1287 // Calculate the overflow size of all child frames, taking preserve-3d into account
1288 void ComputePreserve3DChildrenOverflow(nsOverflowAreas& aOverflowAreas, const nsRect& aBounds);
1290 void RecomputePerspectiveChildrenOverflow(const nsStyleContext* aStartStyle, const nsRect* aBounds);
1292 /**
1293 * Returns the number of ancestors between this and the root of our frame tree
1294 */
1295 uint32_t GetDepthInFrameTree() {
1296 uint32_t result = 0;
1297 for (nsIFrame* ancestor = GetParent(); ancestor;
1298 ancestor = ancestor->GetParent()) {
1299 result++;
1300 }
1301 return result;
1302 }
1304 /**
1305 * Event handling of GUI events.
1306 *
1307 * @param aEvent event structure describing the type of event and rge widget
1308 * where the event originated
1309 * The |point| member of this is in the coordinate system of the
1310 * view returned by GetOffsetFromView.
1311 * @param aEventStatus a return value indicating whether the event was handled
1312 * and whether default processing should be done
1313 *
1314 * XXX From a frame's perspective it's unclear what the effect of the event status
1315 * is. Does it cause the event to continue propagating through the frame hierarchy
1316 * or is it just returned to the widgets?
1317 *
1318 * @see WidgetGUIEvent
1319 * @see nsEventStatus
1320 */
1321 virtual nsresult HandleEvent(nsPresContext* aPresContext,
1322 mozilla::WidgetGUIEvent* aEvent,
1323 nsEventStatus* aEventStatus) = 0;
1325 virtual nsresult GetContentForEvent(mozilla::WidgetEvent* aEvent,
1326 nsIContent** aContent) = 0;
1328 // This structure keeps track of the content node and offsets associated with
1329 // a point; there is a primary and a secondary offset associated with any
1330 // point. The primary and secondary offsets differ when the point is over a
1331 // non-text object. The primary offset is the expected position of the
1332 // cursor calculated from a point; the secondary offset, when it is different,
1333 // indicates that the point is in the boundaries of some selectable object.
1334 // Note that the primary offset can be after the secondary offset; for places
1335 // that need the beginning and end of the object, the StartOffset and
1336 // EndOffset helpers can be used.
1337 struct MOZ_STACK_CLASS ContentOffsets {
1338 ContentOffsets();
1339 ContentOffsets(const ContentOffsets&);
1340 ~ContentOffsets();
1341 nsCOMPtr<nsIContent> content;
1342 bool IsNull() { return !content; }
1343 int32_t offset;
1344 int32_t secondaryOffset;
1345 // Helpers for places that need the ends of the offsets and expect them in
1346 // numerical order, as opposed to wanting the primary and secondary offsets
1347 int32_t StartOffset() { return std::min(offset, secondaryOffset); }
1348 int32_t EndOffset() { return std::max(offset, secondaryOffset); }
1349 // This boolean indicates whether the associated content is before or after
1350 // the offset; the most visible use is to allow the caret to know which line
1351 // to display on.
1352 bool associateWithNext;
1353 };
1354 enum {
1355 IGNORE_SELECTION_STYLE = 0x01,
1356 // Treat visibility:hidden frames as non-selectable
1357 SKIP_HIDDEN = 0x02
1358 };
1359 /**
1360 * This function calculates the content offsets for selection relative to
1361 * a point. Note that this should generally only be callled on the event
1362 * frame associated with an event because this function does not account
1363 * for frame lists other than the primary one.
1364 * @param aPoint point relative to this frame
1365 */
1366 ContentOffsets GetContentOffsetsFromPoint(nsPoint aPoint,
1367 uint32_t aFlags = 0);
1369 virtual ContentOffsets GetContentOffsetsFromPointExternal(nsPoint aPoint,
1370 uint32_t aFlags = 0)
1371 { return GetContentOffsetsFromPoint(aPoint, aFlags); }
1373 /**
1374 * Ensure that aImage gets notifed when the underlying image request loads
1375 * or animates.
1376 */
1377 void AssociateImage(const nsStyleImage& aImage, nsPresContext* aPresContext);
1379 /**
1380 * This structure holds information about a cursor. mContainer represents a
1381 * loaded image that should be preferred. If it is not possible to use it, or
1382 * if it is null, mCursor should be used.
1383 */
1384 struct MOZ_STACK_CLASS Cursor {
1385 nsCOMPtr<imgIContainer> mContainer;
1386 int32_t mCursor;
1387 bool mHaveHotspot;
1388 float mHotspotX, mHotspotY;
1389 };
1390 /**
1391 * Get the cursor for a given frame.
1392 */
1393 virtual nsresult GetCursor(const nsPoint& aPoint,
1394 Cursor& aCursor) = 0;
1396 /**
1397 * Get a point (in the frame's coordinate space) given an offset into
1398 * the content. This point should be on the baseline of text with
1399 * the correct horizontal offset
1400 */
1401 virtual nsresult GetPointFromOffset(int32_t inOffset,
1402 nsPoint* outPoint) = 0;
1404 /**
1405 * Get the child frame of this frame which contains the given
1406 * content offset. outChildFrame may be this frame, or nullptr on return.
1407 * outContentOffset returns the content offset relative to the start
1408 * of the returned node. You can also pass a hint which tells the method
1409 * to stick to the end of the first found frame or the beginning of the
1410 * next in case the offset falls on a boundary.
1411 */
1412 virtual nsresult GetChildFrameContainingOffset(int32_t inContentOffset,
1413 bool inHint,//false stick left
1414 int32_t* outFrameContentOffset,
1415 nsIFrame** outChildFrame) = 0;
1417 /**
1418 * Get the current frame-state value for this frame. aResult is
1419 * filled in with the state bits.
1420 */
1421 nsFrameState GetStateBits() const { return mState; }
1423 /**
1424 * Update the current frame-state value for this frame.
1425 */
1426 void AddStateBits(nsFrameState aBits) { mState |= aBits; }
1427 void RemoveStateBits(nsFrameState aBits) { mState &= ~aBits; }
1429 /**
1430 * Checks if the current frame-state includes all of the listed bits
1431 */
1432 bool HasAllStateBits(nsFrameState aBits) const
1433 {
1434 return (mState & aBits) == aBits;
1435 }
1437 /**
1438 * Checks if the current frame-state includes any of the listed bits
1439 */
1440 bool HasAnyStateBits(nsFrameState aBits) const
1441 {
1442 return mState & aBits;
1443 }
1445 /**
1446 * This call is invoked on the primary frame for a character data content
1447 * node, when it is changed in the content tree.
1448 */
1449 virtual nsresult CharacterDataChanged(CharacterDataChangeInfo* aInfo) = 0;
1451 /**
1452 * This call is invoked when the value of a content objects's attribute
1453 * is changed.
1454 * The first frame that maps that content is asked to deal
1455 * with the change by doing whatever is appropriate.
1456 *
1457 * @param aNameSpaceID the namespace of the attribute
1458 * @param aAttribute the atom name of the attribute
1459 * @param aModType Whether or not the attribute was added, changed, or removed.
1460 * The constants are defined in nsIDOMMutationEvent.h.
1461 */
1462 virtual nsresult AttributeChanged(int32_t aNameSpaceID,
1463 nsIAtom* aAttribute,
1464 int32_t aModType) = 0;
1466 /**
1467 * When the content states of a content object change, this method is invoked
1468 * on the primary frame of that content object.
1469 *
1470 * @param aStates the changed states
1471 */
1472 virtual void ContentStatesChanged(mozilla::EventStates aStates);
1474 /**
1475 * Return how your frame can be split.
1476 */
1477 virtual nsSplittableType GetSplittableType() const = 0;
1479 /**
1480 * Continuation member functions
1481 */
1482 virtual nsIFrame* GetPrevContinuation() const = 0;
1483 virtual void SetPrevContinuation(nsIFrame*) = 0;
1484 virtual nsIFrame* GetNextContinuation() const = 0;
1485 virtual void SetNextContinuation(nsIFrame*) = 0;
1486 virtual nsIFrame* FirstContinuation() const {
1487 return const_cast<nsIFrame*>(this);
1488 }
1489 virtual nsIFrame* LastContinuation() const {
1490 return const_cast<nsIFrame*>(this);
1491 }
1493 /**
1494 * GetTailContinuation gets the last non-overflow-container continuation
1495 * in the continuation chain, i.e. where the next sibling element
1496 * should attach).
1497 */
1498 nsIFrame* GetTailContinuation();
1500 /**
1501 * Flow member functions
1502 */
1503 virtual nsIFrame* GetPrevInFlowVirtual() const = 0;
1504 nsIFrame* GetPrevInFlow() const { return GetPrevInFlowVirtual(); }
1505 virtual void SetPrevInFlow(nsIFrame*) = 0;
1507 virtual nsIFrame* GetNextInFlowVirtual() const = 0;
1508 nsIFrame* GetNextInFlow() const { return GetNextInFlowVirtual(); }
1509 virtual void SetNextInFlow(nsIFrame*) = 0;
1511 /**
1512 * Return the first frame in our current flow.
1513 */
1514 virtual nsIFrame* FirstInFlow() const {
1515 return const_cast<nsIFrame*>(this);
1516 }
1518 /**
1519 * Return the last frame in our current flow.
1520 */
1521 virtual nsIFrame* LastInFlow() const {
1522 return const_cast<nsIFrame*>(this);
1523 }
1526 /**
1527 * Mark any stored intrinsic width information as dirty (requiring
1528 * re-calculation). Note that this should generally not be called
1529 * directly; nsPresShell::FrameNeedsReflow will call it instead.
1530 */
1531 virtual void MarkIntrinsicWidthsDirty() = 0;
1533 /**
1534 * Get the intrinsic minimum width of the frame. This must be less
1535 * than or equal to the intrinsic width.
1536 *
1537 * This is *not* affected by the CSS 'min-width', 'width', and
1538 * 'max-width' properties on this frame, but it is affected by the
1539 * values of those properties on this frame's descendants. (It may be
1540 * called during computation of the values of those properties, so it
1541 * cannot depend on any values in the nsStylePosition for this frame.)
1542 *
1543 * The value returned should **NOT** include the space required for
1544 * padding and border.
1545 *
1546 * Note that many frames will cache the result of this function call
1547 * unless MarkIntrinsicWidthsDirty is called.
1548 *
1549 * It is not acceptable for a frame to mark itself dirty when this
1550 * method is called.
1551 *
1552 * This method must not return a negative value.
1553 */
1554 virtual nscoord GetMinWidth(nsRenderingContext *aRenderingContext) = 0;
1556 /**
1557 * Get the intrinsic width of the frame. This must be greater than or
1558 * equal to the intrinsic minimum width.
1559 *
1560 * Otherwise, all the comments for |GetMinWidth| above apply.
1561 */
1562 virtual nscoord GetPrefWidth(nsRenderingContext *aRenderingContext) = 0;
1564 /**
1565 * |InlineIntrinsicWidth| represents the intrinsic width information
1566 * in inline layout. Code that determines the intrinsic width of a
1567 * region of inline layout accumulates the result into this structure.
1568 * This pattern is needed because we need to maintain state
1569 * information about whitespace (for both collapsing and trimming).
1570 */
1571 struct InlineIntrinsicWidthData {
1572 InlineIntrinsicWidthData()
1573 : line(nullptr)
1574 , lineContainer(nullptr)
1575 , prevLines(0)
1576 , currentLine(0)
1577 , skipWhitespace(true)
1578 , trailingWhitespace(0)
1579 {}
1581 // The line. This may be null if the inlines are not associated with
1582 // a block or if we just don't know the line.
1583 const nsLineList_iterator* line;
1585 // The line container.
1586 nsIFrame* lineContainer;
1588 // The maximum intrinsic width for all previous lines.
1589 nscoord prevLines;
1591 // The maximum intrinsic width for the current line. At a line
1592 // break (mandatory for preferred width; allowed for minimum width),
1593 // the caller should call |Break()|.
1594 nscoord currentLine;
1596 // True if initial collapsable whitespace should be skipped. This
1597 // should be true at the beginning of a block, after hard breaks
1598 // and when the last text ended with whitespace.
1599 bool skipWhitespace;
1601 // This contains the width of the trimmable whitespace at the end of
1602 // |currentLine|; it is zero if there is no such whitespace.
1603 nscoord trailingWhitespace;
1605 // Floats encountered in the lines.
1606 class FloatInfo {
1607 public:
1608 FloatInfo(const nsIFrame* aFrame, nscoord aWidth)
1609 : mFrame(aFrame), mWidth(aWidth)
1610 { }
1611 const nsIFrame* Frame() const { return mFrame; }
1612 nscoord Width() const { return mWidth; }
1614 private:
1615 const nsIFrame* mFrame;
1616 nscoord mWidth;
1617 };
1619 nsTArray<FloatInfo> floats;
1620 };
1622 struct InlineMinWidthData : public InlineIntrinsicWidthData {
1623 InlineMinWidthData()
1624 : trailingTextFrame(nullptr)
1625 , atStartOfLine(true)
1626 {}
1628 // We need to distinguish forced and optional breaks for cases where the
1629 // current line total is negative. When it is, we need to ignore
1630 // optional breaks to prevent min-width from ending up bigger than
1631 // pref-width.
1632 void ForceBreak(nsRenderingContext *aRenderingContext);
1634 // If the break here is actually taken, aHyphenWidth must be added to the
1635 // width of the current line.
1636 void OptionallyBreak(nsRenderingContext *aRenderingContext,
1637 nscoord aHyphenWidth = 0);
1639 // The last text frame processed so far in the current line, when
1640 // the last characters in that text frame are relevant for line
1641 // break opportunities.
1642 nsIFrame *trailingTextFrame;
1644 // Whether we're currently at the start of the line. If we are, we
1645 // can't break (for example, between the text-indent and the first
1646 // word).
1647 bool atStartOfLine;
1648 };
1650 struct InlinePrefWidthData : public InlineIntrinsicWidthData {
1651 void ForceBreak(nsRenderingContext *aRenderingContext);
1652 };
1654 /**
1655 * Add the intrinsic minimum width of a frame in a way suitable for
1656 * use in inline layout to an |InlineIntrinsicWidthData| object that
1657 * represents the intrinsic width information of all the previous
1658 * frames in the inline layout region.
1659 *
1660 * All *allowed* breakpoints within the frame determine what counts as
1661 * a line for the |InlineIntrinsicWidthData|. This means that
1662 * |aData->trailingWhitespace| will always be zero (unlike for
1663 * AddInlinePrefWidth).
1664 *
1665 * All the comments for |GetMinWidth| apply, except that this function
1666 * is responsible for adding padding, border, and margin and for
1667 * considering the effects of 'width', 'min-width', and 'max-width'.
1668 *
1669 * This may be called on any frame. Frames that do not participate in
1670 * line breaking can inherit the default implementation on nsFrame,
1671 * which calls |GetMinWidth|.
1672 */
1673 virtual void
1674 AddInlineMinWidth(nsRenderingContext *aRenderingContext,
1675 InlineMinWidthData *aData) = 0;
1677 /**
1678 * Add the intrinsic preferred width of a frame in a way suitable for
1679 * use in inline layout to an |InlineIntrinsicWidthData| object that
1680 * represents the intrinsic width information of all the previous
1681 * frames in the inline layout region.
1682 *
1683 * All the comments for |AddInlineMinWidth| and |GetPrefWidth| apply,
1684 * except that this fills in an |InlineIntrinsicWidthData| structure
1685 * based on using all *mandatory* breakpoints within the frame.
1686 */
1687 virtual void
1688 AddInlinePrefWidth(nsRenderingContext *aRenderingContext,
1689 InlinePrefWidthData *aData) = 0;
1691 /**
1692 * Return the horizontal components of padding, border, and margin
1693 * that contribute to the intrinsic width that applies to the parent.
1694 */
1695 struct IntrinsicWidthOffsetData {
1696 nscoord hPadding, hBorder, hMargin;
1697 float hPctPadding, hPctMargin;
1699 IntrinsicWidthOffsetData()
1700 : hPadding(0), hBorder(0), hMargin(0)
1701 , hPctPadding(0.0f), hPctMargin(0.0f)
1702 {}
1703 };
1704 virtual IntrinsicWidthOffsetData
1705 IntrinsicWidthOffsets(nsRenderingContext* aRenderingContext) = 0;
1707 virtual mozilla::IntrinsicSize GetIntrinsicSize() = 0;
1709 /*
1710 * Get the intrinsic ratio of this element, or nsSize(0,0) if it has
1711 * no intrinsic ratio. The intrinsic ratio is the ratio of the
1712 * height/width of a box with an intrinsic size or the intrinsic
1713 * aspect ratio of a scalable vector image without an intrinsic size.
1714 *
1715 * Either one of the sides may be zero, indicating a zero or infinite
1716 * ratio.
1717 */
1718 virtual nsSize GetIntrinsicRatio() = 0;
1720 /**
1721 * Bit-flags to pass to ComputeSize in |aFlags| parameter.
1722 */
1723 enum {
1724 /* Set if the frame is in a context where non-replaced blocks should
1725 * shrink-wrap (e.g., it's floating, absolutely positioned, or
1726 * inline-block). */
1727 eShrinkWrap = 1 << 0,
1728 /* Set if we'd like to compute our 'auto' height, regardless of our actual
1729 * computed value of 'height'. (e.g. to get an intrinsic height for flex
1730 * items with "min-height: auto" to use during flexbox layout.) */
1731 eUseAutoHeight = 1 << 1
1732 };
1734 /**
1735 * Compute the size that a frame will occupy. Called while
1736 * constructing the nsHTMLReflowState to be used to Reflow the frame,
1737 * in order to fill its mComputedWidth and mComputedHeight member
1738 * variables.
1739 *
1740 * The |height| member of the return value may be
1741 * NS_UNCONSTRAINEDSIZE, but the |width| member must not be.
1742 *
1743 * Note that the reason that border and padding need to be passed
1744 * separately is so that the 'box-sizing' property can be handled.
1745 * Thus aMargin includes absolute positioning offsets as well.
1746 *
1747 * @param aCBSize The size of the element's containing block. (Well,
1748 * the |height| component isn't really.)
1749 * @param aAvailableWidth The available width for 'auto' widths.
1750 * This is usually the same as aCBSize.width,
1751 * but differs in cases such as block
1752 * formatting context roots next to floats, or
1753 * in some cases of float reflow in quirks
1754 * mode.
1755 * @param aMargin The sum of the vertical / horizontal margins
1756 * ***AND*** absolute positioning offsets (top, right,
1757 * bottom, left) of the frame, including actual values
1758 * resulting from percentages and from the
1759 * "hypothetical box" for absolute positioning, but
1760 * not including actual values resulting from 'auto'
1761 * margins or ignored 'auto' values in absolute
1762 * positioning.
1763 * @param aBorder The sum of the vertical / horizontal border widths
1764 * of the frame.
1765 * @param aPadding The sum of the vertical / horizontal margins of
1766 * the frame, including actual values resulting from
1767 * percentages.
1768 * @param aFlags Flags to further customize behavior (definitions above).
1769 */
1770 virtual nsSize ComputeSize(nsRenderingContext *aRenderingContext,
1771 nsSize aCBSize, nscoord aAvailableWidth,
1772 nsSize aMargin, nsSize aBorder, nsSize aPadding,
1773 uint32_t aFlags) = 0;
1775 /**
1776 * Compute a tight bounding rectangle for the frame. This is a rectangle
1777 * that encloses the pixels that are actually drawn. We're allowed to be
1778 * conservative and currently we don't try very hard. The rectangle is
1779 * in appunits and relative to the origin of this frame.
1780 *
1781 * This probably only needs to include frame bounds, glyph bounds, and
1782 * text decorations, but today it sometimes includes other things that
1783 * contribute to visual overflow.
1784 *
1785 * @param aContext a rendering context that can be used if we need
1786 * to do measurement
1787 */
1788 virtual nsRect ComputeTightBounds(gfxContext* aContext) const;
1790 /**
1791 * This function is similar to GetPrefWidth and ComputeTightBounds: it
1792 * computes the left and right coordinates of a preferred tight bounding
1793 * rectangle for the frame. This is a rectangle that would enclose the pixels
1794 * that are drawn if we lay out the element without taking any optional line
1795 * breaks. The rectangle is in appunits and relative to the origin of this
1796 * frame. Currently, this function is only implemented for nsBlockFrame and
1797 * nsTextFrame and is used to determine intrinsic widths of MathML token
1798 * elements.
1800 * @param aContext a rendering context that can be used if we need
1801 * to do measurement
1802 * @param aX computed left coordinate of the tight bounding rectangle
1803 * @param aXMost computed intrinsic width of the tight bounding rectangle
1804 *
1805 */
1806 virtual nsresult GetPrefWidthTightBounds(nsRenderingContext* aContext,
1807 nscoord* aX,
1808 nscoord* aXMost);
1810 /**
1811 * Pre-reflow hook. Before a frame is reflowed this method will be called.
1812 * This call will always be invoked at least once before a subsequent Reflow
1813 * and DidReflow call. It may be called more than once, In general you will
1814 * receive on WillReflow notification before each Reflow request.
1815 *
1816 * XXX Is this really the semantics we want? Because we have the NS_FRAME_IN_REFLOW
1817 * bit we can ensure we don't call it more than once...
1818 */
1819 virtual nsresult WillReflow(nsPresContext* aPresContext) = 0;
1821 /**
1822 * The frame is given an available size and asked for its desired
1823 * size. This is the frame's opportunity to reflow its children.
1824 *
1825 * If the frame has the NS_FRAME_IS_DIRTY bit set then it is
1826 * responsible for completely reflowing itself and all of its
1827 * descendants.
1828 *
1829 * Otherwise, if the frame has the NS_FRAME_HAS_DIRTY_CHILDREN bit
1830 * set, then it is responsible for reflowing at least those
1831 * children that have NS_FRAME_HAS_DIRTY_CHILDREN or NS_FRAME_IS_DIRTY
1832 * set.
1833 *
1834 * If a difference in available size from the previous reflow causes
1835 * the frame's size to change, it should reflow descendants as needed.
1836 *
1837 * @param aReflowMetrics <i>out</i> parameter where you should return the
1838 * desired size and ascent/descent info. You should include any
1839 * space you want for border/padding in the desired size you return.
1840 *
1841 * It's okay to return a desired size that exceeds the avail
1842 * size if that's the smallest you can be, i.e. it's your
1843 * minimum size.
1844 *
1845 * For an incremental reflow you are responsible for invalidating
1846 * any area within your frame that needs repainting (including
1847 * borders). If your new desired size is different than your current
1848 * size, then your parent frame is responsible for making sure that
1849 * the difference between the two rects is repainted
1850 *
1851 * @param aReflowState information about your reflow including the reason
1852 * for the reflow and the available space in which to lay out. Each
1853 * dimension of the available space can either be constrained or
1854 * unconstrained (a value of NS_UNCONSTRAINEDSIZE).
1855 *
1856 * Note that the available space can be negative. In this case you
1857 * still must return an accurate desired size. If you're a container
1858 * you must <b>always</b> reflow at least one frame regardless of the
1859 * available space
1860 *
1861 * @param aStatus a return value indicating whether the frame is complete
1862 * and whether the next-in-flow is dirty and needs to be reflowed
1863 */
1864 virtual nsresult Reflow(nsPresContext* aPresContext,
1865 nsHTMLReflowMetrics& aReflowMetrics,
1866 const nsHTMLReflowState& aReflowState,
1867 nsReflowStatus& aStatus) = 0;
1869 /**
1870 * Post-reflow hook. After a frame is reflowed this method will be called
1871 * informing the frame that this reflow process is complete, and telling the
1872 * frame the status returned by the Reflow member function.
1873 *
1874 * This call may be invoked many times, while NS_FRAME_IN_REFLOW is set, before
1875 * it is finally called once with a NS_FRAME_REFLOW_COMPLETE value. When called
1876 * with a NS_FRAME_REFLOW_COMPLETE value the NS_FRAME_IN_REFLOW bit in the
1877 * frame state will be cleared.
1878 *
1879 * XXX This doesn't make sense. If the frame is reflowed but not complete, then
1880 * the status should be NS_FRAME_NOT_COMPLETE and not NS_FRAME_COMPLETE
1881 * XXX Don't we want the semantics to dictate that we only call this once for
1882 * a given reflow?
1883 */
1884 virtual nsresult DidReflow(nsPresContext* aPresContext,
1885 const nsHTMLReflowState* aReflowState,
1886 nsDidReflowStatus aStatus) = 0;
1888 // XXX Maybe these three should be a separate interface?
1890 /**
1891 * Updates the overflow areas of the frame. This can be called if an
1892 * overflow area of the frame's children has changed without reflowing.
1893 * @return true if either of the overflow areas for this frame have changed.
1894 */
1895 virtual bool UpdateOverflow() = 0;
1897 /**
1898 * Helper method used by block reflow to identify runs of text so
1899 * that proper word-breaking can be done.
1900 *
1901 * @return
1902 * true if we can continue a "text run" through the frame. A
1903 * text run is text that should be treated contiguously for line
1904 * and word breaking.
1905 */
1906 virtual bool CanContinueTextRun() const = 0;
1908 /**
1909 * Append the rendered text to the passed-in string.
1910 * The appended text will often not contain all the whitespace from source,
1911 * depending on whether the CSS rule "white-space: pre" is active for this frame.
1912 * if aStartOffset + aLength goes past end, or if aLength is not specified
1913 * then use the text up to the string's end.
1914 * Call this on the primary frame for a text node.
1915 * @param aAppendToString String to append text to, or null if text should not be returned
1916 * @param aSkipChars if aSkipIter is non-null, this must also be non-null.
1917 * This gets used as backing data for the iterator so it should outlive the iterator.
1918 * @param aSkipIter Where to fill in the gfxSkipCharsIterator info, or null if not needed by caller
1919 * @param aStartOffset Skipped (rendered text) start offset
1920 * @param aSkippedMaxLength Maximum number of characters to return
1921 * The iterator can be used to map content offsets to offsets in the returned string, or vice versa.
1922 */
1923 virtual nsresult GetRenderedText(nsAString* aAppendToString = nullptr,
1924 gfxSkipChars* aSkipChars = nullptr,
1925 gfxSkipCharsIterator* aSkipIter = nullptr,
1926 uint32_t aSkippedStartOffset = 0,
1927 uint32_t aSkippedMaxLength = UINT32_MAX)
1928 { return NS_ERROR_NOT_IMPLEMENTED; }
1930 /**
1931 * Returns true if the frame contains any non-collapsed characters.
1932 * This method is only available for text frames, and it will return false
1933 * for all other frame types.
1934 */
1935 virtual bool HasAnyNoncollapsedCharacters()
1936 { return false; }
1938 /**
1939 * Accessor functions to get/set the associated view object
1940 *
1941 * GetView returns non-null if and only if |HasView| returns true.
1942 */
1943 bool HasView() const { return !!(mState & NS_FRAME_HAS_VIEW); }
1944 nsView* GetView() const;
1945 virtual nsView* GetViewExternal() const;
1946 nsresult SetView(nsView* aView);
1948 /**
1949 * Find the closest view (on |this| or an ancestor).
1950 * If aOffset is non-null, it will be set to the offset of |this|
1951 * from the returned view.
1952 */
1953 nsView* GetClosestView(nsPoint* aOffset = nullptr) const;
1955 /**
1956 * Find the closest ancestor (excluding |this| !) that has a view
1957 */
1958 nsIFrame* GetAncestorWithView() const;
1959 virtual nsIFrame* GetAncestorWithViewExternal() const;
1961 /**
1962 * Get the offset between the coordinate systems of |this| and aOther.
1963 * Adding the return value to a point in the coordinate system of |this|
1964 * will transform the point to the coordinate system of aOther.
1965 *
1966 * aOther must be non-null.
1967 *
1968 * This function is fastest when aOther is an ancestor of |this|.
1969 *
1970 * This function _DOES NOT_ work across document boundaries.
1971 * Use this function only when |this| and aOther are in the same document.
1972 *
1973 * NOTE: this actually returns the offset from aOther to |this|, but
1974 * that offset is added to transform _coordinates_ from |this| to
1975 * aOther.
1976 */
1977 nsPoint GetOffsetTo(const nsIFrame* aOther) const;
1978 virtual nsPoint GetOffsetToExternal(const nsIFrame* aOther) const;
1980 /**
1981 * Get the offset between the coordinate systems of |this| and aOther
1982 * expressed in appunits per dev pixel of |this|' document. Adding the return
1983 * value to a point that is relative to the origin of |this| will make the
1984 * point relative to the origin of aOther but in the appunits per dev pixel
1985 * ratio of |this|.
1986 *
1987 * aOther must be non-null.
1988 *
1989 * This function is fastest when aOther is an ancestor of |this|.
1990 *
1991 * This function works across document boundaries.
1992 *
1993 * Because this function may cross document boundaries that have different
1994 * app units per dev pixel ratios it needs to be used very carefully.
1995 *
1996 * NOTE: this actually returns the offset from aOther to |this|, but
1997 * that offset is added to transform _coordinates_ from |this| to
1998 * aOther.
1999 */
2000 nsPoint GetOffsetToCrossDoc(const nsIFrame* aOther) const;
2002 /**
2003 * Get the screen rect of the frame in pixels.
2004 * @return the pixel rect of the frame in screen coordinates.
2005 */
2006 nsIntRect GetScreenRect() const;
2007 virtual nsIntRect GetScreenRectExternal() const;
2009 /**
2010 * Get the screen rect of the frame in app units.
2011 * @return the app unit rect of the frame in screen coordinates.
2012 */
2013 nsRect GetScreenRectInAppUnits() const;
2014 virtual nsRect GetScreenRectInAppUnitsExternal() const;
2016 /**
2017 * Returns the offset from this frame to the closest geometric parent that
2018 * has a view. Also returns the containing view or null in case of error
2019 */
2020 void GetOffsetFromView(nsPoint& aOffset, nsView** aView) const;
2022 /**
2023 * Returns the nearest widget containing this frame. If this frame has a
2024 * view and the view has a widget, then this frame's widget is
2025 * returned, otherwise this frame's geometric parent is checked
2026 * recursively upwards.
2027 * XXX virtual because gfx callers use it! (themes)
2028 */
2029 virtual nsIWidget* GetNearestWidget() const;
2031 /**
2032 * Same as GetNearestWidget() above but uses an outparam to return the offset
2033 * of this frame to the returned widget expressed in appunits of |this| (the
2034 * widget might be in a different document with a different zoom).
2035 */
2036 virtual nsIWidget* GetNearestWidget(nsPoint& aOffset) const;
2038 /**
2039 * Get the "type" of the frame. May return nullptr.
2040 *
2041 * @see nsGkAtoms
2042 */
2043 virtual nsIAtom* GetType() const = 0;
2045 /**
2046 * Returns a transformation matrix that converts points in this frame's
2047 * coordinate space to points in some ancestor frame's coordinate space.
2048 * The frame decides which ancestor it will use as a reference point.
2049 * If this frame has no ancestor, aOutAncestor will be set to null.
2050 *
2051 * @param aStopAtAncestor don't look further than aStopAtAncestor. If null,
2052 * all ancestors (including across documents) will be traversed.
2053 * @param aOutAncestor [out] The ancestor frame the frame has chosen. If
2054 * this frame has no ancestor, *aOutAncestor will be set to null. If
2055 * this frame is not a root frame, then *aOutAncestor will be in the same
2056 * document as this frame. If this frame IsTransformed(), then *aOutAncestor
2057 * will be the parent frame (if not preserve-3d) or the nearest non-transformed
2058 * ancestor (if preserve-3d).
2059 * @return A gfxMatrix that converts points in this frame's coordinate space
2060 * into points in aOutAncestor's coordinate space.
2061 */
2062 gfx3DMatrix GetTransformMatrix(const nsIFrame* aStopAtAncestor,
2063 nsIFrame **aOutAncestor);
2065 /**
2066 * Bit-flags to pass to IsFrameOfType()
2067 */
2068 enum {
2069 eMathML = 1 << 0,
2070 eSVG = 1 << 1,
2071 eSVGForeignObject = 1 << 2,
2072 eSVGContainer = 1 << 3,
2073 eSVGGeometry = 1 << 4,
2074 eSVGPaintServer = 1 << 5,
2075 eBidiInlineContainer = 1 << 6,
2076 // the frame is for a replaced element, such as an image
2077 eReplaced = 1 << 7,
2078 // Frame that contains a block but looks like a replaced element
2079 // from the outside
2080 eReplacedContainsBlock = 1 << 8,
2081 // A frame that participates in inline reflow, i.e., one that
2082 // requires nsHTMLReflowState::mLineLayout.
2083 eLineParticipant = 1 << 9,
2084 eXULBox = 1 << 10,
2085 eCanContainOverflowContainers = 1 << 11,
2086 eBlockFrame = 1 << 12,
2087 eTablePart = 1 << 13,
2088 // If this bit is set, the frame doesn't allow ignorable whitespace as
2089 // children. For example, the whitespace between <table>\n<tr>\n<td>
2090 // will be excluded during the construction of children.
2091 eExcludesIgnorableWhitespace = 1 << 14,
2092 eSupportsCSSTransforms = 1 << 15,
2094 // These are to allow nsFrame::Init to assert that IsFrameOfType
2095 // implementations all call the base class method. They are only
2096 // meaningful in DEBUG builds.
2097 eDEBUGAllFrames = 1 << 30,
2098 eDEBUGNoFrames = 1 << 31
2099 };
2101 /**
2102 * API for doing a quick check if a frame is of a given
2103 * type. Returns true if the frame matches ALL flags passed in.
2104 *
2105 * Implementations should always override with inline virtual
2106 * functions that call the base class's IsFrameOfType method.
2107 */
2108 virtual bool IsFrameOfType(uint32_t aFlags) const
2109 {
2110 #ifdef DEBUG
2111 return !(aFlags & ~(nsIFrame::eDEBUGAllFrames | nsIFrame::eSupportsCSSTransforms));
2112 #else
2113 return !(aFlags & ~nsIFrame::eSupportsCSSTransforms);
2114 #endif
2115 }
2117 /**
2118 * Returns true if the frame is a block wrapper.
2119 */
2120 bool IsBlockWrapper() const;
2122 /**
2123 * Get this frame's CSS containing block.
2124 *
2125 * The algorithm is defined in
2126 * http://www.w3.org/TR/CSS2/visudet.html#containing-block-details.
2127 *
2128 * NOTE: This is guaranteed to return a non-null pointer when invoked on any
2129 * frame other than the root frame.
2130 */
2131 nsIFrame* GetContainingBlock() const;
2133 /**
2134 * Is this frame a containing block for floating elements?
2135 * Note that very few frames are, so default to false.
2136 */
2137 virtual bool IsFloatContainingBlock() const { return false; }
2139 /**
2140 * Is this a leaf frame? Frames that want the frame constructor to be able
2141 * to construct kids for them should return false, all others should return
2142 * true. Note that returning true here does not mean that the frame _can't_
2143 * have kids. It could still have kids created via
2144 * nsIAnonymousContentCreator. Returning true indicates that "normal"
2145 * (non-anonymous, XBL-bound, CSS generated content, etc) children should not
2146 * be constructed.
2147 */
2148 virtual bool IsLeaf() const;
2150 /**
2151 * Marks all display items created by this frame as needing a repaint,
2152 * and calls SchedulePaint() if requested and one is not already pending.
2153 *
2154 * This includes all display items created by this frame, including
2155 * container types.
2156 *
2157 * @param aDisplayItemKey If specified, only issues an invalidate
2158 * if this frame painted a display item of that type during the
2159 * previous paint. SVG rendering observers are always notified.
2160 */
2161 virtual void InvalidateFrame(uint32_t aDisplayItemKey = 0);
2163 /**
2164 * Same as InvalidateFrame(), but only mark a fixed rect as needing
2165 * repainting.
2166 *
2167 * @param aRect The rect to invalidate, relative to the TopLeft of the
2168 * frame's border box.
2169 * @param aDisplayItemKey If specified, only issues an invalidate
2170 * if this frame painted a display item of that type during the
2171 * previous paint. SVG rendering observers are always notified.
2172 */
2173 virtual void InvalidateFrameWithRect(const nsRect& aRect, uint32_t aDisplayItemKey = 0);
2175 /**
2176 * Calls InvalidateFrame() on all frames descendant frames (including
2177 * this one).
2178 *
2179 * This function doesn't walk through placeholder frames to invalidate
2180 * the out-of-flow frames.
2181 *
2182 * @param aDisplayItemKey If specified, only issues an invalidate
2183 * if this frame painted a display item of that type during the
2184 * previous paint. SVG rendering observers are always notified.
2185 */
2186 void InvalidateFrameSubtree(uint32_t aDisplayItemKey = 0);
2188 /**
2189 * Called when a frame is about to be removed and needs to be invalidated.
2190 * Normally does nothing since DLBI handles removed frames.
2191 */
2192 virtual void InvalidateFrameForRemoval() {}
2194 /**
2195 * When HasUserData(frame->LayerIsPrerenderedDataKey()), then the
2196 * entire overflow area of this frame has been rendered in its
2197 * layer(s).
2198 */
2199 static void* LayerIsPrerenderedDataKey() {
2200 return &sLayerIsPrerenderedDataKey;
2201 }
2202 static uint8_t sLayerIsPrerenderedDataKey;
2204 /**
2205 * Try to update this frame's transform without invalidating any
2206 * content. Return true iff successful. If unsuccessful, the
2207 * caller is responsible for scheduling an invalidating paint.
2208 *
2209 * If the result is true, aLayerResult will be filled in with the
2210 * transform layer for the frame.
2211 */
2212 bool TryUpdateTransformOnly(Layer** aLayerResult);
2214 /**
2215 * Checks if a frame has had InvalidateFrame() called on it since the
2216 * last paint.
2217 *
2218 * If true, then the invalid rect is returned in aRect, with an
2219 * empty rect meaning all pixels drawn by this frame should be
2220 * invalidated.
2221 * If false, aRect is left unchanged.
2222 */
2223 bool IsInvalid(nsRect& aRect);
2225 /**
2226 * Check if any frame within the frame subtree (including this frame)
2227 * returns true for IsInvalid().
2228 */
2229 bool HasInvalidFrameInSubtree()
2230 {
2231 return HasAnyStateBits(NS_FRAME_NEEDS_PAINT | NS_FRAME_DESCENDANT_NEEDS_PAINT);
2232 }
2234 /**
2235 * Removes the invalid state from the current frame and all
2236 * descendant frames.
2237 */
2238 void ClearInvalidationStateBits();
2240 /**
2241 * Ensures that the refresh driver is running, and schedules a view
2242 * manager flush on the next tick.
2243 *
2244 * The view manager flush will update the layer tree, repaint any
2245 * invalid areas in the layer tree and schedule a layer tree
2246 * composite operation to display the layer tree.
2247 *
2248 * In general it is not necessary for frames to call this when they change.
2249 * For example, changes that result in a reflow will have this called for
2250 * them by PresContext::DoReflow when the reflow begins. Style changes that
2251 * do not trigger a reflow should have this called for them by
2252 * DoApplyRenderingChangeToTree.
2253 *
2254 * @param aType PAINT_COMPOSITE_ONLY : No changes have been made
2255 * that require a layer tree update, so only schedule a layer
2256 * tree composite.
2257 * PAINT_DELAYED_COMPRESS : Schedule a paint to be executed after a delay, and
2258 * put FrameLayerBuilder in 'compressed' mode that avoids short cut optimizations.
2259 */
2260 enum PaintType {
2261 PAINT_DEFAULT = 0,
2262 PAINT_COMPOSITE_ONLY,
2263 PAINT_DELAYED_COMPRESS
2264 };
2265 void SchedulePaint(PaintType aType = PAINT_DEFAULT);
2267 /**
2268 * Checks if the layer tree includes a dedicated layer for this
2269 * frame/display item key pair, and invalidates at least aDamageRect
2270 * area within that layer.
2271 *
2272 * If no layer is found, calls InvalidateFrame() instead.
2273 *
2274 * @param aDamageRect Area of the layer to invalidate.
2275 * @param aDisplayItemKey Display item type.
2276 * @param aFlags UPDATE_IS_ASYNC : Will skip the invalidation
2277 * if the found layer is being composited by a remote
2278 * compositor.
2279 * @return Layer, if found, nullptr otherwise.
2280 */
2281 enum {
2282 UPDATE_IS_ASYNC = 1 << 0
2283 };
2284 Layer* InvalidateLayer(uint32_t aDisplayItemKey, const nsIntRect* aDamageRect = nullptr, uint32_t aFlags = 0);
2286 /**
2287 * Returns a rect that encompasses everything that might be painted by
2288 * this frame. This includes this frame, all its descendent frames, this
2289 * frame's outline, and descentant frames' outline, but does not include
2290 * areas clipped out by the CSS "overflow" and "clip" properties.
2291 *
2292 * HasOverflowRects() (below) will return true when this overflow
2293 * rect has been explicitly set, even if it matches mRect.
2294 * XXX Note: because of a space optimization using the formula above,
2295 * during reflow this function does not give accurate data if
2296 * FinishAndStoreOverflow has been called but mRect hasn't yet been
2297 * updated yet. FIXME: This actually isn't true, but it should be.
2298 *
2299 * The visual overflow rect should NEVER be used for things that
2300 * affect layout. The scrollable overflow rect is permitted to affect
2301 * layout.
2302 *
2303 * @return the rect relative to this frame's origin, but after
2304 * CSS transforms have been applied (i.e. not really this frame's coordinate
2305 * system, and may not contain the frame's border-box, e.g. if there
2306 * is a CSS transform scaling it down)
2307 */
2308 nsRect GetVisualOverflowRect() const {
2309 return GetOverflowRect(eVisualOverflow);
2310 }
2312 /**
2313 * Returns a rect that encompasses the area of this frame that the
2314 * user should be able to scroll to reach. This is similar to
2315 * GetVisualOverflowRect, but does not include outline or shadows, and
2316 * may in the future include more margins than visual overflow does.
2317 * It does not include areas clipped out by the CSS "overflow" and
2318 * "clip" properties.
2319 *
2320 * HasOverflowRects() (below) will return true when this overflow
2321 * rect has been explicitly set, even if it matches mRect.
2322 * XXX Note: because of a space optimization using the formula above,
2323 * during reflow this function does not give accurate data if
2324 * FinishAndStoreOverflow has been called but mRect hasn't yet been
2325 * updated yet.
2326 *
2327 * @return the rect relative to this frame's origin, but after
2328 * CSS transforms have been applied (i.e. not really this frame's coordinate
2329 * system, and may not contain the frame's border-box, e.g. if there
2330 * is a CSS transform scaling it down)
2331 */
2332 nsRect GetScrollableOverflowRect() const {
2333 return GetOverflowRect(eScrollableOverflow);
2334 }
2336 nsRect GetOverflowRect(nsOverflowType aType) const;
2338 nsOverflowAreas GetOverflowAreas() const;
2340 /**
2341 * Same as GetOverflowAreas, except in this frame's coordinate
2342 * system (before transforms are applied).
2343 *
2344 * @return the overflow areas relative to this frame, before any CSS transforms have
2345 * been applied, i.e. in this frame's coordinate system
2346 */
2347 nsOverflowAreas GetOverflowAreasRelativeToSelf() const;
2349 /**
2350 * Same as GetScrollableOverflowRect, except relative to the parent
2351 * frame.
2352 *
2353 * @return the rect relative to the parent frame, in the parent frame's
2354 * coordinate system
2355 */
2356 nsRect GetScrollableOverflowRectRelativeToParent() const;
2358 /**
2359 * Same as GetScrollableOverflowRect, except in this frame's coordinate
2360 * system (before transforms are applied).
2361 *
2362 * @return the rect relative to this frame, before any CSS transforms have
2363 * been applied, i.e. in this frame's coordinate system
2364 */
2365 nsRect GetScrollableOverflowRectRelativeToSelf() const;
2367 /**
2368 * Like GetVisualOverflowRect, except in this frame's
2369 * coordinate system (before transforms are applied).
2370 *
2371 * @return the rect relative to this frame, before any CSS transforms have
2372 * been applied, i.e. in this frame's coordinate system
2373 */
2374 nsRect GetVisualOverflowRectRelativeToSelf() const;
2376 /**
2377 * Returns this frame's visual overflow rect as it would be before taking
2378 * account of SVG effects or transforms. The rect returned is relative to
2379 * this frame.
2380 */
2381 nsRect GetPreEffectsVisualOverflowRect() const;
2383 /**
2384 * Store the overflow area in the frame's mOverflow.mVisualDeltas
2385 * fields or as a frame property in the frame manager so that it can
2386 * be retrieved later without reflowing the frame. Returns true if either of
2387 * the overflow areas changed.
2388 */
2389 bool FinishAndStoreOverflow(nsOverflowAreas& aOverflowAreas,
2390 nsSize aNewSize, nsSize* aOldSize = nullptr);
2392 bool FinishAndStoreOverflow(nsHTMLReflowMetrics* aMetrics) {
2393 return FinishAndStoreOverflow(aMetrics->mOverflowAreas,
2394 nsSize(aMetrics->Width(), aMetrics->Height()));
2395 }
2397 /**
2398 * Returns whether the frame has an overflow rect that is different from
2399 * its border-box.
2400 */
2401 bool HasOverflowAreas() const {
2402 return mOverflow.mType != NS_FRAME_OVERFLOW_NONE;
2403 }
2405 /**
2406 * Removes any stored overflow rects (visual and scrollable) from the frame.
2407 * Returns true if the overflow changed.
2408 */
2409 bool ClearOverflowRects();
2411 /**
2412 * Determine whether borders should not be painted on certain sides of the
2413 * frame.
2414 *
2415 * @note (See also bug 743402, comment 11) GetSkipSides() and its sister
2416 * method, ApplySkipSides() checks to see if this frame has a previous
2417 * or next continuation to determine if a side should be skipped.
2418 * Unfortunately, this only works after reflow has been completed. In
2419 * lieu of this, during reflow, an nsHTMLReflowState parameter can be
2420 * passed in, indicating that it should be used to determine if sides
2421 * should be skipped during reflow.
2422 */
2423 #define LOGICAL_SIDE_B_START 1
2424 #define LOGICAL_SIDE_I_START 2
2425 #define LOGICAL_SIDE_B_END 4
2426 #define LOGICAL_SIDE_I_END 8
2427 #define LOGICAL_SIDES_I_BOTH (LOGICAL_SIDE_I_START | LOGICAL_SIDE_I_END)
2428 #define LOGICAL_SIDES_B_BOTH (LOGICAL_SIDE_B_START | LOGICAL_SIDE_B_END)
2429 #define LOGICAL_SIDES_ALL (LOGICAL_SIDE_I_START | LOGICAL_SIDE_I_END | \
2430 LOGICAL_SIDE_B_START | LOGICAL_SIDE_B_END)
2431 int GetSkipSides(const nsHTMLReflowState* aReflowState = nullptr) const;
2432 virtual int
2433 GetLogicalSkipSides(const nsHTMLReflowState* aReflowState = nullptr) const {
2434 return 0;
2435 }
2437 /**
2438 * @returns true if this frame is selected.
2439 */
2440 bool IsSelected() const;
2442 /**
2443 * called to discover where this frame, or a parent frame has user-select style
2444 * applied, which affects that way that it is selected.
2445 *
2446 * @param aIsSelectable out param. Set to true if the frame can be selected
2447 * (i.e. is not affected by user-select: none)
2448 * @param aSelectStyle out param. Returns the type of selection style found
2449 * (using values defined in nsStyleConsts.h).
2450 */
2451 virtual nsresult IsSelectable(bool* aIsSelectable, uint8_t* aSelectStyle) const = 0;
2453 /**
2454 * Called to retrieve the SelectionController associated with the frame.
2455 * @param aSelCon will contain the selection controller associated with
2456 * the frame.
2457 */
2458 virtual nsresult GetSelectionController(nsPresContext *aPresContext, nsISelectionController **aSelCon) = 0;
2460 /**
2461 * Call to get nsFrameSelection for this frame.
2462 */
2463 already_AddRefed<nsFrameSelection> GetFrameSelection();
2465 /**
2466 * GetConstFrameSelection returns an object which methods are safe to use for
2467 * example in nsIFrame code.
2468 */
2469 const nsFrameSelection* GetConstFrameSelection() const;
2471 /**
2472 * called to find the previous/next character, word, or line returns the actual
2473 * nsIFrame and the frame offset. THIS DOES NOT CHANGE SELECTION STATE
2474 * uses frame's begin selection state to start. if no selection on this frame will
2475 * return NS_ERROR_FAILURE
2476 * @param aPOS is defined in nsFrameSelection
2477 */
2478 virtual nsresult PeekOffset(nsPeekOffsetStruct *aPos);
2480 /**
2481 * called to find the previous/next selectable leaf frame.
2482 * @param aDirection [in] the direction to move in (eDirPrevious or eDirNext)
2483 * @param aVisual [in] whether bidi caret behavior is visual (true) or logical (false)
2484 * @param aJumpLines [in] whether to allow jumping across line boundaries
2485 * @param aScrollViewStop [in] whether to stop when reaching a scroll frame boundary
2486 * @param aOutFrame [out] the previous/next selectable leaf frame
2487 * @param aOutOffset [out] 0 indicates that we arrived at the beginning of the output frame;
2488 * -1 indicates that we arrived at its end.
2489 * @param aOutJumpedLine [out] whether this frame and the returned frame are on different lines
2490 */
2491 nsresult GetFrameFromDirection(nsDirection aDirection, bool aVisual,
2492 bool aJumpLines, bool aScrollViewStop,
2493 nsIFrame** aOutFrame, int32_t* aOutOffset, bool* aOutJumpedLine);
2495 /**
2496 * called to see if the children of the frame are visible from indexstart to index end.
2497 * this does not change any state. returns true only if the indexes are valid and any of
2498 * the children are visible. for textframes this index is the character index.
2499 * if aStart = aEnd result will be false
2500 * @param aStart start index of first child from 0-N (number of children)
2501 * @param aEnd end index of last child from 0-N
2502 * @param aRecurse should this frame talk to siblings to get to the contents other children?
2503 * @param aFinished did this frame have the aEndIndex? or is there more work to do
2504 * @param _retval return value true or false. false = range is not rendered.
2505 */
2506 virtual nsresult CheckVisibility(nsPresContext* aContext, int32_t aStartIndex, int32_t aEndIndex, bool aRecurse, bool *aFinished, bool *_retval)=0;
2508 /**
2509 * Called to tell a frame that one of its child frames is dirty (i.e.,
2510 * has the NS_FRAME_IS_DIRTY *or* NS_FRAME_HAS_DIRTY_CHILDREN bit
2511 * set). This should always set the NS_FRAME_HAS_DIRTY_CHILDREN on
2512 * the frame, and may do other work.
2513 */
2514 virtual void ChildIsDirty(nsIFrame* aChild) = 0;
2516 /**
2517 * Called to retrieve this frame's accessible.
2518 * If this frame implements Accessibility return a valid accessible
2519 * If not return NS_ERROR_NOT_IMPLEMENTED.
2520 * Note: Accessible must be refcountable. Do not implement directly on your frame
2521 * Use a mediatior of some kind.
2522 */
2523 #ifdef ACCESSIBILITY
2524 virtual mozilla::a11y::AccType AccessibleType() = 0;
2525 #endif
2527 /**
2528 * Get the frame whose style context should be the parent of this
2529 * frame's style context (i.e., provide the parent style context).
2530 * This frame must either be an ancestor of this frame or a child. If
2531 * this returns a child frame, then the child frame must be sure to
2532 * return a grandparent or higher! Furthermore, if a child frame is
2533 * returned it must have the same GetContent() as this frame.
2534 *
2535 * @return The frame whose style context should be the parent of this frame's
2536 * style context. Null is permitted, and means that this frame's
2537 * style context should be the root of the style context tree.
2538 */
2539 virtual nsIFrame* GetParentStyleContextFrame() const = 0;
2541 /**
2542 * Determines whether a frame is visible for painting;
2543 * taking into account whether it is painting a selection or printing.
2544 */
2545 bool IsVisibleForPainting(nsDisplayListBuilder* aBuilder);
2546 /**
2547 * Determines whether a frame is visible for painting or collapsed;
2548 * taking into account whether it is painting a selection or printing,
2549 */
2550 bool IsVisibleOrCollapsedForPainting(nsDisplayListBuilder* aBuilder);
2551 /**
2552 * As above, but slower because we have to recompute some stuff that
2553 * aBuilder already has.
2554 */
2555 bool IsVisibleForPainting();
2556 /**
2557 * Check whether this frame is visible in the current selection. Returns
2558 * true if there is no current selection.
2559 */
2560 bool IsVisibleInSelection(nsDisplayListBuilder* aBuilder);
2562 /**
2563 * Overridable function to determine whether this frame should be considered
2564 * "in" the given non-null aSelection for visibility purposes.
2565 */
2566 virtual bool IsVisibleInSelection(nsISelection* aSelection);
2568 /**
2569 * Determines whether this frame is a pseudo stacking context, looking
2570 * only as style --- i.e., assuming that it's in-flow and not a replaced
2571 * element and not an SVG element.
2572 * XXX maybe check IsTransformed()?
2573 */
2574 bool IsPseudoStackingContextFromStyle();
2576 virtual bool HonorPrintBackgroundSettings() { return true; }
2578 /**
2579 * Determine whether the frame is logically empty, which is roughly
2580 * whether the layout would be the same whether or not the frame is
2581 * present. Placeholder frames should return true. Block frames
2582 * should be considered empty whenever margins collapse through them,
2583 * even though those margins are relevant. Text frames containing
2584 * only whitespace that does not contribute to the height of the line
2585 * should return true.
2586 */
2587 virtual bool IsEmpty() = 0;
2588 /**
2589 * Return the same as IsEmpty(). This may only be called after the frame
2590 * has been reflowed and before any further style or content changes.
2591 */
2592 virtual bool CachedIsEmpty();
2593 /**
2594 * Determine whether the frame is logically empty, assuming that all
2595 * its children are empty.
2596 */
2597 virtual bool IsSelfEmpty() = 0;
2599 /**
2600 * IsGeneratedContentFrame returns whether a frame corresponds to
2601 * generated content
2602 *
2603 * @return whether the frame correspods to generated content
2604 */
2605 bool IsGeneratedContentFrame() {
2606 return (mState & NS_FRAME_GENERATED_CONTENT) != 0;
2607 }
2609 /**
2610 * IsPseudoFrame returns whether a frame is a pseudo frame (eg an
2611 * anonymous table-row frame created for a CSS table-cell without an
2612 * enclosing table-row.
2613 *
2614 * @param aParentContent the content node corresponding to the parent frame
2615 * @return whether the frame is a pseudo frame
2616 */
2617 bool IsPseudoFrame(nsIContent* aParentContent) {
2618 return mContent == aParentContent;
2619 }
2621 FrameProperties Properties() const {
2622 return FrameProperties(PresContext()->PropertyTable(), this);
2623 }
2625 NS_DECLARE_FRAME_PROPERTY(BaseLevelProperty, nullptr)
2626 NS_DECLARE_FRAME_PROPERTY(EmbeddingLevelProperty, nullptr)
2627 NS_DECLARE_FRAME_PROPERTY(ParagraphDepthProperty, nullptr)
2629 #define NS_GET_BASE_LEVEL(frame) \
2630 NS_PTR_TO_INT32(frame->Properties().Get(nsIFrame::BaseLevelProperty()))
2632 #define NS_GET_EMBEDDING_LEVEL(frame) \
2633 NS_PTR_TO_INT32(frame->Properties().Get(nsIFrame::EmbeddingLevelProperty()))
2635 #define NS_GET_PARAGRAPH_DEPTH(frame) \
2636 NS_PTR_TO_INT32(frame->Properties().Get(nsIFrame::ParagraphDepthProperty()))
2638 /**
2639 * Return true if and only if this frame obeys visibility:hidden.
2640 * if it does not, then nsContainerFrame will hide its view even though
2641 * this means children can't be made visible again.
2642 */
2643 virtual bool SupportsVisibilityHidden() { return true; }
2645 /**
2646 * Returns true if the frame has a valid clip rect set via the 'clip'
2647 * property, and the 'clip' property applies to this frame. The 'clip'
2648 * property applies to HTML frames if they are absolutely positioned. The
2649 * 'clip' property applies to SVG frames regardless of the value of the
2650 * 'position' property.
2651 *
2652 * If this method returns true, then we also set aRect to the computed clip
2653 * rect, with coordinates relative to this frame's origin. aRect must not be
2654 * null!
2655 */
2656 bool GetClipPropClipRect(const nsStyleDisplay* aDisp, nsRect* aRect,
2657 const nsSize& aSize) const;
2659 /**
2660 * Check if this frame is focusable and in the current tab order.
2661 * Tabbable is indicated by a nonnegative tabindex & is a subset of focusable.
2662 * For example, only the selected radio button in a group is in the
2663 * tab order, unless the radio group has no selection in which case
2664 * all of the visible, non-disabled radio buttons in the group are
2665 * in the tab order. On the other hand, all of the visible, non-disabled
2666 * radio buttons are always focusable via clicking or script.
2667 * Also, depending on the pref accessibility.tabfocus some widgets may be
2668 * focusable but removed from the tab order. This is the default on
2669 * Mac OS X, where fewer items are focusable.
2670 * @param [in, optional] aTabIndex the computed tab index
2671 * < 0 if not tabbable
2672 * == 0 if in normal tab order
2673 * > 0 can be tabbed to in the order specified by this value
2674 * @param [in, optional] aWithMouse, is this focus query for mouse clicking
2675 * @return whether the frame is focusable via mouse, kbd or script.
2676 */
2677 virtual bool IsFocusable(int32_t *aTabIndex = nullptr, bool aWithMouse = false);
2679 // BOX LAYOUT METHODS
2680 // These methods have been migrated from nsIBox and are in the process of
2681 // being refactored. DO NOT USE OUTSIDE OF XUL.
2682 bool IsBoxFrame() const
2683 {
2684 return IsFrameOfType(nsIFrame::eXULBox);
2685 }
2686 bool IsBoxWrapped() const
2687 { return (!IsBoxFrame() && mParent && mParent->IsBoxFrame()); }
2689 enum Halignment {
2690 hAlign_Left,
2691 hAlign_Right,
2692 hAlign_Center
2693 };
2695 enum Valignment {
2696 vAlign_Top,
2697 vAlign_Middle,
2698 vAlign_BaseLine,
2699 vAlign_Bottom
2700 };
2702 /**
2703 * This calculates the minimum size required for a box based on its state
2704 * @param[in] aBoxLayoutState The desired state to calculate for
2705 * @return The minimum size
2706 */
2707 virtual nsSize GetMinSize(nsBoxLayoutState& aBoxLayoutState) = 0;
2709 /**
2710 * This calculates the preferred size of a box based on its state
2711 * @param[in] aBoxLayoutState The desired state to calculate for
2712 * @return The preferred size
2713 */
2714 virtual nsSize GetPrefSize(nsBoxLayoutState& aBoxLayoutState) = 0;
2716 /**
2717 * This calculates the maximum size for a box based on its state
2718 * @param[in] aBoxLayoutState The desired state to calculate for
2719 * @return The maximum size
2720 */
2721 virtual nsSize GetMaxSize(nsBoxLayoutState& aBoxLayoutState) = 0;
2723 /**
2724 * This returns the minimum size for the scroll area if this frame is
2725 * being scrolled. Usually it's (0,0).
2726 */
2727 virtual nsSize GetMinSizeForScrollArea(nsBoxLayoutState& aBoxLayoutState) = 0;
2729 // Implemented in nsBox, used in nsBoxFrame
2730 uint32_t GetOrdinal();
2732 virtual nscoord GetFlex(nsBoxLayoutState& aBoxLayoutState) = 0;
2733 virtual nscoord GetBoxAscent(nsBoxLayoutState& aBoxLayoutState) = 0;
2734 virtual bool IsCollapsed() = 0;
2735 // This does not alter the overflow area. If the caller is changing
2736 // the box size, the caller is responsible for updating the overflow
2737 // area. It's enough to just call Layout or SyncLayout on the
2738 // box. You can pass true to aRemoveOverflowArea as a
2739 // convenience.
2740 virtual void SetBounds(nsBoxLayoutState& aBoxLayoutState, const nsRect& aRect,
2741 bool aRemoveOverflowAreas = false) = 0;
2742 NS_HIDDEN_(nsresult) Layout(nsBoxLayoutState& aBoxLayoutState);
2743 nsIFrame* GetChildBox() const
2744 {
2745 // box layout ends at box-wrapped frames, so don't allow these frames
2746 // to report child boxes.
2747 return IsBoxFrame() ? GetFirstPrincipalChild() : nullptr;
2748 }
2749 nsIFrame* GetNextBox() const
2750 {
2751 return (mParent && mParent->IsBoxFrame()) ? mNextSibling : nullptr;
2752 }
2753 nsIFrame* GetParentBox() const
2754 {
2755 return (mParent && mParent->IsBoxFrame()) ? mParent : nullptr;
2756 }
2757 // Box methods. Note that these do NOT just get the CSS border, padding,
2758 // etc. They also talk to nsITheme.
2759 virtual nsresult GetBorderAndPadding(nsMargin& aBorderAndPadding);
2760 virtual nsresult GetBorder(nsMargin& aBorder)=0;
2761 virtual nsresult GetPadding(nsMargin& aBorderAndPadding)=0;
2762 virtual nsresult GetMargin(nsMargin& aMargin)=0;
2763 virtual void SetLayoutManager(nsBoxLayout* aLayout) { }
2764 virtual nsBoxLayout* GetLayoutManager() { return nullptr; }
2765 NS_HIDDEN_(nsresult) GetClientRect(nsRect& aContentRect);
2767 // For nsSprocketLayout
2768 virtual Valignment GetVAlign() const = 0;
2769 virtual Halignment GetHAlign() const = 0;
2771 bool IsHorizontal() const { return (mState & NS_STATE_IS_HORIZONTAL) != 0; }
2772 bool IsNormalDirection() const { return (mState & NS_STATE_IS_DIRECTION_NORMAL) != 0; }
2774 NS_HIDDEN_(nsresult) Redraw(nsBoxLayoutState& aState);
2775 virtual nsresult RelayoutChildAtOrdinal(nsBoxLayoutState& aState, nsIFrame* aChild)=0;
2776 // XXX take this out after we've branched
2777 virtual bool GetMouseThrough() const { return false; }
2779 #ifdef DEBUG_LAYOUT
2780 virtual nsresult SetDebug(nsBoxLayoutState& aState, bool aDebug)=0;
2781 virtual nsresult GetDebug(bool& aDebug)=0;
2783 virtual nsresult DumpBox(FILE* out)=0;
2784 #endif
2786 /**
2787 * @return true if this text frame ends with a newline character. It
2788 * should return false if this is not a text frame.
2789 */
2790 virtual bool HasSignificantTerminalNewline() const;
2792 static bool AddCSSPrefSize(nsIFrame* aBox, nsSize& aSize, bool& aWidth, bool& aHeightSet);
2793 static bool AddCSSMinSize(nsBoxLayoutState& aState, nsIFrame* aBox,
2794 nsSize& aSize, bool& aWidth, bool& aHeightSet);
2795 static bool AddCSSMaxSize(nsIFrame* aBox, nsSize& aSize, bool& aWidth, bool& aHeightSet);
2796 static bool AddCSSFlex(nsBoxLayoutState& aState, nsIFrame* aBox, nscoord& aFlex);
2798 // END OF BOX LAYOUT METHODS
2799 // The above methods have been migrated from nsIBox and are in the process of
2800 // being refactored. DO NOT USE OUTSIDE OF XUL.
2802 struct CaretPosition {
2803 CaretPosition();
2804 ~CaretPosition();
2806 nsCOMPtr<nsIContent> mResultContent;
2807 int32_t mContentOffset;
2808 };
2810 /**
2811 * gets the first or last possible caret position within the frame
2812 *
2813 * @param [in] aStart
2814 * true for getting the first possible caret position
2815 * false for getting the last possible caret position
2816 * @return The caret position in a CaretPosition.
2817 * the returned value is a 'best effort' in case errors
2818 * are encountered rummaging through the frame.
2819 */
2820 CaretPosition GetExtremeCaretPosition(bool aStart);
2822 /**
2823 * Get a line iterator for this frame, if supported.
2824 *
2825 * @return nullptr if no line iterator is supported.
2826 * @note dispose the line iterator using nsILineIterator::DisposeLineIterator
2827 */
2828 virtual nsILineIterator* GetLineIterator() = 0;
2830 /**
2831 * If this frame is a next-in-flow, and its prev-in-flow has something on its
2832 * overflow list, pull those frames into the child list of this one.
2833 */
2834 virtual void PullOverflowsFromPrevInFlow() {}
2836 /**
2837 * Clear the list of child PresShells generated during the last paint
2838 * so that we can begin generating a new one.
2839 */
2840 void ClearPresShellsFromLastPaint() {
2841 PaintedPresShellList()->Clear();
2842 }
2844 /**
2845 * Flag a child PresShell as painted so that it will get its paint count
2846 * incremented during empty transactions.
2847 */
2848 void AddPaintedPresShell(nsIPresShell* shell) {
2849 nsWeakPtr weakShell = do_GetWeakReference(shell);
2850 PaintedPresShellList()->AppendElement(weakShell);
2851 }
2853 /**
2854 * Increment the paint count of all child PresShells that were painted during
2855 * the last repaint.
2856 */
2857 void UpdatePaintCountForPaintedPresShells() {
2858 nsTArray<nsWeakPtr> * list = PaintedPresShellList();
2859 for (int i = 0, l = list->Length(); i < l; i++) {
2860 nsCOMPtr<nsIPresShell> shell = do_QueryReferent(list->ElementAt(i));
2862 if (shell) {
2863 shell->IncrementPaintCount();
2864 }
2865 }
2866 }
2868 /**
2869 * Accessors for the absolute containing block.
2870 */
2871 bool IsAbsoluteContainer() const { return !!(mState & NS_FRAME_HAS_ABSPOS_CHILDREN); }
2872 bool HasAbsolutelyPositionedChildren() const;
2873 nsAbsoluteContainingBlock* GetAbsoluteContainingBlock() const;
2874 void MarkAsAbsoluteContainingBlock();
2875 void MarkAsNotAbsoluteContainingBlock();
2876 // Child frame types override this function to select their own child list name
2877 virtual mozilla::layout::FrameChildListID GetAbsoluteListID() const { return kAbsoluteList; }
2879 // Checks if we (or any of our descendents) have NS_FRAME_PAINTED_THEBES set, and
2880 // clears this bit if so.
2881 bool CheckAndClearPaintedState();
2883 // CSS visibility just doesn't cut it because it doesn't inherit through
2884 // documents. Also if this frame is in a hidden card of a deck then it isn't
2885 // visible either and that isn't expressed using CSS visibility. Also if it
2886 // is in a hidden view (there are a few cases left and they are hopefully
2887 // going away soon).
2888 // If the VISIBILITY_CROSS_CHROME_CONTENT_BOUNDARY flag is passed then we
2889 // ignore the chrome/content boundary, otherwise we stop looking when we
2890 // reach it.
2891 enum {
2892 VISIBILITY_CROSS_CHROME_CONTENT_BOUNDARY = 0x01
2893 };
2894 bool IsVisibleConsideringAncestors(uint32_t aFlags = 0) const;
2896 struct FrameWithDistance
2897 {
2898 nsIFrame* mFrame;
2899 nscoord mXDistance;
2900 nscoord mYDistance;
2901 };
2903 /**
2904 * Finds a frame that is closer to a specified point than a current
2905 * distance. Distance is measured as for text selection -- a closer x
2906 * distance beats a closer y distance.
2907 *
2908 * Normally, this function will only check the distance between this
2909 * frame's rectangle and the specified point. SVGTextFrame overrides
2910 * this so that it can manage all of its descendant frames and take
2911 * into account any SVG text layout.
2912 *
2913 * If aPoint is closer to this frame's rectangle than aCurrentBestFrame
2914 * indicates, then aCurrentBestFrame is updated with the distance between
2915 * aPoint and this frame's rectangle, and with a pointer to this frame.
2916 * If aPoint is not closer, then aCurrentBestFrame is left unchanged.
2917 *
2918 * @param aPoint The point to check for its distance to this frame.
2919 * @param aCurrentBestFrame Pointer to a struct that will be updated with
2920 * a pointer to this frame and its distance to aPoint, if this frame
2921 * is indeed closer than the current distance in aCurrentBestFrame.
2922 */
2923 virtual void FindCloserFrameForSelection(nsPoint aPoint,
2924 FrameWithDistance* aCurrentBestFrame);
2926 /**
2927 * Is this a flex item? (i.e. a non-abs-pos child of a flex container)
2928 */
2929 inline bool IsFlexItem() const;
2931 inline bool IsBlockInside() const;
2932 inline bool IsBlockOutside() const;
2933 inline bool IsInlineOutside() const;
2934 inline uint8_t GetDisplay() const;
2935 inline bool IsFloating() const;
2936 inline bool IsPositioned() const;
2937 inline bool IsRelativelyPositioned() const;
2938 inline bool IsAbsolutelyPositioned() const;
2940 /**
2941 * Returns the vertical-align value to be used for layout, if it is one
2942 * of the enumerated values. If this is an SVG text frame, it returns a value
2943 * that corresponds to the value of dominant-baseline. If the
2944 * vertical-align property has length or percentage value, this returns
2945 * eInvalidVerticalAlign.
2946 */
2947 uint8_t VerticalAlignEnum() const;
2948 enum { eInvalidVerticalAlign = 0xFF };
2950 bool IsSVGText() const { return mState & NS_FRAME_IS_SVG_TEXT; }
2952 void CreateOwnLayerIfNeeded(nsDisplayListBuilder* aBuilder, nsDisplayList* aList);
2954 /**
2955 * Adds the NS_FRAME_IN_POPUP state bit to aFrame, and
2956 * all descendant frames (including cross-doc ones).
2957 */
2958 static void AddInPopupStateBitToDescendants(nsIFrame* aFrame);
2959 /**
2960 * Removes the NS_FRAME_IN_POPUP state bit from aFrame and
2961 * all descendant frames (including cross-doc ones), unless
2962 * the frame is a popup itself.
2963 */
2964 static void RemoveInPopupStateBitFromDescendants(nsIFrame* aFrame);
2966 /**
2967 * Sorts the given nsFrameList, so that for every two adjacent frames in the
2968 * list, the former is less than or equal to the latter, according to the
2969 * templated IsLessThanOrEqual method.
2970 *
2971 * Note: this method uses a stable merge-sort algorithm.
2972 */
2973 template<bool IsLessThanOrEqual(nsIFrame*, nsIFrame*)>
2974 static void SortFrameList(nsFrameList& aFrameList);
2976 /**
2977 * Returns true if the given frame list is already sorted, according to the
2978 * templated IsLessThanOrEqual function.
2979 */
2980 template<bool IsLessThanOrEqual(nsIFrame*, nsIFrame*)>
2981 static bool IsFrameListSorted(nsFrameList& aFrameList);
2983 /**
2984 * Return true if aFrame is in an {ib} split and is NOT one of the
2985 * continuations of the first inline in it.
2986 */
2987 bool FrameIsNonFirstInIBSplit() const {
2988 return (GetStateBits() & NS_FRAME_PART_OF_IBSPLIT) &&
2989 FirstContinuation()->Properties().Get(nsIFrame::IBSplitPrevSibling());
2990 }
2992 /**
2993 * Return true if aFrame is in an {ib} split and is NOT one of the
2994 * continuations of the last inline in it.
2995 */
2996 bool FrameIsNonLastInIBSplit() const {
2997 return (GetStateBits() & NS_FRAME_PART_OF_IBSPLIT) &&
2998 FirstContinuation()->Properties().Get(nsIFrame::IBSplitSibling());
2999 }
3001 /**
3002 * Return whether this is a frame whose width is used when computing
3003 * the font size inflation of its descendants.
3004 */
3005 bool IsContainerForFontSizeInflation() const {
3006 return GetStateBits() & NS_FRAME_FONT_INFLATION_CONTAINER;
3007 }
3009 /**
3010 * Returns the content node within the anonymous content that this frame
3011 * generated and which corresponds to the specified pseudo-element type,
3012 * or nullptr if there is no such anonymous content.
3013 */
3014 virtual mozilla::dom::Element* GetPseudoElement(nsCSSPseudoElements::Type aType);
3016 protected:
3017 // Members
3018 nsRect mRect;
3019 nsIContent* mContent;
3020 nsStyleContext* mStyleContext;
3021 nsIFrame* mParent;
3022 private:
3023 nsIFrame* mNextSibling; // doubly-linked list of frames
3024 nsIFrame* mPrevSibling; // Do not touch outside SetNextSibling!
3026 void MarkAbsoluteFramesForDisplayList(nsDisplayListBuilder* aBuilder, const nsRect& aDirtyRect);
3028 static void DestroyPaintedPresShellList(void* propertyValue) {
3029 nsTArray<nsWeakPtr>* list = static_cast<nsTArray<nsWeakPtr>*>(propertyValue);
3030 list->Clear();
3031 delete list;
3032 }
3034 // Stores weak references to all the PresShells that were painted during
3035 // the last paint event so that we can increment their paint count during
3036 // empty transactions
3037 NS_DECLARE_FRAME_PROPERTY(PaintedPresShellsProperty, DestroyPaintedPresShellList)
3039 nsTArray<nsWeakPtr>* PaintedPresShellList() {
3040 nsTArray<nsWeakPtr>* list = static_cast<nsTArray<nsWeakPtr>*>(
3041 Properties().Get(PaintedPresShellsProperty())
3042 );
3044 if (!list) {
3045 list = new nsTArray<nsWeakPtr>();
3046 Properties().Set(PaintedPresShellsProperty(), list);
3047 }
3049 return list;
3050 }
3052 protected:
3053 nsFrameState mState;
3055 // When there is an overflow area only slightly larger than mRect,
3056 // we store a set of four 1-byte deltas from the edges of mRect
3057 // rather than allocating a whole separate rectangle property.
3058 // Note that these are unsigned values, all measured "outwards"
3059 // from the edges of mRect, so /mLeft/ and /mTop/ are reversed from
3060 // our normal coordinate system.
3061 // If mOverflow.mType == NS_FRAME_OVERFLOW_LARGE, then the
3062 // delta values are not meaningful and the overflow area is stored
3063 // as a separate rect property.
3064 struct VisualDeltas {
3065 uint8_t mLeft;
3066 uint8_t mTop;
3067 uint8_t mRight;
3068 uint8_t mBottom;
3069 bool operator==(const VisualDeltas& aOther) const
3070 {
3071 return mLeft == aOther.mLeft && mTop == aOther.mTop &&
3072 mRight == aOther.mRight && mBottom == aOther.mBottom;
3073 }
3074 bool operator!=(const VisualDeltas& aOther) const
3075 {
3076 return !(*this == aOther);
3077 }
3078 };
3079 union {
3080 uint32_t mType;
3081 VisualDeltas mVisualDeltas;
3082 } mOverflow;
3084 // Helpers
3085 /**
3086 * Can we stop inside this frame when we're skipping non-rendered whitespace?
3087 * @param aForward [in] Are we moving forward (or backward) in content order.
3088 * @param aOffset [in/out] At what offset into the frame to start looking.
3089 * on output - what offset was reached (whether or not we found a place to stop).
3090 * @return STOP: An appropriate offset was found within this frame,
3091 * and is given by aOffset.
3092 * CONTINUE: Not found within this frame, need to try the next frame.
3093 * see enum FrameSearchResult for more details.
3094 */
3095 virtual FrameSearchResult PeekOffsetNoAmount(bool aForward, int32_t* aOffset) = 0;
3097 /**
3098 * Search the frame for the next character
3099 * @param aForward [in] Are we moving forward (or backward) in content order.
3100 * @param aOffset [in/out] At what offset into the frame to start looking.
3101 * on output - what offset was reached (whether or not we found a place to stop).
3102 * @param aRespectClusters [in] Whether to restrict result to valid cursor locations
3103 * (between grapheme clusters) - default TRUE maintains "normal" behavior,
3104 * FALSE is used for selection by "code unit" (instead of "character")
3105 * @return STOP: An appropriate offset was found within this frame,
3106 * and is given by aOffset.
3107 * CONTINUE: Not found within this frame, need to try the next frame.
3108 * see enum FrameSearchResult for more details.
3109 */
3110 virtual FrameSearchResult PeekOffsetCharacter(bool aForward, int32_t* aOffset,
3111 bool aRespectClusters = true) = 0;
3113 /**
3114 * Search the frame for the next word boundary
3115 * @param aForward [in] Are we moving forward (or backward) in content order.
3116 * @param aWordSelectEatSpace [in] true: look for non-whitespace following
3117 * whitespace (in the direction of movement).
3118 * false: look for whitespace following non-whitespace (in the
3119 * direction of movement).
3120 * @param aIsKeyboardSelect [in] Was the action initiated by a keyboard operation?
3121 * If true, punctuation immediately following a word is considered part
3122 * of that word. Otherwise, a sequence of punctuation is always considered
3123 * as a word on its own.
3124 * @param aOffset [in/out] At what offset into the frame to start looking.
3125 * on output - what offset was reached (whether or not we found a place to stop).
3126 * @param aState [in/out] the state that is carried from frame to frame
3127 * @return true: An appropriate offset was found within this frame,
3128 * and is given by aOffset.
3129 * false: Not found within this frame, need to try the next frame.
3130 */
3131 struct PeekWordState {
3132 // true when we're still at the start of the search, i.e., we can't return
3133 // this point as a valid offset!
3134 bool mAtStart;
3135 // true when we've encountered at least one character of the pre-boundary type
3136 // (whitespace if aWordSelectEatSpace is true, non-whitespace otherwise)
3137 bool mSawBeforeType;
3138 // true when the last character encountered was punctuation
3139 bool mLastCharWasPunctuation;
3140 // true when the last character encountered was whitespace
3141 bool mLastCharWasWhitespace;
3142 // true when we've seen non-punctuation since the last whitespace
3143 bool mSeenNonPunctuationSinceWhitespace;
3144 // text that's *before* the current frame when aForward is true, *after*
3145 // the current frame when aForward is false. Only includes the text
3146 // on the current line.
3147 nsAutoString mContext;
3149 PeekWordState() : mAtStart(true), mSawBeforeType(false),
3150 mLastCharWasPunctuation(false), mLastCharWasWhitespace(false),
3151 mSeenNonPunctuationSinceWhitespace(false) {}
3152 void SetSawBeforeType() { mSawBeforeType = true; }
3153 void Update(bool aAfterPunctuation, bool aAfterWhitespace) {
3154 mLastCharWasPunctuation = aAfterPunctuation;
3155 mLastCharWasWhitespace = aAfterWhitespace;
3156 if (aAfterWhitespace) {
3157 mSeenNonPunctuationSinceWhitespace = false;
3158 } else if (!aAfterPunctuation) {
3159 mSeenNonPunctuationSinceWhitespace = true;
3160 }
3161 mAtStart = false;
3162 }
3163 };
3164 virtual FrameSearchResult PeekOffsetWord(bool aForward, bool aWordSelectEatSpace, bool aIsKeyboardSelect,
3165 int32_t* aOffset, PeekWordState* aState) = 0;
3167 /**
3168 * Search for the first paragraph boundary before or after the given position
3169 * @param aPos See description in nsFrameSelection.h. The following fields are
3170 * used by this method:
3171 * Input: mDirection
3172 * Output: mResultContent, mContentOffset
3173 */
3174 nsresult PeekOffsetParagraph(nsPeekOffsetStruct *aPos);
3176 private:
3177 nsOverflowAreas* GetOverflowAreasProperty();
3178 nsRect GetVisualOverflowFromDeltas() const {
3179 NS_ABORT_IF_FALSE(mOverflow.mType != NS_FRAME_OVERFLOW_LARGE,
3180 "should not be called when overflow is in a property");
3181 // Calculate the rect using deltas from the frame's border rect.
3182 // Note that the mOverflow.mDeltas fields are unsigned, but we will often
3183 // need to return negative values for the left and top, so take care
3184 // to cast away the unsigned-ness.
3185 return nsRect(-(int32_t)mOverflow.mVisualDeltas.mLeft,
3186 -(int32_t)mOverflow.mVisualDeltas.mTop,
3187 mRect.width + mOverflow.mVisualDeltas.mRight +
3188 mOverflow.mVisualDeltas.mLeft,
3189 mRect.height + mOverflow.mVisualDeltas.mBottom +
3190 mOverflow.mVisualDeltas.mTop);
3191 }
3192 /**
3193 * Returns true if any overflow changed.
3194 */
3195 bool SetOverflowAreas(const nsOverflowAreas& aOverflowAreas);
3196 nsPoint GetOffsetToCrossDoc(const nsIFrame* aOther, const int32_t aAPD) const;
3198 // Helper-functions for SortFrameList():
3199 template<bool IsLessThanOrEqual(nsIFrame*, nsIFrame*)>
3200 static nsIFrame* SortedMerge(nsIFrame *aLeft, nsIFrame *aRight);
3202 template<bool IsLessThanOrEqual(nsIFrame*, nsIFrame*)>
3203 static nsIFrame* MergeSort(nsIFrame *aSource);
3205 bool HasOpacityInternal(float aThreshold) const;
3207 #ifdef DEBUG_FRAME_DUMP
3208 public:
3209 static void IndentBy(FILE* out, int32_t aIndent) {
3210 while (--aIndent >= 0) fputs(" ", out);
3211 }
3212 void ListTag(FILE* out) const {
3213 ListTag(out, this);
3214 }
3215 static void ListTag(FILE* out, const nsIFrame* aFrame) {
3216 nsAutoCString t;
3217 ListTag(t, aFrame);
3218 fputs(t.get(), out);
3219 }
3220 void ListTag(nsACString& aTo) const;
3221 static void ListTag(nsACString& aTo, const nsIFrame* aFrame);
3222 void ListGeneric(nsACString& aTo, const char* aPrefix = "", uint32_t aFlags = 0) const;
3223 enum {
3224 TRAVERSE_SUBDOCUMENT_FRAMES = 0x01
3225 };
3226 virtual void List(FILE* out = stderr, const char* aPrefix = "", uint32_t aFlags = 0) const;
3227 /**
3228 * lists the frames beginning from the root frame
3229 * - calls root frame's List(...)
3230 */
3231 static void RootFrameList(nsPresContext* aPresContext,
3232 FILE* out = stderr, const char* aPrefix = "");
3233 virtual void DumpFrameTree();
3234 void DumpFrameTreeLimited();
3236 virtual nsresult GetFrameName(nsAString& aResult) const = 0;
3237 #endif
3239 #ifdef DEBUG
3240 public:
3241 virtual nsFrameState GetDebugStateBits() const = 0;
3242 virtual nsresult DumpRegressionData(nsPresContext* aPresContext,
3243 FILE* out, int32_t aIndent) = 0;
3244 #endif
3245 };
3247 //----------------------------------------------------------------------
3249 /**
3250 * nsWeakFrame can be used to keep a reference to a nsIFrame in a safe way.
3251 * Whenever an nsIFrame object is deleted, the nsWeakFrames pointing
3252 * to it will be cleared.
3253 *
3254 * Create nsWeakFrame object when it is sure that nsIFrame object
3255 * is alive and after some operations which may destroy the nsIFrame
3256 * (for example any DOM modifications) use IsAlive() or GetFrame() methods to
3257 * check whether it is safe to continue to use the nsIFrame object.
3258 *
3259 * @note The usage of this class should be kept to a minimum.
3260 */
3262 class nsWeakFrame {
3263 public:
3264 nsWeakFrame() : mPrev(nullptr), mFrame(nullptr) { }
3266 nsWeakFrame(const nsWeakFrame& aOther) : mPrev(nullptr), mFrame(nullptr)
3267 {
3268 Init(aOther.GetFrame());
3269 }
3271 nsWeakFrame(nsIFrame* aFrame) : mPrev(nullptr), mFrame(nullptr)
3272 {
3273 Init(aFrame);
3274 }
3276 nsWeakFrame& operator=(nsWeakFrame& aOther) {
3277 Init(aOther.GetFrame());
3278 return *this;
3279 }
3281 nsWeakFrame& operator=(nsIFrame* aFrame) {
3282 Init(aFrame);
3283 return *this;
3284 }
3286 nsIFrame* operator->()
3287 {
3288 return mFrame;
3289 }
3291 operator nsIFrame*()
3292 {
3293 return mFrame;
3294 }
3296 void Clear(nsIPresShell* aShell) {
3297 if (aShell) {
3298 aShell->RemoveWeakFrame(this);
3299 }
3300 mFrame = nullptr;
3301 mPrev = nullptr;
3302 }
3304 bool IsAlive() { return !!mFrame; }
3306 nsIFrame* GetFrame() const { return mFrame; }
3308 nsWeakFrame* GetPreviousWeakFrame() { return mPrev; }
3310 void SetPreviousWeakFrame(nsWeakFrame* aPrev) { mPrev = aPrev; }
3312 ~nsWeakFrame()
3313 {
3314 Clear(mFrame ? mFrame->PresContext()->GetPresShell() : nullptr);
3315 }
3316 private:
3317 void Init(nsIFrame* aFrame);
3319 nsWeakFrame* mPrev;
3320 nsIFrame* mFrame;
3321 };
3323 inline bool
3324 nsFrameList::ContinueRemoveFrame(nsIFrame* aFrame)
3325 {
3326 MOZ_ASSERT(!aFrame->GetPrevSibling() || !aFrame->GetNextSibling(),
3327 "Forgot to call StartRemoveFrame?");
3328 if (aFrame == mLastChild) {
3329 MOZ_ASSERT(!aFrame->GetNextSibling(), "broken frame list");
3330 nsIFrame* prevSibling = aFrame->GetPrevSibling();
3331 if (!prevSibling) {
3332 MOZ_ASSERT(aFrame == mFirstChild, "broken frame list");
3333 mFirstChild = mLastChild = nullptr;
3334 return true;
3335 }
3336 MOZ_ASSERT(prevSibling->GetNextSibling() == aFrame, "Broken frame linkage");
3337 prevSibling->SetNextSibling(nullptr);
3338 mLastChild = prevSibling;
3339 return true;
3340 }
3341 if (aFrame == mFirstChild) {
3342 MOZ_ASSERT(!aFrame->GetPrevSibling(), "broken frame list");
3343 mFirstChild = aFrame->GetNextSibling();
3344 aFrame->SetNextSibling(nullptr);
3345 MOZ_ASSERT(mFirstChild, "broken frame list");
3346 return true;
3347 }
3348 return false;
3349 }
3351 inline bool
3352 nsFrameList::StartRemoveFrame(nsIFrame* aFrame)
3353 {
3354 if (aFrame->GetPrevSibling() && aFrame->GetNextSibling()) {
3355 UnhookFrameFromSiblings(aFrame);
3356 return true;
3357 }
3358 return ContinueRemoveFrame(aFrame);
3359 }
3361 inline void
3362 nsFrameList::Enumerator::Next()
3363 {
3364 NS_ASSERTION(!AtEnd(), "Should have checked AtEnd()!");
3365 mFrame = mFrame->GetNextSibling();
3366 }
3368 inline
3369 nsFrameList::FrameLinkEnumerator::
3370 FrameLinkEnumerator(const nsFrameList& aList, nsIFrame* aPrevFrame)
3371 : Enumerator(aList)
3372 {
3373 mPrev = aPrevFrame;
3374 mFrame = aPrevFrame ? aPrevFrame->GetNextSibling() : aList.FirstChild();
3375 }
3377 inline void
3378 nsFrameList::FrameLinkEnumerator::Next()
3379 {
3380 mPrev = mFrame;
3381 Enumerator::Next();
3382 }
3384 // Helper-functions for nsIFrame::SortFrameList()
3385 // ---------------------------------------------------
3387 template<bool IsLessThanOrEqual(nsIFrame*, nsIFrame*)>
3388 /* static */ nsIFrame*
3389 nsIFrame::SortedMerge(nsIFrame *aLeft, nsIFrame *aRight)
3390 {
3391 NS_PRECONDITION(aLeft && aRight, "SortedMerge must have non-empty lists");
3393 nsIFrame *result;
3394 // Unroll first iteration to avoid null-check 'result' inside the loop.
3395 if (IsLessThanOrEqual(aLeft, aRight)) {
3396 result = aLeft;
3397 aLeft = aLeft->GetNextSibling();
3398 if (!aLeft) {
3399 result->SetNextSibling(aRight);
3400 return result;
3401 }
3402 }
3403 else {
3404 result = aRight;
3405 aRight = aRight->GetNextSibling();
3406 if (!aRight) {
3407 result->SetNextSibling(aLeft);
3408 return result;
3409 }
3410 }
3412 nsIFrame *last = result;
3413 for (;;) {
3414 if (IsLessThanOrEqual(aLeft, aRight)) {
3415 last->SetNextSibling(aLeft);
3416 last = aLeft;
3417 aLeft = aLeft->GetNextSibling();
3418 if (!aLeft) {
3419 last->SetNextSibling(aRight);
3420 return result;
3421 }
3422 }
3423 else {
3424 last->SetNextSibling(aRight);
3425 last = aRight;
3426 aRight = aRight->GetNextSibling();
3427 if (!aRight) {
3428 last->SetNextSibling(aLeft);
3429 return result;
3430 }
3431 }
3432 }
3433 }
3435 template<bool IsLessThanOrEqual(nsIFrame*, nsIFrame*)>
3436 /* static */ nsIFrame*
3437 nsIFrame::MergeSort(nsIFrame *aSource)
3438 {
3439 NS_PRECONDITION(aSource, "MergeSort null arg");
3441 nsIFrame *sorted[32] = { nullptr };
3442 nsIFrame **fill = &sorted[0];
3443 nsIFrame **left;
3444 nsIFrame *rest = aSource;
3446 do {
3447 nsIFrame *current = rest;
3448 rest = rest->GetNextSibling();
3449 current->SetNextSibling(nullptr);
3451 // Merge it with sorted[0] if present; then merge the result with sorted[1] etc.
3452 // sorted[0] is a list of length 1 (or nullptr).
3453 // sorted[1] is a list of length 2 (or nullptr).
3454 // sorted[2] is a list of length 4 (or nullptr). etc.
3455 for (left = &sorted[0]; left != fill && *left; ++left) {
3456 current = SortedMerge<IsLessThanOrEqual>(*left, current);
3457 *left = nullptr;
3458 }
3460 // Fill the empty slot that we couldn't merge with the last result.
3461 *left = current;
3463 if (left == fill)
3464 ++fill;
3465 } while (rest);
3467 // Collect and merge the results.
3468 nsIFrame *result = nullptr;
3469 for (left = &sorted[0]; left != fill; ++left) {
3470 if (*left) {
3471 result = result ? SortedMerge<IsLessThanOrEqual>(*left, result) : *left;
3472 }
3473 }
3474 return result;
3475 }
3477 template<bool IsLessThanOrEqual(nsIFrame*, nsIFrame*)>
3478 /* static */ void
3479 nsIFrame::SortFrameList(nsFrameList& aFrameList)
3480 {
3481 nsIFrame* head = MergeSort<IsLessThanOrEqual>(aFrameList.FirstChild());
3482 aFrameList = nsFrameList(head, nsLayoutUtils::GetLastSibling(head));
3483 MOZ_ASSERT(IsFrameListSorted<IsLessThanOrEqual>(aFrameList),
3484 "After we sort a frame list, it should be in sorted order...");
3485 }
3487 template<bool IsLessThanOrEqual(nsIFrame*, nsIFrame*)>
3488 /* static */ bool
3489 nsIFrame::IsFrameListSorted(nsFrameList& aFrameList)
3490 {
3491 if (aFrameList.IsEmpty()) {
3492 // empty lists are trivially sorted.
3493 return true;
3494 }
3496 // We'll walk through the list with two iterators, one trailing behind the
3497 // other. The list is sorted IFF trailingIter <= iter, across the whole list.
3498 nsFrameList::Enumerator trailingIter(aFrameList);
3499 nsFrameList::Enumerator iter(aFrameList);
3500 iter.Next(); // Skip |iter| past first frame. (List is nonempty, so we can.)
3502 // Now, advance the iterators in parallel, comparing each adjacent pair.
3503 while (!iter.AtEnd()) {
3504 MOZ_ASSERT(!trailingIter.AtEnd(), "trailing iter shouldn't finish first");
3505 if (!IsLessThanOrEqual(trailingIter.get(), iter.get())) {
3506 return false;
3507 }
3508 trailingIter.Next();
3509 iter.Next();
3510 }
3512 // We made it to the end without returning early, so the list is sorted.
3513 return true;
3514 }
3516 #endif /* nsIFrame_h___ */