1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/layout/generic/nsIFrame.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,3516 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* vim: set ts=2 sw=2 et tw=78: */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +/* interface for all rendering objects */ 1.11 + 1.12 +#ifndef nsIFrame_h___ 1.13 +#define nsIFrame_h___ 1.14 + 1.15 +#ifndef MOZILLA_INTERNAL_API 1.16 +#error This header/class should only be used within Mozilla code. It should not be used by extensions. 1.17 +#endif 1.18 + 1.19 +#define MAX_REFLOW_DEPTH 200 1.20 + 1.21 +/* nsIFrame is in the process of being deCOMtaminated, i.e., this file is eventually 1.22 + going to be eliminated, and all callers will use nsFrame instead. At the moment 1.23 + we're midway through this process, so you will see inlined functions and member 1.24 + variables in this file. -dwh */ 1.25 + 1.26 +#include <stdio.h> 1.27 +#include "nsQueryFrame.h" 1.28 +#include "nsStyleContext.h" 1.29 +#include "nsStyleStruct.h" 1.30 +#include "nsHTMLReflowMetrics.h" 1.31 +#include "nsFrameList.h" 1.32 +#include "mozilla/layout/FrameChildList.h" 1.33 +#include "FramePropertyTable.h" 1.34 +#include "mozilla/TypedEnum.h" 1.35 +#include "nsDirection.h" 1.36 +#include "WritingModes.h" 1.37 +#include <algorithm> 1.38 +#include "nsITheme.h" 1.39 +#include "gfx3DMatrix.h" 1.40 +#include "nsLayoutUtils.h" 1.41 +#include "nsFrameState.h" 1.42 + 1.43 +#ifdef ACCESSIBILITY 1.44 +#include "mozilla/a11y/AccTypes.h" 1.45 +#endif 1.46 + 1.47 +/** 1.48 + * New rules of reflow: 1.49 + * 1. you get a WillReflow() followed by a Reflow() followed by a DidReflow() in order 1.50 + * (no separate pass over the tree) 1.51 + * 2. it's the parent frame's responsibility to size/position the child's view (not 1.52 + * the child frame's responsibility as it is today) during reflow (and before 1.53 + * sending the DidReflow() notification) 1.54 + * 3. positioning of child frames (and their views) is done on the way down the tree, 1.55 + * and sizing of child frames (and their views) on the way back up 1.56 + * 4. if you move a frame (outside of the reflow process, or after reflowing it), 1.57 + * then you must make sure that its view (or its child frame's views) are re-positioned 1.58 + * as well. It's reasonable to not position the view until after all reflowing the 1.59 + * entire line, for example, but the frame should still be positioned and sized (and 1.60 + * the view sized) during the reflow (i.e., before sending the DidReflow() notification) 1.61 + * 5. the view system handles moving of widgets, i.e., it's not our problem 1.62 + */ 1.63 + 1.64 +struct nsHTMLReflowState; 1.65 +class nsHTMLReflowCommand; 1.66 + 1.67 +struct gfxMatrix; 1.68 +class nsIAtom; 1.69 +class nsPresContext; 1.70 +class nsIPresShell; 1.71 +class nsRenderingContext; 1.72 +class nsView; 1.73 +class nsIWidget; 1.74 +class nsIDOMRange; 1.75 +class nsISelectionController; 1.76 +class nsBoxLayoutState; 1.77 +class nsBoxLayout; 1.78 +class nsILineIterator; 1.79 +class nsDisplayListBuilder; 1.80 +class nsDisplayListSet; 1.81 +class nsDisplayList; 1.82 +class gfxSkipChars; 1.83 +class gfxSkipCharsIterator; 1.84 +class gfxContext; 1.85 +class nsLineList_iterator; 1.86 +class nsAbsoluteContainingBlock; 1.87 +class nsIContent; 1.88 + 1.89 +struct nsPeekOffsetStruct; 1.90 +struct nsPoint; 1.91 +struct nsRect; 1.92 +struct nsSize; 1.93 +struct nsMargin; 1.94 +struct CharacterDataChangeInfo; 1.95 + 1.96 +namespace mozilla { 1.97 + 1.98 +class EventStates; 1.99 + 1.100 +namespace layers { 1.101 +class Layer; 1.102 +} 1.103 + 1.104 +namespace gfx { 1.105 +class Matrix; 1.106 +} 1.107 +} 1.108 + 1.109 +/** 1.110 + * Indication of how the frame can be split. This is used when doing runaround 1.111 + * of floats, and when pulling up child frames from a next-in-flow. 1.112 + * 1.113 + * The choices are splittable, not splittable at all, and splittable in 1.114 + * a non-rectangular fashion. This last type only applies to block-level 1.115 + * elements, and indicates whether splitting can be used when doing runaround. 1.116 + * If you can split across page boundaries, but you expect each continuing 1.117 + * frame to be the same width then return frSplittable and not 1.118 + * frSplittableNonRectangular. 1.119 + * 1.120 + * @see #GetSplittableType() 1.121 + */ 1.122 +typedef uint32_t nsSplittableType; 1.123 + 1.124 +#define NS_FRAME_NOT_SPLITTABLE 0 // Note: not a bit! 1.125 +#define NS_FRAME_SPLITTABLE 0x1 1.126 +#define NS_FRAME_SPLITTABLE_NON_RECTANGULAR 0x3 1.127 + 1.128 +#define NS_FRAME_IS_SPLITTABLE(type)\ 1.129 + (0 != ((type) & NS_FRAME_SPLITTABLE)) 1.130 + 1.131 +#define NS_FRAME_IS_NOT_SPLITTABLE(type)\ 1.132 + (0 == ((type) & NS_FRAME_SPLITTABLE)) 1.133 + 1.134 +#define NS_INTRINSIC_WIDTH_UNKNOWN nscoord_MIN 1.135 + 1.136 +//---------------------------------------------------------------------- 1.137 + 1.138 +#define NS_SUBTREE_DIRTY(_frame) \ 1.139 + (((_frame)->GetStateBits() & \ 1.140 + (NS_FRAME_IS_DIRTY | NS_FRAME_HAS_DIRTY_CHILDREN)) != 0) 1.141 + 1.142 +/** 1.143 + * Constant used to indicate an unconstrained size. 1.144 + * 1.145 + * @see #Reflow() 1.146 + */ 1.147 +#define NS_UNCONSTRAINEDSIZE NS_MAXSIZE 1.148 + 1.149 +#define NS_INTRINSICSIZE NS_UNCONSTRAINEDSIZE 1.150 +#define NS_AUTOHEIGHT NS_UNCONSTRAINEDSIZE 1.151 +#define NS_AUTOMARGIN NS_UNCONSTRAINEDSIZE 1.152 +#define NS_AUTOOFFSET NS_UNCONSTRAINEDSIZE 1.153 +// NOTE: there are assumptions all over that these have the same value, namely NS_UNCONSTRAINEDSIZE 1.154 +// if any are changed to be a value other than NS_UNCONSTRAINEDSIZE 1.155 +// at least update AdjustComputedHeight/Width and test ad nauseum 1.156 + 1.157 +//---------------------------------------------------------------------- 1.158 + 1.159 +enum nsSelectionAmount { 1.160 + eSelectCharacter = 0, // a single Unicode character; 1.161 + // do not use this (prefer Cluster) unless you 1.162 + // are really sure it's what you want 1.163 + eSelectCluster = 1, // a grapheme cluster: this is usually the right 1.164 + // choice for movement or selection by "character" 1.165 + // as perceived by the user 1.166 + eSelectWord = 2, 1.167 + eSelectLine = 3, // previous drawn line in flow. 1.168 + eSelectBeginLine = 4, 1.169 + eSelectEndLine = 5, 1.170 + eSelectNoAmount = 6, // just bounce back current offset. 1.171 + eSelectParagraph = 7, // select a "paragraph" 1.172 + eSelectWordNoSpace = 8 // select a "word" without selecting the following 1.173 + // space, no matter what the default platform 1.174 + // behavior is 1.175 +}; 1.176 + 1.177 +enum nsSpread { 1.178 + eSpreadNone = 0, 1.179 + eSpreadAcross = 1, 1.180 + eSpreadDown = 2 1.181 +}; 1.182 + 1.183 +// Carried out margin flags 1.184 +#define NS_CARRIED_TOP_MARGIN_IS_AUTO 0x1 1.185 +#define NS_CARRIED_BOTTOM_MARGIN_IS_AUTO 0x2 1.186 + 1.187 +//---------------------------------------------------------------------- 1.188 + 1.189 +/** 1.190 + * Reflow status returned by the reflow methods. There are three 1.191 + * completion statuses, represented by two bit flags. 1.192 + * 1.193 + * NS_FRAME_COMPLETE means the frame is fully complete. 1.194 + * 1.195 + * NS_FRAME_NOT_COMPLETE bit flag means the frame does not map all its 1.196 + * content, and that the parent frame should create a continuing frame. 1.197 + * If this bit isn't set it means the frame does map all its content. 1.198 + * This bit is mutually exclusive with NS_FRAME_OVERFLOW_INCOMPLETE. 1.199 + * 1.200 + * NS_FRAME_OVERFLOW_INCOMPLETE bit flag means that the frame has 1.201 + * overflow that is not complete, but its own box is complete. 1.202 + * (This happens when content overflows a fixed-height box.) 1.203 + * The reflower should place and size the frame and continue its reflow, 1.204 + * but needs to create an overflow container as a continuation for this 1.205 + * frame. See nsContainerFrame.h for more information. 1.206 + * This bit is mutually exclusive with NS_FRAME_NOT_COMPLETE. 1.207 + * 1.208 + * Please use the SET macro for handling 1.209 + * NS_FRAME_NOT_COMPLETE and NS_FRAME_OVERFLOW_INCOMPLETE. 1.210 + * 1.211 + * NS_FRAME_REFLOW_NEXTINFLOW bit flag means that the next-in-flow is 1.212 + * dirty, and also needs to be reflowed. This status only makes sense 1.213 + * for a frame that is not complete, i.e. you wouldn't set both 1.214 + * NS_FRAME_COMPLETE and NS_FRAME_REFLOW_NEXTINFLOW. 1.215 + * 1.216 + * The low 8 bits of the nsReflowStatus are reserved for future extensions; 1.217 + * the remaining 24 bits are zero (and available for extensions; however 1.218 + * API's that accept/return nsReflowStatus must not receive/return any 1.219 + * extension bits). 1.220 + * 1.221 + * @see #Reflow() 1.222 + */ 1.223 +typedef uint32_t nsReflowStatus; 1.224 + 1.225 +#define NS_FRAME_COMPLETE 0 // Note: not a bit! 1.226 +#define NS_FRAME_NOT_COMPLETE 0x1 1.227 +#define NS_FRAME_REFLOW_NEXTINFLOW 0x2 1.228 +#define NS_FRAME_OVERFLOW_INCOMPLETE 0x4 1.229 + 1.230 +#define NS_FRAME_IS_COMPLETE(status) \ 1.231 + (0 == ((status) & NS_FRAME_NOT_COMPLETE)) 1.232 + 1.233 +#define NS_FRAME_IS_NOT_COMPLETE(status) \ 1.234 + (0 != ((status) & NS_FRAME_NOT_COMPLETE)) 1.235 + 1.236 +#define NS_FRAME_OVERFLOW_IS_INCOMPLETE(status) \ 1.237 + (0 != ((status) & NS_FRAME_OVERFLOW_INCOMPLETE)) 1.238 + 1.239 +#define NS_FRAME_IS_FULLY_COMPLETE(status) \ 1.240 + (NS_FRAME_IS_COMPLETE(status) && !NS_FRAME_OVERFLOW_IS_INCOMPLETE(status)) 1.241 + 1.242 +// These macros set or switch incomplete statuses without touching the 1.243 +// NS_FRAME_REFLOW_NEXTINFLOW bit. 1.244 +#define NS_FRAME_SET_INCOMPLETE(status) \ 1.245 + status = (status & ~NS_FRAME_OVERFLOW_INCOMPLETE) | NS_FRAME_NOT_COMPLETE 1.246 + 1.247 +#define NS_FRAME_SET_OVERFLOW_INCOMPLETE(status) \ 1.248 + status = (status & ~NS_FRAME_NOT_COMPLETE) | NS_FRAME_OVERFLOW_INCOMPLETE 1.249 + 1.250 +// This macro tests to see if an nsReflowStatus is an error value 1.251 +// or just a regular return value 1.252 +#define NS_IS_REFLOW_ERROR(_status) (int32_t(_status) < 0) 1.253 + 1.254 +/** 1.255 + * Extensions to the reflow status bits defined by nsIFrameReflow 1.256 + */ 1.257 + 1.258 +// This bit is set, when a break is requested. This bit is orthogonal 1.259 +// to the nsIFrame::nsReflowStatus completion bits. 1.260 +#define NS_INLINE_BREAK 0x0100 1.261 + 1.262 +// When a break is requested, this bit when set indicates that the 1.263 +// break should occur after the frame just reflowed; when the bit is 1.264 +// clear the break should occur before the frame just reflowed. 1.265 +#define NS_INLINE_BREAK_BEFORE 0x0000 1.266 +#define NS_INLINE_BREAK_AFTER 0x0200 1.267 + 1.268 +// The type of break requested can be found in these bits. 1.269 +#define NS_INLINE_BREAK_TYPE_MASK 0xF000 1.270 + 1.271 +// Set when a break was induced by completion of a first-letter 1.272 +#define NS_INLINE_BREAK_FIRST_LETTER_COMPLETE 0x10000 1.273 + 1.274 +//---------------------------------------- 1.275 +// Macros that use those bits 1.276 + 1.277 +#define NS_INLINE_IS_BREAK(_status) \ 1.278 + (0 != ((_status) & NS_INLINE_BREAK)) 1.279 + 1.280 +#define NS_INLINE_IS_BREAK_AFTER(_status) \ 1.281 + (0 != ((_status) & NS_INLINE_BREAK_AFTER)) 1.282 + 1.283 +#define NS_INLINE_IS_BREAK_BEFORE(_status) \ 1.284 + (NS_INLINE_BREAK == ((_status) & (NS_INLINE_BREAK|NS_INLINE_BREAK_AFTER))) 1.285 + 1.286 +#define NS_INLINE_GET_BREAK_TYPE(_status) (((_status) >> 12) & 0xF) 1.287 + 1.288 +#define NS_INLINE_MAKE_BREAK_TYPE(_type) ((_type) << 12) 1.289 + 1.290 +// Construct a line-break-before status. Note that there is no 1.291 +// completion status for a line-break before because we *know* that 1.292 +// the frame will be reflowed later and hence its current completion 1.293 +// status doesn't matter. 1.294 +#define NS_INLINE_LINE_BREAK_BEFORE() \ 1.295 + (NS_INLINE_BREAK | NS_INLINE_BREAK_BEFORE | \ 1.296 + NS_INLINE_MAKE_BREAK_TYPE(NS_STYLE_CLEAR_LINE)) 1.297 + 1.298 +// Take a completion status and add to it the desire to have a 1.299 +// line-break after. For this macro we do need the completion status 1.300 +// because the user of the status will need to know whether to 1.301 +// continue the frame or not. 1.302 +#define NS_INLINE_LINE_BREAK_AFTER(_completionStatus) \ 1.303 + ((_completionStatus) | NS_INLINE_BREAK | NS_INLINE_BREAK_AFTER | \ 1.304 + NS_INLINE_MAKE_BREAK_TYPE(NS_STYLE_CLEAR_LINE)) 1.305 + 1.306 +// A frame is "truncated" if the part of the frame before the first 1.307 +// possible break point was unable to fit in the available vertical 1.308 +// space. Therefore, the entire frame should be moved to the next page. 1.309 +// A frame that begins at the top of the page must never be "truncated". 1.310 +// Doing so would likely cause an infinite loop. 1.311 +#define NS_FRAME_TRUNCATED 0x0010 1.312 +#define NS_FRAME_IS_TRUNCATED(status) \ 1.313 + (0 != ((status) & NS_FRAME_TRUNCATED)) 1.314 +#define NS_FRAME_SET_TRUNCATION(status, aReflowState, aMetrics) \ 1.315 + aReflowState.SetTruncated(aMetrics, &status); 1.316 + 1.317 +// Merge the incompleteness, truncation and NS_FRAME_REFLOW_NEXTINFLOW 1.318 +// status from aSecondary into aPrimary. 1.319 +void NS_MergeReflowStatusInto(nsReflowStatus* aPrimary, 1.320 + nsReflowStatus aSecondary); 1.321 + 1.322 +//---------------------------------------------------------------------- 1.323 + 1.324 +/** 1.325 + * DidReflow status values. 1.326 + */ 1.327 +MOZ_BEGIN_ENUM_CLASS(nsDidReflowStatus, uint32_t) 1.328 + NOT_FINISHED, 1.329 + FINISHED 1.330 +MOZ_END_ENUM_CLASS(nsDidReflowStatus) 1.331 + 1.332 +/** 1.333 + * When there is no scrollable overflow rect, the visual overflow rect 1.334 + * may be stored as four 1-byte deltas each strictly LESS THAN 0xff, for 1.335 + * the four edges of the rectangle, or the four bytes may be read as a 1.336 + * single 32-bit "overflow-rect type" value including at least one 0xff 1.337 + * byte as an indicator that the value does NOT represent four deltas. 1.338 + * If all four deltas are zero, this means that no overflow rect has 1.339 + * actually been set (this is the initial state of newly-created frames). 1.340 + */ 1.341 +#define NS_FRAME_OVERFLOW_DELTA_MAX 0xfe // max delta we can store 1.342 + 1.343 +#define NS_FRAME_OVERFLOW_NONE 0x00000000 // there are no overflow rects; 1.344 + // code relies on this being 1.345 + // the all-zero value 1.346 + 1.347 +#define NS_FRAME_OVERFLOW_LARGE 0x000000ff // overflow is stored as a 1.348 + // separate rect property 1.349 + 1.350 +namespace mozilla { 1.351 +/* 1.352 + * For replaced elements only. Gets the intrinsic dimensions of this element. 1.353 + * The dimensions may only be one of the following two types: 1.354 + * 1.355 + * eStyleUnit_Coord - a length in app units 1.356 + * eStyleUnit_None - the element has no intrinsic size in this dimension 1.357 + */ 1.358 +struct IntrinsicSize { 1.359 + nsStyleCoord width, height; 1.360 + 1.361 + IntrinsicSize() 1.362 + : width(eStyleUnit_None), height(eStyleUnit_None) 1.363 + {} 1.364 + IntrinsicSize(const IntrinsicSize& rhs) 1.365 + : width(rhs.width), height(rhs.height) 1.366 + {} 1.367 + IntrinsicSize& operator=(const IntrinsicSize& rhs) { 1.368 + width = rhs.width; height = rhs.height; return *this; 1.369 + } 1.370 + bool operator==(const IntrinsicSize& rhs) { 1.371 + return width == rhs.width && height == rhs.height; 1.372 + } 1.373 + bool operator!=(const IntrinsicSize& rhs) { 1.374 + return !(*this == rhs); 1.375 + } 1.376 +}; 1.377 +} 1.378 + 1.379 +//---------------------------------------------------------------------- 1.380 + 1.381 +/** 1.382 + * A frame in the layout model. This interface is supported by all frame 1.383 + * objects. 1.384 + * 1.385 + * Frames can have multiple child lists: the default child list 1.386 + * (referred to as the <i>principal</i> child list, and additional named 1.387 + * child lists. There is an ordering of frames within a child list, but 1.388 + * there is no order defined between frames in different child lists of 1.389 + * the same parent frame. 1.390 + * 1.391 + * Frames are NOT reference counted. Use the Destroy() member function 1.392 + * to destroy a frame. The lifetime of the frame hierarchy is bounded by the 1.393 + * lifetime of the presentation shell which owns the frames. 1.394 + * 1.395 + * nsIFrame is a private Gecko interface. If you are not Gecko then you 1.396 + * should not use it. If you're not in layout, then you won't be able to 1.397 + * link to many of the functions defined here. Too bad. 1.398 + * 1.399 + * If you're not in layout but you must call functions in here, at least 1.400 + * restrict yourself to calling virtual methods, which won't hurt you as badly. 1.401 + */ 1.402 +class nsIFrame : public nsQueryFrame 1.403 +{ 1.404 +public: 1.405 + typedef mozilla::FramePropertyDescriptor FramePropertyDescriptor; 1.406 + typedef mozilla::FrameProperties FrameProperties; 1.407 + typedef mozilla::layers::Layer Layer; 1.408 + typedef mozilla::layout::FrameChildList ChildList; 1.409 + typedef mozilla::layout::FrameChildListID ChildListID; 1.410 + typedef mozilla::layout::FrameChildListIDs ChildListIDs; 1.411 + typedef mozilla::layout::FrameChildListIterator ChildListIterator; 1.412 + typedef mozilla::layout::FrameChildListArrayIterator ChildListArrayIterator; 1.413 + typedef mozilla::gfx::Matrix Matrix; 1.414 + 1.415 + NS_DECL_QUERYFRAME_TARGET(nsIFrame) 1.416 + 1.417 + nsPresContext* PresContext() const { 1.418 + return StyleContext()->RuleNode()->PresContext(); 1.419 + } 1.420 + 1.421 + /** 1.422 + * Called to initialize the frame. This is called immediately after creating 1.423 + * the frame. 1.424 + * 1.425 + * If the frame is a continuing frame, then aPrevInFlow indicates the previous 1.426 + * frame (the frame that was split). 1.427 + * 1.428 + * If you want a view associated with your frame, you should create the view 1.429 + * after Init() has returned. 1.430 + * 1.431 + * @param aContent the content object associated with the frame 1.432 + * @param aParent the parent frame 1.433 + * @param aPrevInFlow the prev-in-flow frame 1.434 + */ 1.435 + virtual void Init(nsIContent* aContent, 1.436 + nsIFrame* aParent, 1.437 + nsIFrame* aPrevInFlow) = 0; 1.438 + 1.439 + /** 1.440 + * Destroys this frame and each of its child frames (recursively calls 1.441 + * Destroy() for each child). If this frame is a first-continuation, this 1.442 + * also removes the frame from the primary frame map and clears undisplayed 1.443 + * content for its content node. 1.444 + * If the frame is a placeholder, it also ensures the out-of-flow frame's 1.445 + * removal and destruction. 1.446 + */ 1.447 + void Destroy() { DestroyFrom(this); } 1.448 + 1.449 + /** Flags for PeekOffsetCharacter, PeekOffsetNoAmount, PeekOffsetWord return values. 1.450 + */ 1.451 + enum FrameSearchResult { 1.452 + // Peek found a appropriate offset within frame. 1.453 + FOUND = 0x00, 1.454 + // try next frame for offset. 1.455 + CONTINUE = 0x1, 1.456 + // offset not found because the frame was empty of text. 1.457 + CONTINUE_EMPTY = 0x2 | CONTINUE, 1.458 + // offset not found because the frame didn't contain any text that could be selected. 1.459 + CONTINUE_UNSELECTABLE = 0x4 | CONTINUE, 1.460 + }; 1.461 + 1.462 +protected: 1.463 + /** 1.464 + * Return true if the frame is part of a Selection. 1.465 + * Helper method to implement the public IsSelected() API. 1.466 + */ 1.467 + virtual bool IsFrameSelected() const; 1.468 + 1.469 + /** 1.470 + * Implements Destroy(). Do not call this directly except from within a 1.471 + * DestroyFrom() implementation. 1.472 + * 1.473 + * @note This will always be called, so it is not necessary to override 1.474 + * Destroy() in subclasses of nsFrame, just DestroyFrom(). 1.475 + * 1.476 + * @param aDestructRoot is the root of the subtree being destroyed 1.477 + */ 1.478 + virtual void DestroyFrom(nsIFrame* aDestructRoot) = 0; 1.479 + friend class nsFrameList; // needed to pass aDestructRoot through to children 1.480 + friend class nsLineBox; // needed to pass aDestructRoot through to children 1.481 + friend class nsContainerFrame; // needed to pass aDestructRoot through to children 1.482 +public: 1.483 + 1.484 + /** 1.485 + * Called to set the initial list of frames. This happens after the frame 1.486 + * has been initialized. 1.487 + * 1.488 + * This is only called once for a given child list, and won't be called 1.489 + * at all for child lists with no initial list of frames. 1.490 + * 1.491 + * @param aListID the child list identifier. 1.492 + * @param aChildList list of child frames. Each of the frames has its 1.493 + * NS_FRAME_IS_DIRTY bit set. Must not be empty. 1.494 + * This method cannot handle the child list returned by 1.495 + * GetAbsoluteListID(). 1.496 + * @return NS_ERROR_INVALID_ARG if there is no child list with the specified 1.497 + * name, 1.498 + * NS_ERROR_UNEXPECTED if the frame is an atomic frame or if the 1.499 + * initial list of frames has already been set for that child list, 1.500 + * NS_OK otherwise. In this case, SetInitialChildList empties out 1.501 + * aChildList in the process of moving the frames over to its own 1.502 + * child list. 1.503 + * @see #Init() 1.504 + */ 1.505 + virtual nsresult SetInitialChildList(ChildListID aListID, 1.506 + nsFrameList& aChildList) = 0; 1.507 + 1.508 + /** 1.509 + * This method is responsible for appending frames to the frame 1.510 + * list. The implementation should append the frames to the specified 1.511 + * child list and then generate a reflow command. 1.512 + * 1.513 + * @param aListID the child list identifier. 1.514 + * @param aFrameList list of child frames to append. Each of the frames has 1.515 + * its NS_FRAME_IS_DIRTY bit set. Must not be empty. 1.516 + * @return NS_ERROR_INVALID_ARG if there is no child list with the specified 1.517 + * name, 1.518 + * NS_ERROR_UNEXPECTED if the frame is an atomic frame, 1.519 + * NS_OK otherwise. In this case, AppendFrames empties out 1.520 + * aFrameList in the process of moving the frames over to its own 1.521 + * child list. 1.522 + */ 1.523 + virtual nsresult AppendFrames(ChildListID aListID, 1.524 + nsFrameList& aFrameList) = 0; 1.525 + 1.526 + /** 1.527 + * This method is responsible for inserting frames into the frame 1.528 + * list. The implementation should insert the new frames into the specified 1.529 + * child list and then generate a reflow command. 1.530 + * 1.531 + * @param aListID the child list identifier. 1.532 + * @param aPrevFrame the frame to insert frames <b>after</b> 1.533 + * @param aFrameList list of child frames to insert <b>after</b> aPrevFrame. 1.534 + * Each of the frames has its NS_FRAME_IS_DIRTY bit set 1.535 + * @return NS_ERROR_INVALID_ARG if there is no child list with the specified 1.536 + * name, 1.537 + * NS_ERROR_UNEXPECTED if the frame is an atomic frame, 1.538 + * NS_OK otherwise. In this case, InsertFrames empties out 1.539 + * aFrameList in the process of moving the frames over to its own 1.540 + * child list. 1.541 + */ 1.542 + virtual nsresult InsertFrames(ChildListID aListID, 1.543 + nsIFrame* aPrevFrame, 1.544 + nsFrameList& aFrameList) = 0; 1.545 + 1.546 + /** 1.547 + * This method is responsible for removing a frame in the frame 1.548 + * list. The implementation should do something with the removed frame 1.549 + * and then generate a reflow command. The implementation is responsible 1.550 + * for destroying aOldFrame (the caller mustn't destroy aOldFrame). 1.551 + * 1.552 + * @param aListID the child list identifier. 1.553 + * @param aOldFrame the frame to remove 1.554 + * @return NS_ERROR_INVALID_ARG if there is no child list with the specified 1.555 + * name, 1.556 + * NS_ERROR_FAILURE if the child frame is not in the specified 1.557 + * child list, 1.558 + * NS_ERROR_UNEXPECTED if the frame is an atomic frame, 1.559 + * NS_OK otherwise 1.560 + */ 1.561 + virtual nsresult RemoveFrame(ChildListID aListID, 1.562 + nsIFrame* aOldFrame) = 0; 1.563 + 1.564 + /** 1.565 + * Get the content object associated with this frame. Does not add a reference. 1.566 + */ 1.567 + nsIContent* GetContent() const { return mContent; } 1.568 + 1.569 + /** 1.570 + * Get the frame that should be the parent for the frames of child elements 1.571 + * May return nullptr during reflow 1.572 + */ 1.573 + virtual nsIFrame* GetContentInsertionFrame() { return this; } 1.574 + 1.575 + /** 1.576 + * Move any frames on our overflow list to the end of our principal list. 1.577 + * @return true if there were any overflow frames 1.578 + */ 1.579 + virtual bool DrainSelfOverflowList() { return false; } 1.580 + 1.581 + /** 1.582 + * Get the frame that should be scrolled if the content associated 1.583 + * with this frame is targeted for scrolling. For frames implementing 1.584 + * nsIScrollableFrame this will return the frame itself. For frames 1.585 + * like nsTextControlFrame that contain a scrollframe, will return 1.586 + * that scrollframe. 1.587 + */ 1.588 + virtual nsIScrollableFrame* GetScrollTargetFrame() { return nullptr; } 1.589 + 1.590 + /** 1.591 + * Get the offsets of the frame. most will be 0,0 1.592 + * 1.593 + */ 1.594 + virtual nsresult GetOffsets(int32_t &start, int32_t &end) const = 0; 1.595 + 1.596 + /** 1.597 + * Reset the offsets when splitting frames during Bidi reordering 1.598 + * 1.599 + */ 1.600 + virtual void AdjustOffsetsForBidi(int32_t aStart, int32_t aEnd) {} 1.601 + 1.602 + /** 1.603 + * Get the style context associated with this frame. 1.604 + */ 1.605 + nsStyleContext* StyleContext() const { return mStyleContext; } 1.606 + void SetStyleContext(nsStyleContext* aContext) 1.607 + { 1.608 + if (aContext != mStyleContext) { 1.609 + nsStyleContext* oldStyleContext = mStyleContext; 1.610 + mStyleContext = aContext; 1.611 + aContext->AddRef(); 1.612 + DidSetStyleContext(oldStyleContext); 1.613 + oldStyleContext->Release(); 1.614 + } 1.615 + } 1.616 + 1.617 + /** 1.618 + * SetStyleContextWithoutNotification is for changes to the style 1.619 + * context that should suppress style change processing, in other 1.620 + * words, those that aren't really changes. This generally means only 1.621 + * changes that happen during frame construction. 1.622 + */ 1.623 + void SetStyleContextWithoutNotification(nsStyleContext* aContext) 1.624 + { 1.625 + if (aContext != mStyleContext) { 1.626 + mStyleContext->Release(); 1.627 + mStyleContext = aContext; 1.628 + aContext->AddRef(); 1.629 + } 1.630 + } 1.631 + 1.632 + // Style post processing hook 1.633 + // Attention: the old style context is the one we're forgetting, 1.634 + // and hence possibly completely bogus for GetStyle* purposes. 1.635 + // Use PeekStyleData instead. 1.636 + virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext) = 0; 1.637 + 1.638 + /** 1.639 + * Define typesafe getter functions for each style struct by 1.640 + * preprocessing the list of style structs. These functions are the 1.641 + * preferred way to get style data. The macro creates functions like: 1.642 + * const nsStyleBorder* StyleBorder(); 1.643 + * const nsStyleColor* StyleColor(); 1.644 + * 1.645 + * Callers outside of libxul should use nsIDOMWindow::GetComputedStyle() 1.646 + * instead of these accessors. 1.647 + */ 1.648 + #define STYLE_STRUCT(name_, checkdata_cb_) \ 1.649 + const nsStyle##name_ * Style##name_ () const { \ 1.650 + NS_ASSERTION(mStyleContext, "No style context found!"); \ 1.651 + return mStyleContext->Style##name_ (); \ 1.652 + } 1.653 + #include "nsStyleStructList.h" 1.654 + #undef STYLE_STRUCT 1.655 + 1.656 + /** Also forward GetVisitedDependentColor to the style context */ 1.657 + nscolor GetVisitedDependentColor(nsCSSProperty aProperty) 1.658 + { return mStyleContext->GetVisitedDependentColor(aProperty); } 1.659 + 1.660 + /** 1.661 + * These methods are to access any additional style contexts that 1.662 + * the frame may be holding. These are contexts that are children 1.663 + * of the frame's primary context and are NOT used as style contexts 1.664 + * for any child frames. These contexts also MUST NOT have any child 1.665 + * contexts whatsoever. If you need to insert style contexts into the 1.666 + * style tree, then you should create pseudo element frames to own them 1.667 + * The indicies must be consecutive and implementations MUST return an 1.668 + * NS_ERROR_INVALID_ARG if asked for an index that is out of range. 1.669 + */ 1.670 + virtual nsStyleContext* GetAdditionalStyleContext(int32_t aIndex) const = 0; 1.671 + 1.672 + virtual void SetAdditionalStyleContext(int32_t aIndex, 1.673 + nsStyleContext* aStyleContext) = 0; 1.674 + 1.675 + /** 1.676 + * Accessor functions for geometric parent 1.677 + */ 1.678 + nsIFrame* GetParent() const { return mParent; } 1.679 + /** 1.680 + * Set this frame's parent to aParent. 1.681 + * If the frame may have moved into or out of a scrollframe's 1.682 + * frame subtree, StickyScrollContainer::NotifyReparentedFrameAcrossScrollFrameBoundary 1.683 + * must also be called. 1.684 + */ 1.685 + virtual void SetParent(nsIFrame* aParent) = 0; 1.686 + 1.687 + /** 1.688 + * The frame's writing-mode, used for logical layout computations. 1.689 + */ 1.690 + mozilla::WritingMode GetWritingMode() const { 1.691 + return mozilla::WritingMode(StyleVisibility()); 1.692 + } 1.693 + 1.694 + /** 1.695 + * Get the writing mode of this frame, but if it is styled with 1.696 + * unicode-bidi: plaintext, reset the direction to the resolved paragraph 1.697 + * level of the given subframe (typically the first frame on the line), 1.698 + * not this frame's writing mode, because the container frame could be split 1.699 + * by hard line breaks into multiple paragraphs with different base direction. 1.700 + */ 1.701 + mozilla::WritingMode GetWritingMode(nsIFrame* aSubFrame) const; 1.702 + 1.703 + /** 1.704 + * Bounding rect of the frame. The values are in app units, and the origin is 1.705 + * relative to the upper-left of the geometric parent. The size includes the 1.706 + * content area, borders, and padding. 1.707 + * 1.708 + * Note: moving or sizing the frame does not affect the view's size or 1.709 + * position. 1.710 + */ 1.711 + nsRect GetRect() const { return mRect; } 1.712 + nsPoint GetPosition() const { return mRect.TopLeft(); } 1.713 + nsSize GetSize() const { return mRect.Size(); } 1.714 + nsRect GetRectRelativeToSelf() const { 1.715 + return nsRect(nsPoint(0, 0), mRect.Size()); 1.716 + } 1.717 + /** 1.718 + * Dimensions and position in logical coordinates in the frame's writing mode 1.719 + * or another writing mode 1.720 + */ 1.721 + mozilla::LogicalRect GetLogicalRect(nscoord aContainerWidth) const { 1.722 + return GetLogicalRect(GetWritingMode(), aContainerWidth); 1.723 + } 1.724 + mozilla::LogicalPoint GetLogicalPosition(nscoord aContainerWidth) const { 1.725 + return GetLogicalPosition(GetWritingMode(), aContainerWidth); 1.726 + } 1.727 + mozilla::LogicalSize GetLogicalSize() const { 1.728 + return GetLogicalSize(GetWritingMode()); 1.729 + } 1.730 + mozilla::LogicalRect GetLogicalRect(mozilla::WritingMode aWritingMode, 1.731 + nscoord aContainerWidth) const { 1.732 + return mozilla::LogicalRect(aWritingMode, GetRect(), aContainerWidth); 1.733 + } 1.734 + mozilla::LogicalPoint GetLogicalPosition(mozilla::WritingMode aWritingMode, 1.735 + nscoord aContainerWidth) const { 1.736 + return GetLogicalRect(aWritingMode, aContainerWidth).Origin(aWritingMode); 1.737 + } 1.738 + mozilla::LogicalSize GetLogicalSize(mozilla::WritingMode aWritingMode) const { 1.739 + return mozilla::LogicalSize(aWritingMode, GetSize()); 1.740 + } 1.741 + nscoord IStart(nscoord aContainerWidth) const { 1.742 + return IStart(GetWritingMode(), aContainerWidth); 1.743 + } 1.744 + nscoord IStart(mozilla::WritingMode aWritingMode, 1.745 + nscoord aContainerWidth) const { 1.746 + return GetLogicalPosition(aWritingMode, aContainerWidth).I(aWritingMode); 1.747 + } 1.748 + nscoord BStart(nscoord aContainerWidth) const { 1.749 + return BStart(GetWritingMode(), aContainerWidth); 1.750 + } 1.751 + nscoord BStart(mozilla::WritingMode aWritingMode, 1.752 + nscoord aContainerWidth) const { 1.753 + return GetLogicalPosition(aWritingMode, aContainerWidth).B(aWritingMode); 1.754 + } 1.755 + nscoord ISize() const { return ISize(GetWritingMode()); } 1.756 + nscoord ISize(mozilla::WritingMode aWritingMode) const { 1.757 + return GetLogicalSize(aWritingMode).ISize(aWritingMode); 1.758 + } 1.759 + nscoord BSize() const { return BSize(GetWritingMode()); } 1.760 + nscoord BSize(mozilla::WritingMode aWritingMode) const { 1.761 + return GetLogicalSize(aWritingMode).BSize(aWritingMode); 1.762 + } 1.763 + 1.764 + /** 1.765 + * When we change the size of the frame's border-box rect, we may need to 1.766 + * reset the overflow rect if it was previously stored as deltas. 1.767 + * (If it is currently a "large" overflow and could be re-packed as deltas, 1.768 + * we don't bother as the cost of the allocation has already been paid.) 1.769 + */ 1.770 + void SetRect(const nsRect& aRect) { 1.771 + if (mOverflow.mType != NS_FRAME_OVERFLOW_LARGE && 1.772 + mOverflow.mType != NS_FRAME_OVERFLOW_NONE) { 1.773 + nsOverflowAreas overflow = GetOverflowAreas(); 1.774 + mRect = aRect; 1.775 + SetOverflowAreas(overflow); 1.776 + } else { 1.777 + mRect = aRect; 1.778 + } 1.779 + } 1.780 + /** 1.781 + * Set this frame's rect from a logical rect in its own writing direction 1.782 + */ 1.783 + void SetRect(const mozilla::LogicalRect& aRect, nscoord aContainerWidth) { 1.784 + SetRect(GetWritingMode(), aRect, aContainerWidth); 1.785 + } 1.786 + /** 1.787 + * Set this frame's rect from a logical rect in a different writing direction 1.788 + * (GetPhysicalRect will assert if the writing mode doesn't match) 1.789 + */ 1.790 + void SetRect(mozilla::WritingMode aWritingMode, 1.791 + const mozilla::LogicalRect& aRect, 1.792 + nscoord aContainerWidth) { 1.793 + SetRect(aRect.GetPhysicalRect(aWritingMode, aContainerWidth)); 1.794 + } 1.795 + void SetSize(const nsSize& aSize) { 1.796 + SetRect(nsRect(mRect.TopLeft(), aSize)); 1.797 + } 1.798 + void SetPosition(const nsPoint& aPt) { mRect.MoveTo(aPt); } 1.799 + 1.800 + /** 1.801 + * Move the frame, accounting for relative positioning. Use this when 1.802 + * adjusting the frame's position by a known amount, to properly update its 1.803 + * saved normal position (see GetNormalPosition below). 1.804 + * 1.805 + * This must be used only when moving a frame *after* 1.806 + * nsHTMLReflowState::ApplyRelativePositioning is called. When moving 1.807 + * a frame during the reflow process prior to calling 1.808 + * nsHTMLReflowState::ApplyRelativePositioning, the position should 1.809 + * simply be adjusted directly (e.g., using SetPosition()). 1.810 + */ 1.811 + void MovePositionBy(const nsPoint& aTranslation); 1.812 + 1.813 + /** 1.814 + * Return frame's position without relative positioning 1.815 + */ 1.816 + nsPoint GetNormalPosition() const; 1.817 + mozilla::LogicalPoint 1.818 + GetLogicalNormalPosition(mozilla::WritingMode aWritingMode, 1.819 + nscoord aContainerWidth) const 1.820 + { 1.821 + return mozilla::LogicalPoint(aWritingMode, 1.822 + GetNormalPosition(), aContainerWidth); 1.823 + } 1.824 + 1.825 + virtual nsPoint GetPositionOfChildIgnoringScrolling(nsIFrame* aChild) 1.826 + { return aChild->GetPosition(); } 1.827 + 1.828 + nsPoint GetPositionIgnoringScrolling() { 1.829 + return mParent ? mParent->GetPositionOfChildIgnoringScrolling(this) 1.830 + : GetPosition(); 1.831 + } 1.832 + 1.833 + static void DestroyRegion(void* aPropertyValue); 1.834 + 1.835 + static void DestroyMargin(void* aPropertyValue) 1.836 + { 1.837 + delete static_cast<nsMargin*>(aPropertyValue); 1.838 + } 1.839 + 1.840 + static void DestroyRect(void* aPropertyValue) 1.841 + { 1.842 + delete static_cast<nsRect*>(aPropertyValue); 1.843 + } 1.844 + 1.845 + static void DestroyPoint(void* aPropertyValue) 1.846 + { 1.847 + delete static_cast<nsPoint*>(aPropertyValue); 1.848 + } 1.849 + 1.850 + static void DestroyOverflowAreas(void* aPropertyValue) 1.851 + { 1.852 + delete static_cast<nsOverflowAreas*>(aPropertyValue); 1.853 + } 1.854 + 1.855 + static void DestroySurface(void* aPropertyValue); 1.856 + static void DestroyDT(void* aPropertyValue); 1.857 + 1.858 +#ifdef _MSC_VER 1.859 +// XXX Workaround MSVC issue by making the static FramePropertyDescriptor 1.860 +// non-const. See bug 555727. 1.861 +#define NS_PROPERTY_DESCRIPTOR_CONST 1.862 +#else 1.863 +#define NS_PROPERTY_DESCRIPTOR_CONST const 1.864 +#endif 1.865 + 1.866 +#define NS_DECLARE_FRAME_PROPERTY(prop, dtor) \ 1.867 + static const FramePropertyDescriptor* prop() { \ 1.868 + static NS_PROPERTY_DESCRIPTOR_CONST FramePropertyDescriptor descriptor = { dtor, nullptr }; \ 1.869 + return &descriptor; \ 1.870 + } 1.871 +// Don't use this unless you really know what you're doing! 1.872 +#define NS_DECLARE_FRAME_PROPERTY_WITH_FRAME_IN_DTOR(prop, dtor) \ 1.873 + static const FramePropertyDescriptor* prop() { \ 1.874 + static NS_PROPERTY_DESCRIPTOR_CONST FramePropertyDescriptor descriptor = { nullptr, dtor }; \ 1.875 + return &descriptor; \ 1.876 + } 1.877 + 1.878 + NS_DECLARE_FRAME_PROPERTY(IBSplitSibling, nullptr) 1.879 + NS_DECLARE_FRAME_PROPERTY(IBSplitPrevSibling, nullptr) 1.880 + 1.881 + NS_DECLARE_FRAME_PROPERTY(NormalPositionProperty, DestroyPoint) 1.882 + NS_DECLARE_FRAME_PROPERTY(ComputedOffsetProperty, DestroyMargin) 1.883 + 1.884 + NS_DECLARE_FRAME_PROPERTY(OutlineInnerRectProperty, DestroyRect) 1.885 + NS_DECLARE_FRAME_PROPERTY(PreEffectsBBoxProperty, DestroyRect) 1.886 + NS_DECLARE_FRAME_PROPERTY(PreTransformOverflowAreasProperty, 1.887 + DestroyOverflowAreas) 1.888 + 1.889 + // The initial overflow area passed to FinishAndStoreOverflow. This is only set 1.890 + // on frames that Preserve3D() or HasPerspective() or IsTransformed(), and 1.891 + // when at least one of the overflow areas differs from the frame bound rect. 1.892 + NS_DECLARE_FRAME_PROPERTY(InitialOverflowProperty, DestroyOverflowAreas) 1.893 + 1.894 +#ifdef DEBUG 1.895 + // InitialOverflowPropertyDebug is added to the frame to indicate that either 1.896 + // the InitialOverflowProperty has been stored or the InitialOverflowProperty 1.897 + // has been suppressed due to being set to the default value (frame bounds) 1.898 + NS_DECLARE_FRAME_PROPERTY(DebugInitialOverflowPropertyApplied, nullptr) 1.899 +#endif 1.900 + 1.901 + NS_DECLARE_FRAME_PROPERTY(UsedMarginProperty, DestroyMargin) 1.902 + NS_DECLARE_FRAME_PROPERTY(UsedPaddingProperty, DestroyMargin) 1.903 + NS_DECLARE_FRAME_PROPERTY(UsedBorderProperty, DestroyMargin) 1.904 + 1.905 + NS_DECLARE_FRAME_PROPERTY(ScrollLayerCount, nullptr) 1.906 + 1.907 + NS_DECLARE_FRAME_PROPERTY(LineBaselineOffset, nullptr) 1.908 + 1.909 + NS_DECLARE_FRAME_PROPERTY(CachedBackgroundImage, DestroySurface) 1.910 + NS_DECLARE_FRAME_PROPERTY(CachedBackgroundImageDT, DestroyDT) 1.911 + 1.912 + NS_DECLARE_FRAME_PROPERTY(InvalidationRect, DestroyRect) 1.913 + 1.914 + NS_DECLARE_FRAME_PROPERTY(RefusedAsyncAnimation, nullptr) 1.915 + 1.916 + /** 1.917 + * Return the distance between the border edge of the frame and the 1.918 + * margin edge of the frame. Like GetRect(), returns the dimensions 1.919 + * as of the most recent reflow. 1.920 + * 1.921 + * This doesn't include any margin collapsing that may have occurred. 1.922 + * 1.923 + * It also treats 'auto' margins as zero, and treats any margins that 1.924 + * should have been turned into 'auto' because of overconstraint as 1.925 + * having their original values. 1.926 + */ 1.927 + virtual nsMargin GetUsedMargin() const; 1.928 + virtual mozilla::LogicalMargin 1.929 + GetLogicalUsedMargin(mozilla::WritingMode aWritingMode) const { 1.930 + return mozilla::LogicalMargin(aWritingMode, GetUsedMargin()); 1.931 + } 1.932 + 1.933 + /** 1.934 + * Return the distance between the border edge of the frame (which is 1.935 + * its rect) and the padding edge of the frame. Like GetRect(), returns 1.936 + * the dimensions as of the most recent reflow. 1.937 + * 1.938 + * Note that this differs from StyleBorder()->GetBorder() in that 1.939 + * this describes region of the frame's box, and 1.940 + * StyleBorder()->GetBorder() describes a border. They differ only 1.941 + * for tables, particularly border-collapse tables. 1.942 + */ 1.943 + virtual nsMargin GetUsedBorder() const; 1.944 + virtual mozilla::LogicalMargin 1.945 + GetLogicalUsedBorder(mozilla::WritingMode aWritingMode) const { 1.946 + return mozilla::LogicalMargin(aWritingMode, GetUsedBorder()); 1.947 + } 1.948 + 1.949 + /** 1.950 + * Return the distance between the padding edge of the frame and the 1.951 + * content edge of the frame. Like GetRect(), returns the dimensions 1.952 + * as of the most recent reflow. 1.953 + */ 1.954 + virtual nsMargin GetUsedPadding() const; 1.955 + virtual mozilla::LogicalMargin 1.956 + GetLogicalUsedPadding(mozilla::WritingMode aWritingMode) const { 1.957 + return mozilla::LogicalMargin(aWritingMode, GetUsedPadding()); 1.958 + } 1.959 + 1.960 + nsMargin GetUsedBorderAndPadding() const { 1.961 + return GetUsedBorder() + GetUsedPadding(); 1.962 + } 1.963 + mozilla::LogicalMargin 1.964 + GetLogicalUsedBorderAndPadding(mozilla::WritingMode aWritingMode) const { 1.965 + return mozilla::LogicalMargin(aWritingMode, GetUsedBorderAndPadding()); 1.966 + } 1.967 + 1.968 + /** 1.969 + * Apply the result of GetSkipSides() on this frame to an nsMargin by 1.970 + * setting to zero any sides that are skipped. 1.971 + * 1.972 + * @param aMargin The margin to apply the result of GetSkipSides() to. 1.973 + * @param aReflowState An optional reflow state parameter, which is used if 1.974 + * ApplySkipSides() is being called in the middle of reflow. 1.975 + * 1.976 + * @note (See also bug 743402, comment 11) GetSkipSides() and its sister 1.977 + * method, ApplySkipSides() checks to see if this frame has a previous 1.978 + * or next continuation to determine if a side should be skipped. 1.979 + * Unfortunately, this only works after reflow has been completed. In 1.980 + * lieu of this, during reflow, an nsHTMLReflowState parameter can be 1.981 + * passed in, indicating that it should be used to determine if sides 1.982 + * should be skipped during reflow. 1.983 + */ 1.984 + void ApplySkipSides(nsMargin& aMargin, 1.985 + const nsHTMLReflowState* aReflowState = nullptr) const; 1.986 + void ApplyLogicalSkipSides(mozilla::LogicalMargin& aMargin, 1.987 + const nsHTMLReflowState* aReflowState = nullptr) const; 1.988 + 1.989 + /** 1.990 + * Like the frame's rect (see |GetRect|), which is the border rect, 1.991 + * other rectangles of the frame, in app units, relative to the parent. 1.992 + */ 1.993 + nsRect GetPaddingRect() const; 1.994 + nsRect GetPaddingRectRelativeToSelf() const; 1.995 + nsRect GetContentRect() const; 1.996 + nsRect GetContentRectRelativeToSelf() const; 1.997 + nsRect GetMarginRectRelativeToSelf() const; 1.998 + 1.999 + /** 1.1000 + * The area to paint box-shadows around. The default is the border rect. 1.1001 + * (nsFieldSetFrame overrides this). 1.1002 + */ 1.1003 + virtual nsRect VisualBorderRectRelativeToSelf() const { 1.1004 + return nsRect(0, 0, mRect.width, mRect.height); 1.1005 + } 1.1006 + 1.1007 + /** 1.1008 + * Get the size, in app units, of the border radii. It returns FALSE iff all 1.1009 + * returned radii == 0 (so no border radii), TRUE otherwise. 1.1010 + * For the aRadii indexes, use the NS_CORNER_* constants in nsStyleConsts.h 1.1011 + * If a side is skipped via aSkipSides, its corners are forced to 0. 1.1012 + * 1.1013 + * All corner radii are then adjusted so they do not require more 1.1014 + * space than aBorderArea, according to the algorithm in css3-background. 1.1015 + * 1.1016 + * aFrameSize is used as the basis for percentage widths and heights. 1.1017 + * aBorderArea is used for the adjustment of radii that might be too 1.1018 + * large. 1.1019 + * FIXME: In the long run, we can probably get away with only one of 1.1020 + * these, especially if we change the way we handle outline-radius (by 1.1021 + * removing it and inflating the border radius) 1.1022 + * 1.1023 + * Return whether any radii are nonzero. 1.1024 + */ 1.1025 + static bool ComputeBorderRadii(const nsStyleCorners& aBorderRadius, 1.1026 + const nsSize& aFrameSize, 1.1027 + const nsSize& aBorderArea, 1.1028 + int aSkipSides, 1.1029 + nscoord aRadii[8]); 1.1030 + 1.1031 + /* 1.1032 + * Given a set of border radii for one box (e.g., border box), convert 1.1033 + * it to the equivalent set of radii for another box (e.g., in to 1.1034 + * padding box, out to outline box) by reducing radii or increasing 1.1035 + * nonzero radii as appropriate. 1.1036 + * 1.1037 + * Indices into aRadii are the NS_CORNER_* constants in nsStyleConsts.h 1.1038 + * 1.1039 + * Note that InsetBorderRadii is lossy, since it can turn nonzero 1.1040 + * radii into zero, and OutsetBorderRadii does not inflate zero radii. 1.1041 + * Therefore, callers should always inset or outset directly from the 1.1042 + * original value coming from style. 1.1043 + */ 1.1044 + static void InsetBorderRadii(nscoord aRadii[8], const nsMargin &aOffsets); 1.1045 + static void OutsetBorderRadii(nscoord aRadii[8], const nsMargin &aOffsets); 1.1046 + 1.1047 + /** 1.1048 + * Fill in border radii for this frame. Return whether any are 1.1049 + * nonzero. 1.1050 + * 1.1051 + * Indices into aRadii are the NS_CORNER_* constants in nsStyleConsts.h 1.1052 + */ 1.1053 + virtual bool GetBorderRadii(nscoord aRadii[8]) const; 1.1054 + 1.1055 + bool GetPaddingBoxBorderRadii(nscoord aRadii[8]) const; 1.1056 + bool GetContentBoxBorderRadii(nscoord aRadii[8]) const; 1.1057 + 1.1058 + /** 1.1059 + * Get the position of the frame's baseline, relative to the top of 1.1060 + * the frame (its top border edge). Only valid when Reflow is not 1.1061 + * needed. 1.1062 + */ 1.1063 + virtual nscoord GetBaseline() const = 0; 1.1064 + 1.1065 + /** 1.1066 + * Get the position of the baseline on which the caret needs to be placed, 1.1067 + * relative to the top of the frame. This is mostly needed for frames 1.1068 + * which return a baseline from GetBaseline which is not useful for 1.1069 + * caret positioning. 1.1070 + */ 1.1071 + virtual nscoord GetCaretBaseline() const { 1.1072 + return GetBaseline(); 1.1073 + } 1.1074 + 1.1075 + /** 1.1076 + * Get the specified child list. 1.1077 + * 1.1078 + * @param aListID identifies the requested child list. 1.1079 + * @return the child list. If the requested list is unsupported by this 1.1080 + * frame type, an empty list will be returned. 1.1081 + */ 1.1082 + virtual const nsFrameList& GetChildList(ChildListID aListID) const = 0; 1.1083 + const nsFrameList& PrincipalChildList() { return GetChildList(kPrincipalList); } 1.1084 + virtual void GetChildLists(nsTArray<ChildList>* aLists) const = 0; 1.1085 + 1.1086 + /** 1.1087 + * Gets the child lists for this frame, including 1.1088 + * ones belong to a child document. 1.1089 + */ 1.1090 + void GetCrossDocChildLists(nsTArray<ChildList>* aLists); 1.1091 + 1.1092 + // XXXbz this method should go away 1.1093 + nsIFrame* GetFirstChild(ChildListID aListID) const { 1.1094 + return GetChildList(aListID).FirstChild(); 1.1095 + } 1.1096 + // XXXmats this method should also go away then 1.1097 + nsIFrame* GetLastChild(ChildListID aListID) const { 1.1098 + return GetChildList(aListID).LastChild(); 1.1099 + } 1.1100 + nsIFrame* GetFirstPrincipalChild() const { 1.1101 + return GetFirstChild(kPrincipalList); 1.1102 + } 1.1103 + 1.1104 + // The individual concrete child lists. 1.1105 + static const ChildListID kPrincipalList = mozilla::layout::kPrincipalList; 1.1106 + static const ChildListID kAbsoluteList = mozilla::layout::kAbsoluteList; 1.1107 + static const ChildListID kBulletList = mozilla::layout::kBulletList; 1.1108 + static const ChildListID kCaptionList = mozilla::layout::kCaptionList; 1.1109 + static const ChildListID kColGroupList = mozilla::layout::kColGroupList; 1.1110 + static const ChildListID kExcessOverflowContainersList = mozilla::layout::kExcessOverflowContainersList; 1.1111 + static const ChildListID kFixedList = mozilla::layout::kFixedList; 1.1112 + static const ChildListID kFloatList = mozilla::layout::kFloatList; 1.1113 + static const ChildListID kOverflowContainersList = mozilla::layout::kOverflowContainersList; 1.1114 + static const ChildListID kOverflowList = mozilla::layout::kOverflowList; 1.1115 + static const ChildListID kOverflowOutOfFlowList = mozilla::layout::kOverflowOutOfFlowList; 1.1116 + static const ChildListID kPopupList = mozilla::layout::kPopupList; 1.1117 + static const ChildListID kPushedFloatsList = mozilla::layout::kPushedFloatsList; 1.1118 + static const ChildListID kSelectPopupList = mozilla::layout::kSelectPopupList; 1.1119 + // A special alias for kPrincipalList that do not request reflow. 1.1120 + static const ChildListID kNoReflowPrincipalList = mozilla::layout::kNoReflowPrincipalList; 1.1121 + 1.1122 + /** 1.1123 + * Child frames are linked together in a doubly-linked list 1.1124 + */ 1.1125 + nsIFrame* GetNextSibling() const { return mNextSibling; } 1.1126 + void SetNextSibling(nsIFrame* aNextSibling) { 1.1127 + NS_ASSERTION(this != aNextSibling, "Creating a circular frame list, this is very bad."); 1.1128 + if (mNextSibling && mNextSibling->GetPrevSibling() == this) { 1.1129 + mNextSibling->mPrevSibling = nullptr; 1.1130 + } 1.1131 + mNextSibling = aNextSibling; 1.1132 + if (mNextSibling) { 1.1133 + mNextSibling->mPrevSibling = this; 1.1134 + } 1.1135 + } 1.1136 + 1.1137 + nsIFrame* GetPrevSibling() const { return mPrevSibling; } 1.1138 + 1.1139 + /** 1.1140 + * Builds the display lists for the content represented by this frame 1.1141 + * and its descendants. The background+borders of this element must 1.1142 + * be added first, before any other content. 1.1143 + * 1.1144 + * This should only be called by methods in nsFrame. Instead of calling this 1.1145 + * directly, call either BuildDisplayListForStackingContext or 1.1146 + * BuildDisplayListForChild. 1.1147 + * 1.1148 + * See nsDisplayList.h for more information about display lists. 1.1149 + * 1.1150 + * @param aDirtyRect content outside this rectangle can be ignored; the 1.1151 + * rectangle is in frame coordinates 1.1152 + */ 1.1153 + virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder, 1.1154 + const nsRect& aDirtyRect, 1.1155 + const nsDisplayListSet& aLists) {} 1.1156 + /** 1.1157 + * Displays the caret onto the given display list builder. The caret is 1.1158 + * painted on top of the rest of the display list items. 1.1159 + * 1.1160 + * @param aDirtyRect is the dirty rectangle that we're repainting. 1.1161 + */ 1.1162 + void DisplayCaret(nsDisplayListBuilder* aBuilder, 1.1163 + const nsRect& aDirtyRect, 1.1164 + nsDisplayList* aList); 1.1165 + 1.1166 + /** 1.1167 + * Get the preferred caret color at the offset. 1.1168 + * 1.1169 + * @param aOffset is offset of the content. 1.1170 + */ 1.1171 + virtual nscolor GetCaretColorAt(int32_t aOffset); 1.1172 + 1.1173 + 1.1174 + bool IsThemed(nsITheme::Transparency* aTransparencyState = nullptr) const { 1.1175 + return IsThemed(StyleDisplay(), aTransparencyState); 1.1176 + } 1.1177 + bool IsThemed(const nsStyleDisplay* aDisp, 1.1178 + nsITheme::Transparency* aTransparencyState = nullptr) const { 1.1179 + nsIFrame* mutable_this = const_cast<nsIFrame*>(this); 1.1180 + if (!aDisp->mAppearance) 1.1181 + return false; 1.1182 + nsPresContext* pc = PresContext(); 1.1183 + nsITheme *theme = pc->GetTheme(); 1.1184 + if(!theme || 1.1185 + !theme->ThemeSupportsWidget(pc, mutable_this, aDisp->mAppearance)) 1.1186 + return false; 1.1187 + if (aTransparencyState) { 1.1188 + *aTransparencyState = 1.1189 + theme->GetWidgetTransparency(mutable_this, aDisp->mAppearance); 1.1190 + } 1.1191 + return true; 1.1192 + } 1.1193 + 1.1194 + /** 1.1195 + * Builds a display list for the content represented by this frame, 1.1196 + * treating this frame as the root of a stacking context. 1.1197 + * @param aDirtyRect content outside this rectangle can be ignored; the 1.1198 + * rectangle is in frame coordinates 1.1199 + */ 1.1200 + void BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder, 1.1201 + const nsRect& aDirtyRect, 1.1202 + nsDisplayList* aList); 1.1203 + 1.1204 + enum { 1.1205 + DISPLAY_CHILD_FORCE_PSEUDO_STACKING_CONTEXT = 0x01, 1.1206 + DISPLAY_CHILD_FORCE_STACKING_CONTEXT = 0x02, 1.1207 + DISPLAY_CHILD_INLINE = 0x04 1.1208 + }; 1.1209 + /** 1.1210 + * Adjusts aDirtyRect for the child's offset, checks that the dirty rect 1.1211 + * actually intersects the child (or its descendants), calls BuildDisplayList 1.1212 + * on the child if necessary, and puts things in the right lists if the child 1.1213 + * is positioned. 1.1214 + * 1.1215 + * @param aFlags combination of DISPLAY_CHILD_FORCE_PSEUDO_STACKING_CONTEXT, 1.1216 + * DISPLAY_CHILD_FORCE_STACKING_CONTEXT and DISPLAY_CHILD_INLINE 1.1217 + */ 1.1218 + void BuildDisplayListForChild(nsDisplayListBuilder* aBuilder, 1.1219 + nsIFrame* aChild, 1.1220 + const nsRect& aDirtyRect, 1.1221 + const nsDisplayListSet& aLists, 1.1222 + uint32_t aFlags = 0); 1.1223 + 1.1224 + /** 1.1225 + * Does this frame need a view? 1.1226 + */ 1.1227 + virtual bool NeedsView() { return false; } 1.1228 + 1.1229 + /** 1.1230 + * Returns true if this frame is transformed (e.g. has CSS or SVG transforms) 1.1231 + * or if its parent is an SVG frame that has children-only transforms (e.g. 1.1232 + * an SVG viewBox attribute). 1.1233 + */ 1.1234 + bool IsTransformed() const; 1.1235 + 1.1236 + /** 1.1237 + * Returns true if the frame is translucent for the purposes of creating a 1.1238 + * stacking context. 1.1239 + */ 1.1240 + bool HasOpacity() const 1.1241 + { 1.1242 + return HasOpacityInternal(1.0f); 1.1243 + } 1.1244 + /** 1.1245 + * Returns true if the frame is translucent for display purposes. 1.1246 + */ 1.1247 + bool HasVisualOpacity() const 1.1248 + { 1.1249 + // Treat an opacity value of 0.99 and above as opaque. This is an 1.1250 + // optimization aimed at Web content which use opacity:0.99 as a hint for 1.1251 + // creating a stacking context only. 1.1252 + return HasOpacityInternal(0.99f); 1.1253 + } 1.1254 + 1.1255 + /** 1.1256 + * Return true if this frame might be using a transform getter. 1.1257 + */ 1.1258 + virtual bool HasTransformGetter() const { return false; } 1.1259 + 1.1260 + /** 1.1261 + * Returns true if this frame is an SVG frame that has SVG transforms applied 1.1262 + * to it, or if its parent frame is an SVG frame that has children-only 1.1263 + * transforms (e.g. an SVG viewBox attribute). 1.1264 + * If aOwnTransforms is non-null and the frame has its own SVG transforms, 1.1265 + * aOwnTransforms will be set to these transforms. If aFromParentTransforms 1.1266 + * is non-null and the frame has an SVG parent with children-only transforms, 1.1267 + * then aFromParentTransforms will be set to these transforms. 1.1268 + */ 1.1269 + virtual bool IsSVGTransformed(Matrix *aOwnTransforms = nullptr, 1.1270 + Matrix *aFromParentTransforms = nullptr) const; 1.1271 + 1.1272 + /** 1.1273 + * Returns whether this frame will attempt to preserve the 3d transforms of its 1.1274 + * children. This requires transform-style: preserve-3d, as well as no clipping 1.1275 + * or svg effects. 1.1276 + */ 1.1277 + bool Preserves3DChildren() const; 1.1278 + 1.1279 + /** 1.1280 + * Returns whether this frame has a parent that Preserves3DChildren() and has 1.1281 + * its own transform (or hidden backface) to be combined with the parent's 1.1282 + * transform. 1.1283 + */ 1.1284 + bool Preserves3D() const; 1.1285 + 1.1286 + bool HasPerspective() const; 1.1287 + 1.1288 + bool ChildrenHavePerspective() const; 1.1289 + 1.1290 + // Calculate the overflow size of all child frames, taking preserve-3d into account 1.1291 + void ComputePreserve3DChildrenOverflow(nsOverflowAreas& aOverflowAreas, const nsRect& aBounds); 1.1292 + 1.1293 + void RecomputePerspectiveChildrenOverflow(const nsStyleContext* aStartStyle, const nsRect* aBounds); 1.1294 + 1.1295 + /** 1.1296 + * Returns the number of ancestors between this and the root of our frame tree 1.1297 + */ 1.1298 + uint32_t GetDepthInFrameTree() { 1.1299 + uint32_t result = 0; 1.1300 + for (nsIFrame* ancestor = GetParent(); ancestor; 1.1301 + ancestor = ancestor->GetParent()) { 1.1302 + result++; 1.1303 + } 1.1304 + return result; 1.1305 + } 1.1306 + 1.1307 + /** 1.1308 + * Event handling of GUI events. 1.1309 + * 1.1310 + * @param aEvent event structure describing the type of event and rge widget 1.1311 + * where the event originated 1.1312 + * The |point| member of this is in the coordinate system of the 1.1313 + * view returned by GetOffsetFromView. 1.1314 + * @param aEventStatus a return value indicating whether the event was handled 1.1315 + * and whether default processing should be done 1.1316 + * 1.1317 + * XXX From a frame's perspective it's unclear what the effect of the event status 1.1318 + * is. Does it cause the event to continue propagating through the frame hierarchy 1.1319 + * or is it just returned to the widgets? 1.1320 + * 1.1321 + * @see WidgetGUIEvent 1.1322 + * @see nsEventStatus 1.1323 + */ 1.1324 + virtual nsresult HandleEvent(nsPresContext* aPresContext, 1.1325 + mozilla::WidgetGUIEvent* aEvent, 1.1326 + nsEventStatus* aEventStatus) = 0; 1.1327 + 1.1328 + virtual nsresult GetContentForEvent(mozilla::WidgetEvent* aEvent, 1.1329 + nsIContent** aContent) = 0; 1.1330 + 1.1331 + // This structure keeps track of the content node and offsets associated with 1.1332 + // a point; there is a primary and a secondary offset associated with any 1.1333 + // point. The primary and secondary offsets differ when the point is over a 1.1334 + // non-text object. The primary offset is the expected position of the 1.1335 + // cursor calculated from a point; the secondary offset, when it is different, 1.1336 + // indicates that the point is in the boundaries of some selectable object. 1.1337 + // Note that the primary offset can be after the secondary offset; for places 1.1338 + // that need the beginning and end of the object, the StartOffset and 1.1339 + // EndOffset helpers can be used. 1.1340 + struct MOZ_STACK_CLASS ContentOffsets { 1.1341 + ContentOffsets(); 1.1342 + ContentOffsets(const ContentOffsets&); 1.1343 + ~ContentOffsets(); 1.1344 + nsCOMPtr<nsIContent> content; 1.1345 + bool IsNull() { return !content; } 1.1346 + int32_t offset; 1.1347 + int32_t secondaryOffset; 1.1348 + // Helpers for places that need the ends of the offsets and expect them in 1.1349 + // numerical order, as opposed to wanting the primary and secondary offsets 1.1350 + int32_t StartOffset() { return std::min(offset, secondaryOffset); } 1.1351 + int32_t EndOffset() { return std::max(offset, secondaryOffset); } 1.1352 + // This boolean indicates whether the associated content is before or after 1.1353 + // the offset; the most visible use is to allow the caret to know which line 1.1354 + // to display on. 1.1355 + bool associateWithNext; 1.1356 + }; 1.1357 + enum { 1.1358 + IGNORE_SELECTION_STYLE = 0x01, 1.1359 + // Treat visibility:hidden frames as non-selectable 1.1360 + SKIP_HIDDEN = 0x02 1.1361 + }; 1.1362 + /** 1.1363 + * This function calculates the content offsets for selection relative to 1.1364 + * a point. Note that this should generally only be callled on the event 1.1365 + * frame associated with an event because this function does not account 1.1366 + * for frame lists other than the primary one. 1.1367 + * @param aPoint point relative to this frame 1.1368 + */ 1.1369 + ContentOffsets GetContentOffsetsFromPoint(nsPoint aPoint, 1.1370 + uint32_t aFlags = 0); 1.1371 + 1.1372 + virtual ContentOffsets GetContentOffsetsFromPointExternal(nsPoint aPoint, 1.1373 + uint32_t aFlags = 0) 1.1374 + { return GetContentOffsetsFromPoint(aPoint, aFlags); } 1.1375 + 1.1376 + /** 1.1377 + * Ensure that aImage gets notifed when the underlying image request loads 1.1378 + * or animates. 1.1379 + */ 1.1380 + void AssociateImage(const nsStyleImage& aImage, nsPresContext* aPresContext); 1.1381 + 1.1382 + /** 1.1383 + * This structure holds information about a cursor. mContainer represents a 1.1384 + * loaded image that should be preferred. If it is not possible to use it, or 1.1385 + * if it is null, mCursor should be used. 1.1386 + */ 1.1387 + struct MOZ_STACK_CLASS Cursor { 1.1388 + nsCOMPtr<imgIContainer> mContainer; 1.1389 + int32_t mCursor; 1.1390 + bool mHaveHotspot; 1.1391 + float mHotspotX, mHotspotY; 1.1392 + }; 1.1393 + /** 1.1394 + * Get the cursor for a given frame. 1.1395 + */ 1.1396 + virtual nsresult GetCursor(const nsPoint& aPoint, 1.1397 + Cursor& aCursor) = 0; 1.1398 + 1.1399 + /** 1.1400 + * Get a point (in the frame's coordinate space) given an offset into 1.1401 + * the content. This point should be on the baseline of text with 1.1402 + * the correct horizontal offset 1.1403 + */ 1.1404 + virtual nsresult GetPointFromOffset(int32_t inOffset, 1.1405 + nsPoint* outPoint) = 0; 1.1406 + 1.1407 + /** 1.1408 + * Get the child frame of this frame which contains the given 1.1409 + * content offset. outChildFrame may be this frame, or nullptr on return. 1.1410 + * outContentOffset returns the content offset relative to the start 1.1411 + * of the returned node. You can also pass a hint which tells the method 1.1412 + * to stick to the end of the first found frame or the beginning of the 1.1413 + * next in case the offset falls on a boundary. 1.1414 + */ 1.1415 + virtual nsresult GetChildFrameContainingOffset(int32_t inContentOffset, 1.1416 + bool inHint,//false stick left 1.1417 + int32_t* outFrameContentOffset, 1.1418 + nsIFrame** outChildFrame) = 0; 1.1419 + 1.1420 + /** 1.1421 + * Get the current frame-state value for this frame. aResult is 1.1422 + * filled in with the state bits. 1.1423 + */ 1.1424 + nsFrameState GetStateBits() const { return mState; } 1.1425 + 1.1426 + /** 1.1427 + * Update the current frame-state value for this frame. 1.1428 + */ 1.1429 + void AddStateBits(nsFrameState aBits) { mState |= aBits; } 1.1430 + void RemoveStateBits(nsFrameState aBits) { mState &= ~aBits; } 1.1431 + 1.1432 + /** 1.1433 + * Checks if the current frame-state includes all of the listed bits 1.1434 + */ 1.1435 + bool HasAllStateBits(nsFrameState aBits) const 1.1436 + { 1.1437 + return (mState & aBits) == aBits; 1.1438 + } 1.1439 + 1.1440 + /** 1.1441 + * Checks if the current frame-state includes any of the listed bits 1.1442 + */ 1.1443 + bool HasAnyStateBits(nsFrameState aBits) const 1.1444 + { 1.1445 + return mState & aBits; 1.1446 + } 1.1447 + 1.1448 + /** 1.1449 + * This call is invoked on the primary frame for a character data content 1.1450 + * node, when it is changed in the content tree. 1.1451 + */ 1.1452 + virtual nsresult CharacterDataChanged(CharacterDataChangeInfo* aInfo) = 0; 1.1453 + 1.1454 + /** 1.1455 + * This call is invoked when the value of a content objects's attribute 1.1456 + * is changed. 1.1457 + * The first frame that maps that content is asked to deal 1.1458 + * with the change by doing whatever is appropriate. 1.1459 + * 1.1460 + * @param aNameSpaceID the namespace of the attribute 1.1461 + * @param aAttribute the atom name of the attribute 1.1462 + * @param aModType Whether or not the attribute was added, changed, or removed. 1.1463 + * The constants are defined in nsIDOMMutationEvent.h. 1.1464 + */ 1.1465 + virtual nsresult AttributeChanged(int32_t aNameSpaceID, 1.1466 + nsIAtom* aAttribute, 1.1467 + int32_t aModType) = 0; 1.1468 + 1.1469 + /** 1.1470 + * When the content states of a content object change, this method is invoked 1.1471 + * on the primary frame of that content object. 1.1472 + * 1.1473 + * @param aStates the changed states 1.1474 + */ 1.1475 + virtual void ContentStatesChanged(mozilla::EventStates aStates); 1.1476 + 1.1477 + /** 1.1478 + * Return how your frame can be split. 1.1479 + */ 1.1480 + virtual nsSplittableType GetSplittableType() const = 0; 1.1481 + 1.1482 + /** 1.1483 + * Continuation member functions 1.1484 + */ 1.1485 + virtual nsIFrame* GetPrevContinuation() const = 0; 1.1486 + virtual void SetPrevContinuation(nsIFrame*) = 0; 1.1487 + virtual nsIFrame* GetNextContinuation() const = 0; 1.1488 + virtual void SetNextContinuation(nsIFrame*) = 0; 1.1489 + virtual nsIFrame* FirstContinuation() const { 1.1490 + return const_cast<nsIFrame*>(this); 1.1491 + } 1.1492 + virtual nsIFrame* LastContinuation() const { 1.1493 + return const_cast<nsIFrame*>(this); 1.1494 + } 1.1495 + 1.1496 + /** 1.1497 + * GetTailContinuation gets the last non-overflow-container continuation 1.1498 + * in the continuation chain, i.e. where the next sibling element 1.1499 + * should attach). 1.1500 + */ 1.1501 + nsIFrame* GetTailContinuation(); 1.1502 + 1.1503 + /** 1.1504 + * Flow member functions 1.1505 + */ 1.1506 + virtual nsIFrame* GetPrevInFlowVirtual() const = 0; 1.1507 + nsIFrame* GetPrevInFlow() const { return GetPrevInFlowVirtual(); } 1.1508 + virtual void SetPrevInFlow(nsIFrame*) = 0; 1.1509 + 1.1510 + virtual nsIFrame* GetNextInFlowVirtual() const = 0; 1.1511 + nsIFrame* GetNextInFlow() const { return GetNextInFlowVirtual(); } 1.1512 + virtual void SetNextInFlow(nsIFrame*) = 0; 1.1513 + 1.1514 + /** 1.1515 + * Return the first frame in our current flow. 1.1516 + */ 1.1517 + virtual nsIFrame* FirstInFlow() const { 1.1518 + return const_cast<nsIFrame*>(this); 1.1519 + } 1.1520 + 1.1521 + /** 1.1522 + * Return the last frame in our current flow. 1.1523 + */ 1.1524 + virtual nsIFrame* LastInFlow() const { 1.1525 + return const_cast<nsIFrame*>(this); 1.1526 + } 1.1527 + 1.1528 + 1.1529 + /** 1.1530 + * Mark any stored intrinsic width information as dirty (requiring 1.1531 + * re-calculation). Note that this should generally not be called 1.1532 + * directly; nsPresShell::FrameNeedsReflow will call it instead. 1.1533 + */ 1.1534 + virtual void MarkIntrinsicWidthsDirty() = 0; 1.1535 + 1.1536 + /** 1.1537 + * Get the intrinsic minimum width of the frame. This must be less 1.1538 + * than or equal to the intrinsic width. 1.1539 + * 1.1540 + * This is *not* affected by the CSS 'min-width', 'width', and 1.1541 + * 'max-width' properties on this frame, but it is affected by the 1.1542 + * values of those properties on this frame's descendants. (It may be 1.1543 + * called during computation of the values of those properties, so it 1.1544 + * cannot depend on any values in the nsStylePosition for this frame.) 1.1545 + * 1.1546 + * The value returned should **NOT** include the space required for 1.1547 + * padding and border. 1.1548 + * 1.1549 + * Note that many frames will cache the result of this function call 1.1550 + * unless MarkIntrinsicWidthsDirty is called. 1.1551 + * 1.1552 + * It is not acceptable for a frame to mark itself dirty when this 1.1553 + * method is called. 1.1554 + * 1.1555 + * This method must not return a negative value. 1.1556 + */ 1.1557 + virtual nscoord GetMinWidth(nsRenderingContext *aRenderingContext) = 0; 1.1558 + 1.1559 + /** 1.1560 + * Get the intrinsic width of the frame. This must be greater than or 1.1561 + * equal to the intrinsic minimum width. 1.1562 + * 1.1563 + * Otherwise, all the comments for |GetMinWidth| above apply. 1.1564 + */ 1.1565 + virtual nscoord GetPrefWidth(nsRenderingContext *aRenderingContext) = 0; 1.1566 + 1.1567 + /** 1.1568 + * |InlineIntrinsicWidth| represents the intrinsic width information 1.1569 + * in inline layout. Code that determines the intrinsic width of a 1.1570 + * region of inline layout accumulates the result into this structure. 1.1571 + * This pattern is needed because we need to maintain state 1.1572 + * information about whitespace (for both collapsing and trimming). 1.1573 + */ 1.1574 + struct InlineIntrinsicWidthData { 1.1575 + InlineIntrinsicWidthData() 1.1576 + : line(nullptr) 1.1577 + , lineContainer(nullptr) 1.1578 + , prevLines(0) 1.1579 + , currentLine(0) 1.1580 + , skipWhitespace(true) 1.1581 + , trailingWhitespace(0) 1.1582 + {} 1.1583 + 1.1584 + // The line. This may be null if the inlines are not associated with 1.1585 + // a block or if we just don't know the line. 1.1586 + const nsLineList_iterator* line; 1.1587 + 1.1588 + // The line container. 1.1589 + nsIFrame* lineContainer; 1.1590 + 1.1591 + // The maximum intrinsic width for all previous lines. 1.1592 + nscoord prevLines; 1.1593 + 1.1594 + // The maximum intrinsic width for the current line. At a line 1.1595 + // break (mandatory for preferred width; allowed for minimum width), 1.1596 + // the caller should call |Break()|. 1.1597 + nscoord currentLine; 1.1598 + 1.1599 + // True if initial collapsable whitespace should be skipped. This 1.1600 + // should be true at the beginning of a block, after hard breaks 1.1601 + // and when the last text ended with whitespace. 1.1602 + bool skipWhitespace; 1.1603 + 1.1604 + // This contains the width of the trimmable whitespace at the end of 1.1605 + // |currentLine|; it is zero if there is no such whitespace. 1.1606 + nscoord trailingWhitespace; 1.1607 + 1.1608 + // Floats encountered in the lines. 1.1609 + class FloatInfo { 1.1610 + public: 1.1611 + FloatInfo(const nsIFrame* aFrame, nscoord aWidth) 1.1612 + : mFrame(aFrame), mWidth(aWidth) 1.1613 + { } 1.1614 + const nsIFrame* Frame() const { return mFrame; } 1.1615 + nscoord Width() const { return mWidth; } 1.1616 + 1.1617 + private: 1.1618 + const nsIFrame* mFrame; 1.1619 + nscoord mWidth; 1.1620 + }; 1.1621 + 1.1622 + nsTArray<FloatInfo> floats; 1.1623 + }; 1.1624 + 1.1625 + struct InlineMinWidthData : public InlineIntrinsicWidthData { 1.1626 + InlineMinWidthData() 1.1627 + : trailingTextFrame(nullptr) 1.1628 + , atStartOfLine(true) 1.1629 + {} 1.1630 + 1.1631 + // We need to distinguish forced and optional breaks for cases where the 1.1632 + // current line total is negative. When it is, we need to ignore 1.1633 + // optional breaks to prevent min-width from ending up bigger than 1.1634 + // pref-width. 1.1635 + void ForceBreak(nsRenderingContext *aRenderingContext); 1.1636 + 1.1637 + // If the break here is actually taken, aHyphenWidth must be added to the 1.1638 + // width of the current line. 1.1639 + void OptionallyBreak(nsRenderingContext *aRenderingContext, 1.1640 + nscoord aHyphenWidth = 0); 1.1641 + 1.1642 + // The last text frame processed so far in the current line, when 1.1643 + // the last characters in that text frame are relevant for line 1.1644 + // break opportunities. 1.1645 + nsIFrame *trailingTextFrame; 1.1646 + 1.1647 + // Whether we're currently at the start of the line. If we are, we 1.1648 + // can't break (for example, between the text-indent and the first 1.1649 + // word). 1.1650 + bool atStartOfLine; 1.1651 + }; 1.1652 + 1.1653 + struct InlinePrefWidthData : public InlineIntrinsicWidthData { 1.1654 + void ForceBreak(nsRenderingContext *aRenderingContext); 1.1655 + }; 1.1656 + 1.1657 + /** 1.1658 + * Add the intrinsic minimum width of a frame in a way suitable for 1.1659 + * use in inline layout to an |InlineIntrinsicWidthData| object that 1.1660 + * represents the intrinsic width information of all the previous 1.1661 + * frames in the inline layout region. 1.1662 + * 1.1663 + * All *allowed* breakpoints within the frame determine what counts as 1.1664 + * a line for the |InlineIntrinsicWidthData|. This means that 1.1665 + * |aData->trailingWhitespace| will always be zero (unlike for 1.1666 + * AddInlinePrefWidth). 1.1667 + * 1.1668 + * All the comments for |GetMinWidth| apply, except that this function 1.1669 + * is responsible for adding padding, border, and margin and for 1.1670 + * considering the effects of 'width', 'min-width', and 'max-width'. 1.1671 + * 1.1672 + * This may be called on any frame. Frames that do not participate in 1.1673 + * line breaking can inherit the default implementation on nsFrame, 1.1674 + * which calls |GetMinWidth|. 1.1675 + */ 1.1676 + virtual void 1.1677 + AddInlineMinWidth(nsRenderingContext *aRenderingContext, 1.1678 + InlineMinWidthData *aData) = 0; 1.1679 + 1.1680 + /** 1.1681 + * Add the intrinsic preferred width of a frame in a way suitable for 1.1682 + * use in inline layout to an |InlineIntrinsicWidthData| object that 1.1683 + * represents the intrinsic width information of all the previous 1.1684 + * frames in the inline layout region. 1.1685 + * 1.1686 + * All the comments for |AddInlineMinWidth| and |GetPrefWidth| apply, 1.1687 + * except that this fills in an |InlineIntrinsicWidthData| structure 1.1688 + * based on using all *mandatory* breakpoints within the frame. 1.1689 + */ 1.1690 + virtual void 1.1691 + AddInlinePrefWidth(nsRenderingContext *aRenderingContext, 1.1692 + InlinePrefWidthData *aData) = 0; 1.1693 + 1.1694 + /** 1.1695 + * Return the horizontal components of padding, border, and margin 1.1696 + * that contribute to the intrinsic width that applies to the parent. 1.1697 + */ 1.1698 + struct IntrinsicWidthOffsetData { 1.1699 + nscoord hPadding, hBorder, hMargin; 1.1700 + float hPctPadding, hPctMargin; 1.1701 + 1.1702 + IntrinsicWidthOffsetData() 1.1703 + : hPadding(0), hBorder(0), hMargin(0) 1.1704 + , hPctPadding(0.0f), hPctMargin(0.0f) 1.1705 + {} 1.1706 + }; 1.1707 + virtual IntrinsicWidthOffsetData 1.1708 + IntrinsicWidthOffsets(nsRenderingContext* aRenderingContext) = 0; 1.1709 + 1.1710 + virtual mozilla::IntrinsicSize GetIntrinsicSize() = 0; 1.1711 + 1.1712 + /* 1.1713 + * Get the intrinsic ratio of this element, or nsSize(0,0) if it has 1.1714 + * no intrinsic ratio. The intrinsic ratio is the ratio of the 1.1715 + * height/width of a box with an intrinsic size or the intrinsic 1.1716 + * aspect ratio of a scalable vector image without an intrinsic size. 1.1717 + * 1.1718 + * Either one of the sides may be zero, indicating a zero or infinite 1.1719 + * ratio. 1.1720 + */ 1.1721 + virtual nsSize GetIntrinsicRatio() = 0; 1.1722 + 1.1723 + /** 1.1724 + * Bit-flags to pass to ComputeSize in |aFlags| parameter. 1.1725 + */ 1.1726 + enum { 1.1727 + /* Set if the frame is in a context where non-replaced blocks should 1.1728 + * shrink-wrap (e.g., it's floating, absolutely positioned, or 1.1729 + * inline-block). */ 1.1730 + eShrinkWrap = 1 << 0, 1.1731 + /* Set if we'd like to compute our 'auto' height, regardless of our actual 1.1732 + * computed value of 'height'. (e.g. to get an intrinsic height for flex 1.1733 + * items with "min-height: auto" to use during flexbox layout.) */ 1.1734 + eUseAutoHeight = 1 << 1 1.1735 + }; 1.1736 + 1.1737 + /** 1.1738 + * Compute the size that a frame will occupy. Called while 1.1739 + * constructing the nsHTMLReflowState to be used to Reflow the frame, 1.1740 + * in order to fill its mComputedWidth and mComputedHeight member 1.1741 + * variables. 1.1742 + * 1.1743 + * The |height| member of the return value may be 1.1744 + * NS_UNCONSTRAINEDSIZE, but the |width| member must not be. 1.1745 + * 1.1746 + * Note that the reason that border and padding need to be passed 1.1747 + * separately is so that the 'box-sizing' property can be handled. 1.1748 + * Thus aMargin includes absolute positioning offsets as well. 1.1749 + * 1.1750 + * @param aCBSize The size of the element's containing block. (Well, 1.1751 + * the |height| component isn't really.) 1.1752 + * @param aAvailableWidth The available width for 'auto' widths. 1.1753 + * This is usually the same as aCBSize.width, 1.1754 + * but differs in cases such as block 1.1755 + * formatting context roots next to floats, or 1.1756 + * in some cases of float reflow in quirks 1.1757 + * mode. 1.1758 + * @param aMargin The sum of the vertical / horizontal margins 1.1759 + * ***AND*** absolute positioning offsets (top, right, 1.1760 + * bottom, left) of the frame, including actual values 1.1761 + * resulting from percentages and from the 1.1762 + * "hypothetical box" for absolute positioning, but 1.1763 + * not including actual values resulting from 'auto' 1.1764 + * margins or ignored 'auto' values in absolute 1.1765 + * positioning. 1.1766 + * @param aBorder The sum of the vertical / horizontal border widths 1.1767 + * of the frame. 1.1768 + * @param aPadding The sum of the vertical / horizontal margins of 1.1769 + * the frame, including actual values resulting from 1.1770 + * percentages. 1.1771 + * @param aFlags Flags to further customize behavior (definitions above). 1.1772 + */ 1.1773 + virtual nsSize ComputeSize(nsRenderingContext *aRenderingContext, 1.1774 + nsSize aCBSize, nscoord aAvailableWidth, 1.1775 + nsSize aMargin, nsSize aBorder, nsSize aPadding, 1.1776 + uint32_t aFlags) = 0; 1.1777 + 1.1778 + /** 1.1779 + * Compute a tight bounding rectangle for the frame. This is a rectangle 1.1780 + * that encloses the pixels that are actually drawn. We're allowed to be 1.1781 + * conservative and currently we don't try very hard. The rectangle is 1.1782 + * in appunits and relative to the origin of this frame. 1.1783 + * 1.1784 + * This probably only needs to include frame bounds, glyph bounds, and 1.1785 + * text decorations, but today it sometimes includes other things that 1.1786 + * contribute to visual overflow. 1.1787 + * 1.1788 + * @param aContext a rendering context that can be used if we need 1.1789 + * to do measurement 1.1790 + */ 1.1791 + virtual nsRect ComputeTightBounds(gfxContext* aContext) const; 1.1792 + 1.1793 + /** 1.1794 + * This function is similar to GetPrefWidth and ComputeTightBounds: it 1.1795 + * computes the left and right coordinates of a preferred tight bounding 1.1796 + * rectangle for the frame. This is a rectangle that would enclose the pixels 1.1797 + * that are drawn if we lay out the element without taking any optional line 1.1798 + * breaks. The rectangle is in appunits and relative to the origin of this 1.1799 + * frame. Currently, this function is only implemented for nsBlockFrame and 1.1800 + * nsTextFrame and is used to determine intrinsic widths of MathML token 1.1801 + * elements. 1.1802 + 1.1803 + * @param aContext a rendering context that can be used if we need 1.1804 + * to do measurement 1.1805 + * @param aX computed left coordinate of the tight bounding rectangle 1.1806 + * @param aXMost computed intrinsic width of the tight bounding rectangle 1.1807 + * 1.1808 + */ 1.1809 + virtual nsresult GetPrefWidthTightBounds(nsRenderingContext* aContext, 1.1810 + nscoord* aX, 1.1811 + nscoord* aXMost); 1.1812 + 1.1813 + /** 1.1814 + * Pre-reflow hook. Before a frame is reflowed this method will be called. 1.1815 + * This call will always be invoked at least once before a subsequent Reflow 1.1816 + * and DidReflow call. It may be called more than once, In general you will 1.1817 + * receive on WillReflow notification before each Reflow request. 1.1818 + * 1.1819 + * XXX Is this really the semantics we want? Because we have the NS_FRAME_IN_REFLOW 1.1820 + * bit we can ensure we don't call it more than once... 1.1821 + */ 1.1822 + virtual nsresult WillReflow(nsPresContext* aPresContext) = 0; 1.1823 + 1.1824 + /** 1.1825 + * The frame is given an available size and asked for its desired 1.1826 + * size. This is the frame's opportunity to reflow its children. 1.1827 + * 1.1828 + * If the frame has the NS_FRAME_IS_DIRTY bit set then it is 1.1829 + * responsible for completely reflowing itself and all of its 1.1830 + * descendants. 1.1831 + * 1.1832 + * Otherwise, if the frame has the NS_FRAME_HAS_DIRTY_CHILDREN bit 1.1833 + * set, then it is responsible for reflowing at least those 1.1834 + * children that have NS_FRAME_HAS_DIRTY_CHILDREN or NS_FRAME_IS_DIRTY 1.1835 + * set. 1.1836 + * 1.1837 + * If a difference in available size from the previous reflow causes 1.1838 + * the frame's size to change, it should reflow descendants as needed. 1.1839 + * 1.1840 + * @param aReflowMetrics <i>out</i> parameter where you should return the 1.1841 + * desired size and ascent/descent info. You should include any 1.1842 + * space you want for border/padding in the desired size you return. 1.1843 + * 1.1844 + * It's okay to return a desired size that exceeds the avail 1.1845 + * size if that's the smallest you can be, i.e. it's your 1.1846 + * minimum size. 1.1847 + * 1.1848 + * For an incremental reflow you are responsible for invalidating 1.1849 + * any area within your frame that needs repainting (including 1.1850 + * borders). If your new desired size is different than your current 1.1851 + * size, then your parent frame is responsible for making sure that 1.1852 + * the difference between the two rects is repainted 1.1853 + * 1.1854 + * @param aReflowState information about your reflow including the reason 1.1855 + * for the reflow and the available space in which to lay out. Each 1.1856 + * dimension of the available space can either be constrained or 1.1857 + * unconstrained (a value of NS_UNCONSTRAINEDSIZE). 1.1858 + * 1.1859 + * Note that the available space can be negative. In this case you 1.1860 + * still must return an accurate desired size. If you're a container 1.1861 + * you must <b>always</b> reflow at least one frame regardless of the 1.1862 + * available space 1.1863 + * 1.1864 + * @param aStatus a return value indicating whether the frame is complete 1.1865 + * and whether the next-in-flow is dirty and needs to be reflowed 1.1866 + */ 1.1867 + virtual nsresult Reflow(nsPresContext* aPresContext, 1.1868 + nsHTMLReflowMetrics& aReflowMetrics, 1.1869 + const nsHTMLReflowState& aReflowState, 1.1870 + nsReflowStatus& aStatus) = 0; 1.1871 + 1.1872 + /** 1.1873 + * Post-reflow hook. After a frame is reflowed this method will be called 1.1874 + * informing the frame that this reflow process is complete, and telling the 1.1875 + * frame the status returned by the Reflow member function. 1.1876 + * 1.1877 + * This call may be invoked many times, while NS_FRAME_IN_REFLOW is set, before 1.1878 + * it is finally called once with a NS_FRAME_REFLOW_COMPLETE value. When called 1.1879 + * with a NS_FRAME_REFLOW_COMPLETE value the NS_FRAME_IN_REFLOW bit in the 1.1880 + * frame state will be cleared. 1.1881 + * 1.1882 + * XXX This doesn't make sense. If the frame is reflowed but not complete, then 1.1883 + * the status should be NS_FRAME_NOT_COMPLETE and not NS_FRAME_COMPLETE 1.1884 + * XXX Don't we want the semantics to dictate that we only call this once for 1.1885 + * a given reflow? 1.1886 + */ 1.1887 + virtual nsresult DidReflow(nsPresContext* aPresContext, 1.1888 + const nsHTMLReflowState* aReflowState, 1.1889 + nsDidReflowStatus aStatus) = 0; 1.1890 + 1.1891 + // XXX Maybe these three should be a separate interface? 1.1892 + 1.1893 + /** 1.1894 + * Updates the overflow areas of the frame. This can be called if an 1.1895 + * overflow area of the frame's children has changed without reflowing. 1.1896 + * @return true if either of the overflow areas for this frame have changed. 1.1897 + */ 1.1898 + virtual bool UpdateOverflow() = 0; 1.1899 + 1.1900 + /** 1.1901 + * Helper method used by block reflow to identify runs of text so 1.1902 + * that proper word-breaking can be done. 1.1903 + * 1.1904 + * @return 1.1905 + * true if we can continue a "text run" through the frame. A 1.1906 + * text run is text that should be treated contiguously for line 1.1907 + * and word breaking. 1.1908 + */ 1.1909 + virtual bool CanContinueTextRun() const = 0; 1.1910 + 1.1911 + /** 1.1912 + * Append the rendered text to the passed-in string. 1.1913 + * The appended text will often not contain all the whitespace from source, 1.1914 + * depending on whether the CSS rule "white-space: pre" is active for this frame. 1.1915 + * if aStartOffset + aLength goes past end, or if aLength is not specified 1.1916 + * then use the text up to the string's end. 1.1917 + * Call this on the primary frame for a text node. 1.1918 + * @param aAppendToString String to append text to, or null if text should not be returned 1.1919 + * @param aSkipChars if aSkipIter is non-null, this must also be non-null. 1.1920 + * This gets used as backing data for the iterator so it should outlive the iterator. 1.1921 + * @param aSkipIter Where to fill in the gfxSkipCharsIterator info, or null if not needed by caller 1.1922 + * @param aStartOffset Skipped (rendered text) start offset 1.1923 + * @param aSkippedMaxLength Maximum number of characters to return 1.1924 + * The iterator can be used to map content offsets to offsets in the returned string, or vice versa. 1.1925 + */ 1.1926 + virtual nsresult GetRenderedText(nsAString* aAppendToString = nullptr, 1.1927 + gfxSkipChars* aSkipChars = nullptr, 1.1928 + gfxSkipCharsIterator* aSkipIter = nullptr, 1.1929 + uint32_t aSkippedStartOffset = 0, 1.1930 + uint32_t aSkippedMaxLength = UINT32_MAX) 1.1931 + { return NS_ERROR_NOT_IMPLEMENTED; } 1.1932 + 1.1933 + /** 1.1934 + * Returns true if the frame contains any non-collapsed characters. 1.1935 + * This method is only available for text frames, and it will return false 1.1936 + * for all other frame types. 1.1937 + */ 1.1938 + virtual bool HasAnyNoncollapsedCharacters() 1.1939 + { return false; } 1.1940 + 1.1941 + /** 1.1942 + * Accessor functions to get/set the associated view object 1.1943 + * 1.1944 + * GetView returns non-null if and only if |HasView| returns true. 1.1945 + */ 1.1946 + bool HasView() const { return !!(mState & NS_FRAME_HAS_VIEW); } 1.1947 + nsView* GetView() const; 1.1948 + virtual nsView* GetViewExternal() const; 1.1949 + nsresult SetView(nsView* aView); 1.1950 + 1.1951 + /** 1.1952 + * Find the closest view (on |this| or an ancestor). 1.1953 + * If aOffset is non-null, it will be set to the offset of |this| 1.1954 + * from the returned view. 1.1955 + */ 1.1956 + nsView* GetClosestView(nsPoint* aOffset = nullptr) const; 1.1957 + 1.1958 + /** 1.1959 + * Find the closest ancestor (excluding |this| !) that has a view 1.1960 + */ 1.1961 + nsIFrame* GetAncestorWithView() const; 1.1962 + virtual nsIFrame* GetAncestorWithViewExternal() const; 1.1963 + 1.1964 + /** 1.1965 + * Get the offset between the coordinate systems of |this| and aOther. 1.1966 + * Adding the return value to a point in the coordinate system of |this| 1.1967 + * will transform the point to the coordinate system of aOther. 1.1968 + * 1.1969 + * aOther must be non-null. 1.1970 + * 1.1971 + * This function is fastest when aOther is an ancestor of |this|. 1.1972 + * 1.1973 + * This function _DOES NOT_ work across document boundaries. 1.1974 + * Use this function only when |this| and aOther are in the same document. 1.1975 + * 1.1976 + * NOTE: this actually returns the offset from aOther to |this|, but 1.1977 + * that offset is added to transform _coordinates_ from |this| to 1.1978 + * aOther. 1.1979 + */ 1.1980 + nsPoint GetOffsetTo(const nsIFrame* aOther) const; 1.1981 + virtual nsPoint GetOffsetToExternal(const nsIFrame* aOther) const; 1.1982 + 1.1983 + /** 1.1984 + * Get the offset between the coordinate systems of |this| and aOther 1.1985 + * expressed in appunits per dev pixel of |this|' document. Adding the return 1.1986 + * value to a point that is relative to the origin of |this| will make the 1.1987 + * point relative to the origin of aOther but in the appunits per dev pixel 1.1988 + * ratio of |this|. 1.1989 + * 1.1990 + * aOther must be non-null. 1.1991 + * 1.1992 + * This function is fastest when aOther is an ancestor of |this|. 1.1993 + * 1.1994 + * This function works across document boundaries. 1.1995 + * 1.1996 + * Because this function may cross document boundaries that have different 1.1997 + * app units per dev pixel ratios it needs to be used very carefully. 1.1998 + * 1.1999 + * NOTE: this actually returns the offset from aOther to |this|, but 1.2000 + * that offset is added to transform _coordinates_ from |this| to 1.2001 + * aOther. 1.2002 + */ 1.2003 + nsPoint GetOffsetToCrossDoc(const nsIFrame* aOther) const; 1.2004 + 1.2005 + /** 1.2006 + * Get the screen rect of the frame in pixels. 1.2007 + * @return the pixel rect of the frame in screen coordinates. 1.2008 + */ 1.2009 + nsIntRect GetScreenRect() const; 1.2010 + virtual nsIntRect GetScreenRectExternal() const; 1.2011 + 1.2012 + /** 1.2013 + * Get the screen rect of the frame in app units. 1.2014 + * @return the app unit rect of the frame in screen coordinates. 1.2015 + */ 1.2016 + nsRect GetScreenRectInAppUnits() const; 1.2017 + virtual nsRect GetScreenRectInAppUnitsExternal() const; 1.2018 + 1.2019 + /** 1.2020 + * Returns the offset from this frame to the closest geometric parent that 1.2021 + * has a view. Also returns the containing view or null in case of error 1.2022 + */ 1.2023 + void GetOffsetFromView(nsPoint& aOffset, nsView** aView) const; 1.2024 + 1.2025 + /** 1.2026 + * Returns the nearest widget containing this frame. If this frame has a 1.2027 + * view and the view has a widget, then this frame's widget is 1.2028 + * returned, otherwise this frame's geometric parent is checked 1.2029 + * recursively upwards. 1.2030 + * XXX virtual because gfx callers use it! (themes) 1.2031 + */ 1.2032 + virtual nsIWidget* GetNearestWidget() const; 1.2033 + 1.2034 + /** 1.2035 + * Same as GetNearestWidget() above but uses an outparam to return the offset 1.2036 + * of this frame to the returned widget expressed in appunits of |this| (the 1.2037 + * widget might be in a different document with a different zoom). 1.2038 + */ 1.2039 + virtual nsIWidget* GetNearestWidget(nsPoint& aOffset) const; 1.2040 + 1.2041 + /** 1.2042 + * Get the "type" of the frame. May return nullptr. 1.2043 + * 1.2044 + * @see nsGkAtoms 1.2045 + */ 1.2046 + virtual nsIAtom* GetType() const = 0; 1.2047 + 1.2048 + /** 1.2049 + * Returns a transformation matrix that converts points in this frame's 1.2050 + * coordinate space to points in some ancestor frame's coordinate space. 1.2051 + * The frame decides which ancestor it will use as a reference point. 1.2052 + * If this frame has no ancestor, aOutAncestor will be set to null. 1.2053 + * 1.2054 + * @param aStopAtAncestor don't look further than aStopAtAncestor. If null, 1.2055 + * all ancestors (including across documents) will be traversed. 1.2056 + * @param aOutAncestor [out] The ancestor frame the frame has chosen. If 1.2057 + * this frame has no ancestor, *aOutAncestor will be set to null. If 1.2058 + * this frame is not a root frame, then *aOutAncestor will be in the same 1.2059 + * document as this frame. If this frame IsTransformed(), then *aOutAncestor 1.2060 + * will be the parent frame (if not preserve-3d) or the nearest non-transformed 1.2061 + * ancestor (if preserve-3d). 1.2062 + * @return A gfxMatrix that converts points in this frame's coordinate space 1.2063 + * into points in aOutAncestor's coordinate space. 1.2064 + */ 1.2065 + gfx3DMatrix GetTransformMatrix(const nsIFrame* aStopAtAncestor, 1.2066 + nsIFrame **aOutAncestor); 1.2067 + 1.2068 + /** 1.2069 + * Bit-flags to pass to IsFrameOfType() 1.2070 + */ 1.2071 + enum { 1.2072 + eMathML = 1 << 0, 1.2073 + eSVG = 1 << 1, 1.2074 + eSVGForeignObject = 1 << 2, 1.2075 + eSVGContainer = 1 << 3, 1.2076 + eSVGGeometry = 1 << 4, 1.2077 + eSVGPaintServer = 1 << 5, 1.2078 + eBidiInlineContainer = 1 << 6, 1.2079 + // the frame is for a replaced element, such as an image 1.2080 + eReplaced = 1 << 7, 1.2081 + // Frame that contains a block but looks like a replaced element 1.2082 + // from the outside 1.2083 + eReplacedContainsBlock = 1 << 8, 1.2084 + // A frame that participates in inline reflow, i.e., one that 1.2085 + // requires nsHTMLReflowState::mLineLayout. 1.2086 + eLineParticipant = 1 << 9, 1.2087 + eXULBox = 1 << 10, 1.2088 + eCanContainOverflowContainers = 1 << 11, 1.2089 + eBlockFrame = 1 << 12, 1.2090 + eTablePart = 1 << 13, 1.2091 + // If this bit is set, the frame doesn't allow ignorable whitespace as 1.2092 + // children. For example, the whitespace between <table>\n<tr>\n<td> 1.2093 + // will be excluded during the construction of children. 1.2094 + eExcludesIgnorableWhitespace = 1 << 14, 1.2095 + eSupportsCSSTransforms = 1 << 15, 1.2096 + 1.2097 + // These are to allow nsFrame::Init to assert that IsFrameOfType 1.2098 + // implementations all call the base class method. They are only 1.2099 + // meaningful in DEBUG builds. 1.2100 + eDEBUGAllFrames = 1 << 30, 1.2101 + eDEBUGNoFrames = 1 << 31 1.2102 + }; 1.2103 + 1.2104 + /** 1.2105 + * API for doing a quick check if a frame is of a given 1.2106 + * type. Returns true if the frame matches ALL flags passed in. 1.2107 + * 1.2108 + * Implementations should always override with inline virtual 1.2109 + * functions that call the base class's IsFrameOfType method. 1.2110 + */ 1.2111 + virtual bool IsFrameOfType(uint32_t aFlags) const 1.2112 + { 1.2113 +#ifdef DEBUG 1.2114 + return !(aFlags & ~(nsIFrame::eDEBUGAllFrames | nsIFrame::eSupportsCSSTransforms)); 1.2115 +#else 1.2116 + return !(aFlags & ~nsIFrame::eSupportsCSSTransforms); 1.2117 +#endif 1.2118 + } 1.2119 + 1.2120 + /** 1.2121 + * Returns true if the frame is a block wrapper. 1.2122 + */ 1.2123 + bool IsBlockWrapper() const; 1.2124 + 1.2125 + /** 1.2126 + * Get this frame's CSS containing block. 1.2127 + * 1.2128 + * The algorithm is defined in 1.2129 + * http://www.w3.org/TR/CSS2/visudet.html#containing-block-details. 1.2130 + * 1.2131 + * NOTE: This is guaranteed to return a non-null pointer when invoked on any 1.2132 + * frame other than the root frame. 1.2133 + */ 1.2134 + nsIFrame* GetContainingBlock() const; 1.2135 + 1.2136 + /** 1.2137 + * Is this frame a containing block for floating elements? 1.2138 + * Note that very few frames are, so default to false. 1.2139 + */ 1.2140 + virtual bool IsFloatContainingBlock() const { return false; } 1.2141 + 1.2142 + /** 1.2143 + * Is this a leaf frame? Frames that want the frame constructor to be able 1.2144 + * to construct kids for them should return false, all others should return 1.2145 + * true. Note that returning true here does not mean that the frame _can't_ 1.2146 + * have kids. It could still have kids created via 1.2147 + * nsIAnonymousContentCreator. Returning true indicates that "normal" 1.2148 + * (non-anonymous, XBL-bound, CSS generated content, etc) children should not 1.2149 + * be constructed. 1.2150 + */ 1.2151 + virtual bool IsLeaf() const; 1.2152 + 1.2153 + /** 1.2154 + * Marks all display items created by this frame as needing a repaint, 1.2155 + * and calls SchedulePaint() if requested and one is not already pending. 1.2156 + * 1.2157 + * This includes all display items created by this frame, including 1.2158 + * container types. 1.2159 + * 1.2160 + * @param aDisplayItemKey If specified, only issues an invalidate 1.2161 + * if this frame painted a display item of that type during the 1.2162 + * previous paint. SVG rendering observers are always notified. 1.2163 + */ 1.2164 + virtual void InvalidateFrame(uint32_t aDisplayItemKey = 0); 1.2165 + 1.2166 + /** 1.2167 + * Same as InvalidateFrame(), but only mark a fixed rect as needing 1.2168 + * repainting. 1.2169 + * 1.2170 + * @param aRect The rect to invalidate, relative to the TopLeft of the 1.2171 + * frame's border box. 1.2172 + * @param aDisplayItemKey If specified, only issues an invalidate 1.2173 + * if this frame painted a display item of that type during the 1.2174 + * previous paint. SVG rendering observers are always notified. 1.2175 + */ 1.2176 + virtual void InvalidateFrameWithRect(const nsRect& aRect, uint32_t aDisplayItemKey = 0); 1.2177 + 1.2178 + /** 1.2179 + * Calls InvalidateFrame() on all frames descendant frames (including 1.2180 + * this one). 1.2181 + * 1.2182 + * This function doesn't walk through placeholder frames to invalidate 1.2183 + * the out-of-flow frames. 1.2184 + * 1.2185 + * @param aDisplayItemKey If specified, only issues an invalidate 1.2186 + * if this frame painted a display item of that type during the 1.2187 + * previous paint. SVG rendering observers are always notified. 1.2188 + */ 1.2189 + void InvalidateFrameSubtree(uint32_t aDisplayItemKey = 0); 1.2190 + 1.2191 + /** 1.2192 + * Called when a frame is about to be removed and needs to be invalidated. 1.2193 + * Normally does nothing since DLBI handles removed frames. 1.2194 + */ 1.2195 + virtual void InvalidateFrameForRemoval() {} 1.2196 + 1.2197 + /** 1.2198 + * When HasUserData(frame->LayerIsPrerenderedDataKey()), then the 1.2199 + * entire overflow area of this frame has been rendered in its 1.2200 + * layer(s). 1.2201 + */ 1.2202 + static void* LayerIsPrerenderedDataKey() { 1.2203 + return &sLayerIsPrerenderedDataKey; 1.2204 + } 1.2205 + static uint8_t sLayerIsPrerenderedDataKey; 1.2206 + 1.2207 + /** 1.2208 + * Try to update this frame's transform without invalidating any 1.2209 + * content. Return true iff successful. If unsuccessful, the 1.2210 + * caller is responsible for scheduling an invalidating paint. 1.2211 + * 1.2212 + * If the result is true, aLayerResult will be filled in with the 1.2213 + * transform layer for the frame. 1.2214 + */ 1.2215 + bool TryUpdateTransformOnly(Layer** aLayerResult); 1.2216 + 1.2217 + /** 1.2218 + * Checks if a frame has had InvalidateFrame() called on it since the 1.2219 + * last paint. 1.2220 + * 1.2221 + * If true, then the invalid rect is returned in aRect, with an 1.2222 + * empty rect meaning all pixels drawn by this frame should be 1.2223 + * invalidated. 1.2224 + * If false, aRect is left unchanged. 1.2225 + */ 1.2226 + bool IsInvalid(nsRect& aRect); 1.2227 + 1.2228 + /** 1.2229 + * Check if any frame within the frame subtree (including this frame) 1.2230 + * returns true for IsInvalid(). 1.2231 + */ 1.2232 + bool HasInvalidFrameInSubtree() 1.2233 + { 1.2234 + return HasAnyStateBits(NS_FRAME_NEEDS_PAINT | NS_FRAME_DESCENDANT_NEEDS_PAINT); 1.2235 + } 1.2236 + 1.2237 + /** 1.2238 + * Removes the invalid state from the current frame and all 1.2239 + * descendant frames. 1.2240 + */ 1.2241 + void ClearInvalidationStateBits(); 1.2242 + 1.2243 + /** 1.2244 + * Ensures that the refresh driver is running, and schedules a view 1.2245 + * manager flush on the next tick. 1.2246 + * 1.2247 + * The view manager flush will update the layer tree, repaint any 1.2248 + * invalid areas in the layer tree and schedule a layer tree 1.2249 + * composite operation to display the layer tree. 1.2250 + * 1.2251 + * In general it is not necessary for frames to call this when they change. 1.2252 + * For example, changes that result in a reflow will have this called for 1.2253 + * them by PresContext::DoReflow when the reflow begins. Style changes that 1.2254 + * do not trigger a reflow should have this called for them by 1.2255 + * DoApplyRenderingChangeToTree. 1.2256 + * 1.2257 + * @param aType PAINT_COMPOSITE_ONLY : No changes have been made 1.2258 + * that require a layer tree update, so only schedule a layer 1.2259 + * tree composite. 1.2260 + * PAINT_DELAYED_COMPRESS : Schedule a paint to be executed after a delay, and 1.2261 + * put FrameLayerBuilder in 'compressed' mode that avoids short cut optimizations. 1.2262 + */ 1.2263 + enum PaintType { 1.2264 + PAINT_DEFAULT = 0, 1.2265 + PAINT_COMPOSITE_ONLY, 1.2266 + PAINT_DELAYED_COMPRESS 1.2267 + }; 1.2268 + void SchedulePaint(PaintType aType = PAINT_DEFAULT); 1.2269 + 1.2270 + /** 1.2271 + * Checks if the layer tree includes a dedicated layer for this 1.2272 + * frame/display item key pair, and invalidates at least aDamageRect 1.2273 + * area within that layer. 1.2274 + * 1.2275 + * If no layer is found, calls InvalidateFrame() instead. 1.2276 + * 1.2277 + * @param aDamageRect Area of the layer to invalidate. 1.2278 + * @param aDisplayItemKey Display item type. 1.2279 + * @param aFlags UPDATE_IS_ASYNC : Will skip the invalidation 1.2280 + * if the found layer is being composited by a remote 1.2281 + * compositor. 1.2282 + * @return Layer, if found, nullptr otherwise. 1.2283 + */ 1.2284 + enum { 1.2285 + UPDATE_IS_ASYNC = 1 << 0 1.2286 + }; 1.2287 + Layer* InvalidateLayer(uint32_t aDisplayItemKey, const nsIntRect* aDamageRect = nullptr, uint32_t aFlags = 0); 1.2288 + 1.2289 + /** 1.2290 + * Returns a rect that encompasses everything that might be painted by 1.2291 + * this frame. This includes this frame, all its descendent frames, this 1.2292 + * frame's outline, and descentant frames' outline, but does not include 1.2293 + * areas clipped out by the CSS "overflow" and "clip" properties. 1.2294 + * 1.2295 + * HasOverflowRects() (below) will return true when this overflow 1.2296 + * rect has been explicitly set, even if it matches mRect. 1.2297 + * XXX Note: because of a space optimization using the formula above, 1.2298 + * during reflow this function does not give accurate data if 1.2299 + * FinishAndStoreOverflow has been called but mRect hasn't yet been 1.2300 + * updated yet. FIXME: This actually isn't true, but it should be. 1.2301 + * 1.2302 + * The visual overflow rect should NEVER be used for things that 1.2303 + * affect layout. The scrollable overflow rect is permitted to affect 1.2304 + * layout. 1.2305 + * 1.2306 + * @return the rect relative to this frame's origin, but after 1.2307 + * CSS transforms have been applied (i.e. not really this frame's coordinate 1.2308 + * system, and may not contain the frame's border-box, e.g. if there 1.2309 + * is a CSS transform scaling it down) 1.2310 + */ 1.2311 + nsRect GetVisualOverflowRect() const { 1.2312 + return GetOverflowRect(eVisualOverflow); 1.2313 + } 1.2314 + 1.2315 + /** 1.2316 + * Returns a rect that encompasses the area of this frame that the 1.2317 + * user should be able to scroll to reach. This is similar to 1.2318 + * GetVisualOverflowRect, but does not include outline or shadows, and 1.2319 + * may in the future include more margins than visual overflow does. 1.2320 + * It does not include areas clipped out by the CSS "overflow" and 1.2321 + * "clip" properties. 1.2322 + * 1.2323 + * HasOverflowRects() (below) will return true when this overflow 1.2324 + * rect has been explicitly set, even if it matches mRect. 1.2325 + * XXX Note: because of a space optimization using the formula above, 1.2326 + * during reflow this function does not give accurate data if 1.2327 + * FinishAndStoreOverflow has been called but mRect hasn't yet been 1.2328 + * updated yet. 1.2329 + * 1.2330 + * @return the rect relative to this frame's origin, but after 1.2331 + * CSS transforms have been applied (i.e. not really this frame's coordinate 1.2332 + * system, and may not contain the frame's border-box, e.g. if there 1.2333 + * is a CSS transform scaling it down) 1.2334 + */ 1.2335 + nsRect GetScrollableOverflowRect() const { 1.2336 + return GetOverflowRect(eScrollableOverflow); 1.2337 + } 1.2338 + 1.2339 + nsRect GetOverflowRect(nsOverflowType aType) const; 1.2340 + 1.2341 + nsOverflowAreas GetOverflowAreas() const; 1.2342 + 1.2343 + /** 1.2344 + * Same as GetOverflowAreas, except in this frame's coordinate 1.2345 + * system (before transforms are applied). 1.2346 + * 1.2347 + * @return the overflow areas relative to this frame, before any CSS transforms have 1.2348 + * been applied, i.e. in this frame's coordinate system 1.2349 + */ 1.2350 + nsOverflowAreas GetOverflowAreasRelativeToSelf() const; 1.2351 + 1.2352 + /** 1.2353 + * Same as GetScrollableOverflowRect, except relative to the parent 1.2354 + * frame. 1.2355 + * 1.2356 + * @return the rect relative to the parent frame, in the parent frame's 1.2357 + * coordinate system 1.2358 + */ 1.2359 + nsRect GetScrollableOverflowRectRelativeToParent() const; 1.2360 + 1.2361 + /** 1.2362 + * Same as GetScrollableOverflowRect, except in this frame's coordinate 1.2363 + * system (before transforms are applied). 1.2364 + * 1.2365 + * @return the rect relative to this frame, before any CSS transforms have 1.2366 + * been applied, i.e. in this frame's coordinate system 1.2367 + */ 1.2368 + nsRect GetScrollableOverflowRectRelativeToSelf() const; 1.2369 + 1.2370 + /** 1.2371 + * Like GetVisualOverflowRect, except in this frame's 1.2372 + * coordinate system (before transforms are applied). 1.2373 + * 1.2374 + * @return the rect relative to this frame, before any CSS transforms have 1.2375 + * been applied, i.e. in this frame's coordinate system 1.2376 + */ 1.2377 + nsRect GetVisualOverflowRectRelativeToSelf() const; 1.2378 + 1.2379 + /** 1.2380 + * Returns this frame's visual overflow rect as it would be before taking 1.2381 + * account of SVG effects or transforms. The rect returned is relative to 1.2382 + * this frame. 1.2383 + */ 1.2384 + nsRect GetPreEffectsVisualOverflowRect() const; 1.2385 + 1.2386 + /** 1.2387 + * Store the overflow area in the frame's mOverflow.mVisualDeltas 1.2388 + * fields or as a frame property in the frame manager so that it can 1.2389 + * be retrieved later without reflowing the frame. Returns true if either of 1.2390 + * the overflow areas changed. 1.2391 + */ 1.2392 + bool FinishAndStoreOverflow(nsOverflowAreas& aOverflowAreas, 1.2393 + nsSize aNewSize, nsSize* aOldSize = nullptr); 1.2394 + 1.2395 + bool FinishAndStoreOverflow(nsHTMLReflowMetrics* aMetrics) { 1.2396 + return FinishAndStoreOverflow(aMetrics->mOverflowAreas, 1.2397 + nsSize(aMetrics->Width(), aMetrics->Height())); 1.2398 + } 1.2399 + 1.2400 + /** 1.2401 + * Returns whether the frame has an overflow rect that is different from 1.2402 + * its border-box. 1.2403 + */ 1.2404 + bool HasOverflowAreas() const { 1.2405 + return mOverflow.mType != NS_FRAME_OVERFLOW_NONE; 1.2406 + } 1.2407 + 1.2408 + /** 1.2409 + * Removes any stored overflow rects (visual and scrollable) from the frame. 1.2410 + * Returns true if the overflow changed. 1.2411 + */ 1.2412 + bool ClearOverflowRects(); 1.2413 + 1.2414 + /** 1.2415 + * Determine whether borders should not be painted on certain sides of the 1.2416 + * frame. 1.2417 + * 1.2418 + * @note (See also bug 743402, comment 11) GetSkipSides() and its sister 1.2419 + * method, ApplySkipSides() checks to see if this frame has a previous 1.2420 + * or next continuation to determine if a side should be skipped. 1.2421 + * Unfortunately, this only works after reflow has been completed. In 1.2422 + * lieu of this, during reflow, an nsHTMLReflowState parameter can be 1.2423 + * passed in, indicating that it should be used to determine if sides 1.2424 + * should be skipped during reflow. 1.2425 + */ 1.2426 +#define LOGICAL_SIDE_B_START 1 1.2427 +#define LOGICAL_SIDE_I_START 2 1.2428 +#define LOGICAL_SIDE_B_END 4 1.2429 +#define LOGICAL_SIDE_I_END 8 1.2430 +#define LOGICAL_SIDES_I_BOTH (LOGICAL_SIDE_I_START | LOGICAL_SIDE_I_END) 1.2431 +#define LOGICAL_SIDES_B_BOTH (LOGICAL_SIDE_B_START | LOGICAL_SIDE_B_END) 1.2432 +#define LOGICAL_SIDES_ALL (LOGICAL_SIDE_I_START | LOGICAL_SIDE_I_END | \ 1.2433 + LOGICAL_SIDE_B_START | LOGICAL_SIDE_B_END) 1.2434 + int GetSkipSides(const nsHTMLReflowState* aReflowState = nullptr) const; 1.2435 + virtual int 1.2436 + GetLogicalSkipSides(const nsHTMLReflowState* aReflowState = nullptr) const { 1.2437 + return 0; 1.2438 + } 1.2439 + 1.2440 + /** 1.2441 + * @returns true if this frame is selected. 1.2442 + */ 1.2443 + bool IsSelected() const; 1.2444 + 1.2445 + /** 1.2446 + * called to discover where this frame, or a parent frame has user-select style 1.2447 + * applied, which affects that way that it is selected. 1.2448 + * 1.2449 + * @param aIsSelectable out param. Set to true if the frame can be selected 1.2450 + * (i.e. is not affected by user-select: none) 1.2451 + * @param aSelectStyle out param. Returns the type of selection style found 1.2452 + * (using values defined in nsStyleConsts.h). 1.2453 + */ 1.2454 + virtual nsresult IsSelectable(bool* aIsSelectable, uint8_t* aSelectStyle) const = 0; 1.2455 + 1.2456 + /** 1.2457 + * Called to retrieve the SelectionController associated with the frame. 1.2458 + * @param aSelCon will contain the selection controller associated with 1.2459 + * the frame. 1.2460 + */ 1.2461 + virtual nsresult GetSelectionController(nsPresContext *aPresContext, nsISelectionController **aSelCon) = 0; 1.2462 + 1.2463 + /** 1.2464 + * Call to get nsFrameSelection for this frame. 1.2465 + */ 1.2466 + already_AddRefed<nsFrameSelection> GetFrameSelection(); 1.2467 + 1.2468 + /** 1.2469 + * GetConstFrameSelection returns an object which methods are safe to use for 1.2470 + * example in nsIFrame code. 1.2471 + */ 1.2472 + const nsFrameSelection* GetConstFrameSelection() const; 1.2473 + 1.2474 + /** 1.2475 + * called to find the previous/next character, word, or line returns the actual 1.2476 + * nsIFrame and the frame offset. THIS DOES NOT CHANGE SELECTION STATE 1.2477 + * uses frame's begin selection state to start. if no selection on this frame will 1.2478 + * return NS_ERROR_FAILURE 1.2479 + * @param aPOS is defined in nsFrameSelection 1.2480 + */ 1.2481 + virtual nsresult PeekOffset(nsPeekOffsetStruct *aPos); 1.2482 + 1.2483 + /** 1.2484 + * called to find the previous/next selectable leaf frame. 1.2485 + * @param aDirection [in] the direction to move in (eDirPrevious or eDirNext) 1.2486 + * @param aVisual [in] whether bidi caret behavior is visual (true) or logical (false) 1.2487 + * @param aJumpLines [in] whether to allow jumping across line boundaries 1.2488 + * @param aScrollViewStop [in] whether to stop when reaching a scroll frame boundary 1.2489 + * @param aOutFrame [out] the previous/next selectable leaf frame 1.2490 + * @param aOutOffset [out] 0 indicates that we arrived at the beginning of the output frame; 1.2491 + * -1 indicates that we arrived at its end. 1.2492 + * @param aOutJumpedLine [out] whether this frame and the returned frame are on different lines 1.2493 + */ 1.2494 + nsresult GetFrameFromDirection(nsDirection aDirection, bool aVisual, 1.2495 + bool aJumpLines, bool aScrollViewStop, 1.2496 + nsIFrame** aOutFrame, int32_t* aOutOffset, bool* aOutJumpedLine); 1.2497 + 1.2498 + /** 1.2499 + * called to see if the children of the frame are visible from indexstart to index end. 1.2500 + * this does not change any state. returns true only if the indexes are valid and any of 1.2501 + * the children are visible. for textframes this index is the character index. 1.2502 + * if aStart = aEnd result will be false 1.2503 + * @param aStart start index of first child from 0-N (number of children) 1.2504 + * @param aEnd end index of last child from 0-N 1.2505 + * @param aRecurse should this frame talk to siblings to get to the contents other children? 1.2506 + * @param aFinished did this frame have the aEndIndex? or is there more work to do 1.2507 + * @param _retval return value true or false. false = range is not rendered. 1.2508 + */ 1.2509 + virtual nsresult CheckVisibility(nsPresContext* aContext, int32_t aStartIndex, int32_t aEndIndex, bool aRecurse, bool *aFinished, bool *_retval)=0; 1.2510 + 1.2511 + /** 1.2512 + * Called to tell a frame that one of its child frames is dirty (i.e., 1.2513 + * has the NS_FRAME_IS_DIRTY *or* NS_FRAME_HAS_DIRTY_CHILDREN bit 1.2514 + * set). This should always set the NS_FRAME_HAS_DIRTY_CHILDREN on 1.2515 + * the frame, and may do other work. 1.2516 + */ 1.2517 + virtual void ChildIsDirty(nsIFrame* aChild) = 0; 1.2518 + 1.2519 + /** 1.2520 + * Called to retrieve this frame's accessible. 1.2521 + * If this frame implements Accessibility return a valid accessible 1.2522 + * If not return NS_ERROR_NOT_IMPLEMENTED. 1.2523 + * Note: Accessible must be refcountable. Do not implement directly on your frame 1.2524 + * Use a mediatior of some kind. 1.2525 + */ 1.2526 +#ifdef ACCESSIBILITY 1.2527 + virtual mozilla::a11y::AccType AccessibleType() = 0; 1.2528 +#endif 1.2529 + 1.2530 + /** 1.2531 + * Get the frame whose style context should be the parent of this 1.2532 + * frame's style context (i.e., provide the parent style context). 1.2533 + * This frame must either be an ancestor of this frame or a child. If 1.2534 + * this returns a child frame, then the child frame must be sure to 1.2535 + * return a grandparent or higher! Furthermore, if a child frame is 1.2536 + * returned it must have the same GetContent() as this frame. 1.2537 + * 1.2538 + * @return The frame whose style context should be the parent of this frame's 1.2539 + * style context. Null is permitted, and means that this frame's 1.2540 + * style context should be the root of the style context tree. 1.2541 + */ 1.2542 + virtual nsIFrame* GetParentStyleContextFrame() const = 0; 1.2543 + 1.2544 + /** 1.2545 + * Determines whether a frame is visible for painting; 1.2546 + * taking into account whether it is painting a selection or printing. 1.2547 + */ 1.2548 + bool IsVisibleForPainting(nsDisplayListBuilder* aBuilder); 1.2549 + /** 1.2550 + * Determines whether a frame is visible for painting or collapsed; 1.2551 + * taking into account whether it is painting a selection or printing, 1.2552 + */ 1.2553 + bool IsVisibleOrCollapsedForPainting(nsDisplayListBuilder* aBuilder); 1.2554 + /** 1.2555 + * As above, but slower because we have to recompute some stuff that 1.2556 + * aBuilder already has. 1.2557 + */ 1.2558 + bool IsVisibleForPainting(); 1.2559 + /** 1.2560 + * Check whether this frame is visible in the current selection. Returns 1.2561 + * true if there is no current selection. 1.2562 + */ 1.2563 + bool IsVisibleInSelection(nsDisplayListBuilder* aBuilder); 1.2564 + 1.2565 + /** 1.2566 + * Overridable function to determine whether this frame should be considered 1.2567 + * "in" the given non-null aSelection for visibility purposes. 1.2568 + */ 1.2569 + virtual bool IsVisibleInSelection(nsISelection* aSelection); 1.2570 + 1.2571 + /** 1.2572 + * Determines whether this frame is a pseudo stacking context, looking 1.2573 + * only as style --- i.e., assuming that it's in-flow and not a replaced 1.2574 + * element and not an SVG element. 1.2575 + * XXX maybe check IsTransformed()? 1.2576 + */ 1.2577 + bool IsPseudoStackingContextFromStyle(); 1.2578 + 1.2579 + virtual bool HonorPrintBackgroundSettings() { return true; } 1.2580 + 1.2581 + /** 1.2582 + * Determine whether the frame is logically empty, which is roughly 1.2583 + * whether the layout would be the same whether or not the frame is 1.2584 + * present. Placeholder frames should return true. Block frames 1.2585 + * should be considered empty whenever margins collapse through them, 1.2586 + * even though those margins are relevant. Text frames containing 1.2587 + * only whitespace that does not contribute to the height of the line 1.2588 + * should return true. 1.2589 + */ 1.2590 + virtual bool IsEmpty() = 0; 1.2591 + /** 1.2592 + * Return the same as IsEmpty(). This may only be called after the frame 1.2593 + * has been reflowed and before any further style or content changes. 1.2594 + */ 1.2595 + virtual bool CachedIsEmpty(); 1.2596 + /** 1.2597 + * Determine whether the frame is logically empty, assuming that all 1.2598 + * its children are empty. 1.2599 + */ 1.2600 + virtual bool IsSelfEmpty() = 0; 1.2601 + 1.2602 + /** 1.2603 + * IsGeneratedContentFrame returns whether a frame corresponds to 1.2604 + * generated content 1.2605 + * 1.2606 + * @return whether the frame correspods to generated content 1.2607 + */ 1.2608 + bool IsGeneratedContentFrame() { 1.2609 + return (mState & NS_FRAME_GENERATED_CONTENT) != 0; 1.2610 + } 1.2611 + 1.2612 + /** 1.2613 + * IsPseudoFrame returns whether a frame is a pseudo frame (eg an 1.2614 + * anonymous table-row frame created for a CSS table-cell without an 1.2615 + * enclosing table-row. 1.2616 + * 1.2617 + * @param aParentContent the content node corresponding to the parent frame 1.2618 + * @return whether the frame is a pseudo frame 1.2619 + */ 1.2620 + bool IsPseudoFrame(nsIContent* aParentContent) { 1.2621 + return mContent == aParentContent; 1.2622 + } 1.2623 + 1.2624 + FrameProperties Properties() const { 1.2625 + return FrameProperties(PresContext()->PropertyTable(), this); 1.2626 + } 1.2627 + 1.2628 + NS_DECLARE_FRAME_PROPERTY(BaseLevelProperty, nullptr) 1.2629 + NS_DECLARE_FRAME_PROPERTY(EmbeddingLevelProperty, nullptr) 1.2630 + NS_DECLARE_FRAME_PROPERTY(ParagraphDepthProperty, nullptr) 1.2631 + 1.2632 +#define NS_GET_BASE_LEVEL(frame) \ 1.2633 +NS_PTR_TO_INT32(frame->Properties().Get(nsIFrame::BaseLevelProperty())) 1.2634 + 1.2635 +#define NS_GET_EMBEDDING_LEVEL(frame) \ 1.2636 +NS_PTR_TO_INT32(frame->Properties().Get(nsIFrame::EmbeddingLevelProperty())) 1.2637 + 1.2638 +#define NS_GET_PARAGRAPH_DEPTH(frame) \ 1.2639 +NS_PTR_TO_INT32(frame->Properties().Get(nsIFrame::ParagraphDepthProperty())) 1.2640 + 1.2641 + /** 1.2642 + * Return true if and only if this frame obeys visibility:hidden. 1.2643 + * if it does not, then nsContainerFrame will hide its view even though 1.2644 + * this means children can't be made visible again. 1.2645 + */ 1.2646 + virtual bool SupportsVisibilityHidden() { return true; } 1.2647 + 1.2648 + /** 1.2649 + * Returns true if the frame has a valid clip rect set via the 'clip' 1.2650 + * property, and the 'clip' property applies to this frame. The 'clip' 1.2651 + * property applies to HTML frames if they are absolutely positioned. The 1.2652 + * 'clip' property applies to SVG frames regardless of the value of the 1.2653 + * 'position' property. 1.2654 + * 1.2655 + * If this method returns true, then we also set aRect to the computed clip 1.2656 + * rect, with coordinates relative to this frame's origin. aRect must not be 1.2657 + * null! 1.2658 + */ 1.2659 + bool GetClipPropClipRect(const nsStyleDisplay* aDisp, nsRect* aRect, 1.2660 + const nsSize& aSize) const; 1.2661 + 1.2662 + /** 1.2663 + * Check if this frame is focusable and in the current tab order. 1.2664 + * Tabbable is indicated by a nonnegative tabindex & is a subset of focusable. 1.2665 + * For example, only the selected radio button in a group is in the 1.2666 + * tab order, unless the radio group has no selection in which case 1.2667 + * all of the visible, non-disabled radio buttons in the group are 1.2668 + * in the tab order. On the other hand, all of the visible, non-disabled 1.2669 + * radio buttons are always focusable via clicking or script. 1.2670 + * Also, depending on the pref accessibility.tabfocus some widgets may be 1.2671 + * focusable but removed from the tab order. This is the default on 1.2672 + * Mac OS X, where fewer items are focusable. 1.2673 + * @param [in, optional] aTabIndex the computed tab index 1.2674 + * < 0 if not tabbable 1.2675 + * == 0 if in normal tab order 1.2676 + * > 0 can be tabbed to in the order specified by this value 1.2677 + * @param [in, optional] aWithMouse, is this focus query for mouse clicking 1.2678 + * @return whether the frame is focusable via mouse, kbd or script. 1.2679 + */ 1.2680 + virtual bool IsFocusable(int32_t *aTabIndex = nullptr, bool aWithMouse = false); 1.2681 + 1.2682 + // BOX LAYOUT METHODS 1.2683 + // These methods have been migrated from nsIBox and are in the process of 1.2684 + // being refactored. DO NOT USE OUTSIDE OF XUL. 1.2685 + bool IsBoxFrame() const 1.2686 + { 1.2687 + return IsFrameOfType(nsIFrame::eXULBox); 1.2688 + } 1.2689 + bool IsBoxWrapped() const 1.2690 + { return (!IsBoxFrame() && mParent && mParent->IsBoxFrame()); } 1.2691 + 1.2692 + enum Halignment { 1.2693 + hAlign_Left, 1.2694 + hAlign_Right, 1.2695 + hAlign_Center 1.2696 + }; 1.2697 + 1.2698 + enum Valignment { 1.2699 + vAlign_Top, 1.2700 + vAlign_Middle, 1.2701 + vAlign_BaseLine, 1.2702 + vAlign_Bottom 1.2703 + }; 1.2704 + 1.2705 + /** 1.2706 + * This calculates the minimum size required for a box based on its state 1.2707 + * @param[in] aBoxLayoutState The desired state to calculate for 1.2708 + * @return The minimum size 1.2709 + */ 1.2710 + virtual nsSize GetMinSize(nsBoxLayoutState& aBoxLayoutState) = 0; 1.2711 + 1.2712 + /** 1.2713 + * This calculates the preferred size of a box based on its state 1.2714 + * @param[in] aBoxLayoutState The desired state to calculate for 1.2715 + * @return The preferred size 1.2716 + */ 1.2717 + virtual nsSize GetPrefSize(nsBoxLayoutState& aBoxLayoutState) = 0; 1.2718 + 1.2719 + /** 1.2720 + * This calculates the maximum size for a box based on its state 1.2721 + * @param[in] aBoxLayoutState The desired state to calculate for 1.2722 + * @return The maximum size 1.2723 + */ 1.2724 + virtual nsSize GetMaxSize(nsBoxLayoutState& aBoxLayoutState) = 0; 1.2725 + 1.2726 + /** 1.2727 + * This returns the minimum size for the scroll area if this frame is 1.2728 + * being scrolled. Usually it's (0,0). 1.2729 + */ 1.2730 + virtual nsSize GetMinSizeForScrollArea(nsBoxLayoutState& aBoxLayoutState) = 0; 1.2731 + 1.2732 + // Implemented in nsBox, used in nsBoxFrame 1.2733 + uint32_t GetOrdinal(); 1.2734 + 1.2735 + virtual nscoord GetFlex(nsBoxLayoutState& aBoxLayoutState) = 0; 1.2736 + virtual nscoord GetBoxAscent(nsBoxLayoutState& aBoxLayoutState) = 0; 1.2737 + virtual bool IsCollapsed() = 0; 1.2738 + // This does not alter the overflow area. If the caller is changing 1.2739 + // the box size, the caller is responsible for updating the overflow 1.2740 + // area. It's enough to just call Layout or SyncLayout on the 1.2741 + // box. You can pass true to aRemoveOverflowArea as a 1.2742 + // convenience. 1.2743 + virtual void SetBounds(nsBoxLayoutState& aBoxLayoutState, const nsRect& aRect, 1.2744 + bool aRemoveOverflowAreas = false) = 0; 1.2745 + NS_HIDDEN_(nsresult) Layout(nsBoxLayoutState& aBoxLayoutState); 1.2746 + nsIFrame* GetChildBox() const 1.2747 + { 1.2748 + // box layout ends at box-wrapped frames, so don't allow these frames 1.2749 + // to report child boxes. 1.2750 + return IsBoxFrame() ? GetFirstPrincipalChild() : nullptr; 1.2751 + } 1.2752 + nsIFrame* GetNextBox() const 1.2753 + { 1.2754 + return (mParent && mParent->IsBoxFrame()) ? mNextSibling : nullptr; 1.2755 + } 1.2756 + nsIFrame* GetParentBox() const 1.2757 + { 1.2758 + return (mParent && mParent->IsBoxFrame()) ? mParent : nullptr; 1.2759 + } 1.2760 + // Box methods. Note that these do NOT just get the CSS border, padding, 1.2761 + // etc. They also talk to nsITheme. 1.2762 + virtual nsresult GetBorderAndPadding(nsMargin& aBorderAndPadding); 1.2763 + virtual nsresult GetBorder(nsMargin& aBorder)=0; 1.2764 + virtual nsresult GetPadding(nsMargin& aBorderAndPadding)=0; 1.2765 + virtual nsresult GetMargin(nsMargin& aMargin)=0; 1.2766 + virtual void SetLayoutManager(nsBoxLayout* aLayout) { } 1.2767 + virtual nsBoxLayout* GetLayoutManager() { return nullptr; } 1.2768 + NS_HIDDEN_(nsresult) GetClientRect(nsRect& aContentRect); 1.2769 + 1.2770 + // For nsSprocketLayout 1.2771 + virtual Valignment GetVAlign() const = 0; 1.2772 + virtual Halignment GetHAlign() const = 0; 1.2773 + 1.2774 + bool IsHorizontal() const { return (mState & NS_STATE_IS_HORIZONTAL) != 0; } 1.2775 + bool IsNormalDirection() const { return (mState & NS_STATE_IS_DIRECTION_NORMAL) != 0; } 1.2776 + 1.2777 + NS_HIDDEN_(nsresult) Redraw(nsBoxLayoutState& aState); 1.2778 + virtual nsresult RelayoutChildAtOrdinal(nsBoxLayoutState& aState, nsIFrame* aChild)=0; 1.2779 + // XXX take this out after we've branched 1.2780 + virtual bool GetMouseThrough() const { return false; } 1.2781 + 1.2782 +#ifdef DEBUG_LAYOUT 1.2783 + virtual nsresult SetDebug(nsBoxLayoutState& aState, bool aDebug)=0; 1.2784 + virtual nsresult GetDebug(bool& aDebug)=0; 1.2785 + 1.2786 + virtual nsresult DumpBox(FILE* out)=0; 1.2787 +#endif 1.2788 + 1.2789 + /** 1.2790 + * @return true if this text frame ends with a newline character. It 1.2791 + * should return false if this is not a text frame. 1.2792 + */ 1.2793 + virtual bool HasSignificantTerminalNewline() const; 1.2794 + 1.2795 + static bool AddCSSPrefSize(nsIFrame* aBox, nsSize& aSize, bool& aWidth, bool& aHeightSet); 1.2796 + static bool AddCSSMinSize(nsBoxLayoutState& aState, nsIFrame* aBox, 1.2797 + nsSize& aSize, bool& aWidth, bool& aHeightSet); 1.2798 + static bool AddCSSMaxSize(nsIFrame* aBox, nsSize& aSize, bool& aWidth, bool& aHeightSet); 1.2799 + static bool AddCSSFlex(nsBoxLayoutState& aState, nsIFrame* aBox, nscoord& aFlex); 1.2800 + 1.2801 + // END OF BOX LAYOUT METHODS 1.2802 + // The above methods have been migrated from nsIBox and are in the process of 1.2803 + // being refactored. DO NOT USE OUTSIDE OF XUL. 1.2804 + 1.2805 + struct CaretPosition { 1.2806 + CaretPosition(); 1.2807 + ~CaretPosition(); 1.2808 + 1.2809 + nsCOMPtr<nsIContent> mResultContent; 1.2810 + int32_t mContentOffset; 1.2811 + }; 1.2812 + 1.2813 + /** 1.2814 + * gets the first or last possible caret position within the frame 1.2815 + * 1.2816 + * @param [in] aStart 1.2817 + * true for getting the first possible caret position 1.2818 + * false for getting the last possible caret position 1.2819 + * @return The caret position in a CaretPosition. 1.2820 + * the returned value is a 'best effort' in case errors 1.2821 + * are encountered rummaging through the frame. 1.2822 + */ 1.2823 + CaretPosition GetExtremeCaretPosition(bool aStart); 1.2824 + 1.2825 + /** 1.2826 + * Get a line iterator for this frame, if supported. 1.2827 + * 1.2828 + * @return nullptr if no line iterator is supported. 1.2829 + * @note dispose the line iterator using nsILineIterator::DisposeLineIterator 1.2830 + */ 1.2831 + virtual nsILineIterator* GetLineIterator() = 0; 1.2832 + 1.2833 + /** 1.2834 + * If this frame is a next-in-flow, and its prev-in-flow has something on its 1.2835 + * overflow list, pull those frames into the child list of this one. 1.2836 + */ 1.2837 + virtual void PullOverflowsFromPrevInFlow() {} 1.2838 + 1.2839 + /** 1.2840 + * Clear the list of child PresShells generated during the last paint 1.2841 + * so that we can begin generating a new one. 1.2842 + */ 1.2843 + void ClearPresShellsFromLastPaint() { 1.2844 + PaintedPresShellList()->Clear(); 1.2845 + } 1.2846 + 1.2847 + /** 1.2848 + * Flag a child PresShell as painted so that it will get its paint count 1.2849 + * incremented during empty transactions. 1.2850 + */ 1.2851 + void AddPaintedPresShell(nsIPresShell* shell) { 1.2852 + nsWeakPtr weakShell = do_GetWeakReference(shell); 1.2853 + PaintedPresShellList()->AppendElement(weakShell); 1.2854 + } 1.2855 + 1.2856 + /** 1.2857 + * Increment the paint count of all child PresShells that were painted during 1.2858 + * the last repaint. 1.2859 + */ 1.2860 + void UpdatePaintCountForPaintedPresShells() { 1.2861 + nsTArray<nsWeakPtr> * list = PaintedPresShellList(); 1.2862 + for (int i = 0, l = list->Length(); i < l; i++) { 1.2863 + nsCOMPtr<nsIPresShell> shell = do_QueryReferent(list->ElementAt(i)); 1.2864 + 1.2865 + if (shell) { 1.2866 + shell->IncrementPaintCount(); 1.2867 + } 1.2868 + } 1.2869 + } 1.2870 + 1.2871 + /** 1.2872 + * Accessors for the absolute containing block. 1.2873 + */ 1.2874 + bool IsAbsoluteContainer() const { return !!(mState & NS_FRAME_HAS_ABSPOS_CHILDREN); } 1.2875 + bool HasAbsolutelyPositionedChildren() const; 1.2876 + nsAbsoluteContainingBlock* GetAbsoluteContainingBlock() const; 1.2877 + void MarkAsAbsoluteContainingBlock(); 1.2878 + void MarkAsNotAbsoluteContainingBlock(); 1.2879 + // Child frame types override this function to select their own child list name 1.2880 + virtual mozilla::layout::FrameChildListID GetAbsoluteListID() const { return kAbsoluteList; } 1.2881 + 1.2882 + // Checks if we (or any of our descendents) have NS_FRAME_PAINTED_THEBES set, and 1.2883 + // clears this bit if so. 1.2884 + bool CheckAndClearPaintedState(); 1.2885 + 1.2886 + // CSS visibility just doesn't cut it because it doesn't inherit through 1.2887 + // documents. Also if this frame is in a hidden card of a deck then it isn't 1.2888 + // visible either and that isn't expressed using CSS visibility. Also if it 1.2889 + // is in a hidden view (there are a few cases left and they are hopefully 1.2890 + // going away soon). 1.2891 + // If the VISIBILITY_CROSS_CHROME_CONTENT_BOUNDARY flag is passed then we 1.2892 + // ignore the chrome/content boundary, otherwise we stop looking when we 1.2893 + // reach it. 1.2894 + enum { 1.2895 + VISIBILITY_CROSS_CHROME_CONTENT_BOUNDARY = 0x01 1.2896 + }; 1.2897 + bool IsVisibleConsideringAncestors(uint32_t aFlags = 0) const; 1.2898 + 1.2899 + struct FrameWithDistance 1.2900 + { 1.2901 + nsIFrame* mFrame; 1.2902 + nscoord mXDistance; 1.2903 + nscoord mYDistance; 1.2904 + }; 1.2905 + 1.2906 + /** 1.2907 + * Finds a frame that is closer to a specified point than a current 1.2908 + * distance. Distance is measured as for text selection -- a closer x 1.2909 + * distance beats a closer y distance. 1.2910 + * 1.2911 + * Normally, this function will only check the distance between this 1.2912 + * frame's rectangle and the specified point. SVGTextFrame overrides 1.2913 + * this so that it can manage all of its descendant frames and take 1.2914 + * into account any SVG text layout. 1.2915 + * 1.2916 + * If aPoint is closer to this frame's rectangle than aCurrentBestFrame 1.2917 + * indicates, then aCurrentBestFrame is updated with the distance between 1.2918 + * aPoint and this frame's rectangle, and with a pointer to this frame. 1.2919 + * If aPoint is not closer, then aCurrentBestFrame is left unchanged. 1.2920 + * 1.2921 + * @param aPoint The point to check for its distance to this frame. 1.2922 + * @param aCurrentBestFrame Pointer to a struct that will be updated with 1.2923 + * a pointer to this frame and its distance to aPoint, if this frame 1.2924 + * is indeed closer than the current distance in aCurrentBestFrame. 1.2925 + */ 1.2926 + virtual void FindCloserFrameForSelection(nsPoint aPoint, 1.2927 + FrameWithDistance* aCurrentBestFrame); 1.2928 + 1.2929 + /** 1.2930 + * Is this a flex item? (i.e. a non-abs-pos child of a flex container) 1.2931 + */ 1.2932 + inline bool IsFlexItem() const; 1.2933 + 1.2934 + inline bool IsBlockInside() const; 1.2935 + inline bool IsBlockOutside() const; 1.2936 + inline bool IsInlineOutside() const; 1.2937 + inline uint8_t GetDisplay() const; 1.2938 + inline bool IsFloating() const; 1.2939 + inline bool IsPositioned() const; 1.2940 + inline bool IsRelativelyPositioned() const; 1.2941 + inline bool IsAbsolutelyPositioned() const; 1.2942 + 1.2943 + /** 1.2944 + * Returns the vertical-align value to be used for layout, if it is one 1.2945 + * of the enumerated values. If this is an SVG text frame, it returns a value 1.2946 + * that corresponds to the value of dominant-baseline. If the 1.2947 + * vertical-align property has length or percentage value, this returns 1.2948 + * eInvalidVerticalAlign. 1.2949 + */ 1.2950 + uint8_t VerticalAlignEnum() const; 1.2951 + enum { eInvalidVerticalAlign = 0xFF }; 1.2952 + 1.2953 + bool IsSVGText() const { return mState & NS_FRAME_IS_SVG_TEXT; } 1.2954 + 1.2955 + void CreateOwnLayerIfNeeded(nsDisplayListBuilder* aBuilder, nsDisplayList* aList); 1.2956 + 1.2957 + /** 1.2958 + * Adds the NS_FRAME_IN_POPUP state bit to aFrame, and 1.2959 + * all descendant frames (including cross-doc ones). 1.2960 + */ 1.2961 + static void AddInPopupStateBitToDescendants(nsIFrame* aFrame); 1.2962 + /** 1.2963 + * Removes the NS_FRAME_IN_POPUP state bit from aFrame and 1.2964 + * all descendant frames (including cross-doc ones), unless 1.2965 + * the frame is a popup itself. 1.2966 + */ 1.2967 + static void RemoveInPopupStateBitFromDescendants(nsIFrame* aFrame); 1.2968 + 1.2969 + /** 1.2970 + * Sorts the given nsFrameList, so that for every two adjacent frames in the 1.2971 + * list, the former is less than or equal to the latter, according to the 1.2972 + * templated IsLessThanOrEqual method. 1.2973 + * 1.2974 + * Note: this method uses a stable merge-sort algorithm. 1.2975 + */ 1.2976 + template<bool IsLessThanOrEqual(nsIFrame*, nsIFrame*)> 1.2977 + static void SortFrameList(nsFrameList& aFrameList); 1.2978 + 1.2979 + /** 1.2980 + * Returns true if the given frame list is already sorted, according to the 1.2981 + * templated IsLessThanOrEqual function. 1.2982 + */ 1.2983 + template<bool IsLessThanOrEqual(nsIFrame*, nsIFrame*)> 1.2984 + static bool IsFrameListSorted(nsFrameList& aFrameList); 1.2985 + 1.2986 + /** 1.2987 + * Return true if aFrame is in an {ib} split and is NOT one of the 1.2988 + * continuations of the first inline in it. 1.2989 + */ 1.2990 + bool FrameIsNonFirstInIBSplit() const { 1.2991 + return (GetStateBits() & NS_FRAME_PART_OF_IBSPLIT) && 1.2992 + FirstContinuation()->Properties().Get(nsIFrame::IBSplitPrevSibling()); 1.2993 + } 1.2994 + 1.2995 + /** 1.2996 + * Return true if aFrame is in an {ib} split and is NOT one of the 1.2997 + * continuations of the last inline in it. 1.2998 + */ 1.2999 + bool FrameIsNonLastInIBSplit() const { 1.3000 + return (GetStateBits() & NS_FRAME_PART_OF_IBSPLIT) && 1.3001 + FirstContinuation()->Properties().Get(nsIFrame::IBSplitSibling()); 1.3002 + } 1.3003 + 1.3004 + /** 1.3005 + * Return whether this is a frame whose width is used when computing 1.3006 + * the font size inflation of its descendants. 1.3007 + */ 1.3008 + bool IsContainerForFontSizeInflation() const { 1.3009 + return GetStateBits() & NS_FRAME_FONT_INFLATION_CONTAINER; 1.3010 + } 1.3011 + 1.3012 + /** 1.3013 + * Returns the content node within the anonymous content that this frame 1.3014 + * generated and which corresponds to the specified pseudo-element type, 1.3015 + * or nullptr if there is no such anonymous content. 1.3016 + */ 1.3017 + virtual mozilla::dom::Element* GetPseudoElement(nsCSSPseudoElements::Type aType); 1.3018 + 1.3019 +protected: 1.3020 + // Members 1.3021 + nsRect mRect; 1.3022 + nsIContent* mContent; 1.3023 + nsStyleContext* mStyleContext; 1.3024 + nsIFrame* mParent; 1.3025 +private: 1.3026 + nsIFrame* mNextSibling; // doubly-linked list of frames 1.3027 + nsIFrame* mPrevSibling; // Do not touch outside SetNextSibling! 1.3028 + 1.3029 + void MarkAbsoluteFramesForDisplayList(nsDisplayListBuilder* aBuilder, const nsRect& aDirtyRect); 1.3030 + 1.3031 + static void DestroyPaintedPresShellList(void* propertyValue) { 1.3032 + nsTArray<nsWeakPtr>* list = static_cast<nsTArray<nsWeakPtr>*>(propertyValue); 1.3033 + list->Clear(); 1.3034 + delete list; 1.3035 + } 1.3036 + 1.3037 + // Stores weak references to all the PresShells that were painted during 1.3038 + // the last paint event so that we can increment their paint count during 1.3039 + // empty transactions 1.3040 + NS_DECLARE_FRAME_PROPERTY(PaintedPresShellsProperty, DestroyPaintedPresShellList) 1.3041 + 1.3042 + nsTArray<nsWeakPtr>* PaintedPresShellList() { 1.3043 + nsTArray<nsWeakPtr>* list = static_cast<nsTArray<nsWeakPtr>*>( 1.3044 + Properties().Get(PaintedPresShellsProperty()) 1.3045 + ); 1.3046 + 1.3047 + if (!list) { 1.3048 + list = new nsTArray<nsWeakPtr>(); 1.3049 + Properties().Set(PaintedPresShellsProperty(), list); 1.3050 + } 1.3051 + 1.3052 + return list; 1.3053 + } 1.3054 + 1.3055 +protected: 1.3056 + nsFrameState mState; 1.3057 + 1.3058 + // When there is an overflow area only slightly larger than mRect, 1.3059 + // we store a set of four 1-byte deltas from the edges of mRect 1.3060 + // rather than allocating a whole separate rectangle property. 1.3061 + // Note that these are unsigned values, all measured "outwards" 1.3062 + // from the edges of mRect, so /mLeft/ and /mTop/ are reversed from 1.3063 + // our normal coordinate system. 1.3064 + // If mOverflow.mType == NS_FRAME_OVERFLOW_LARGE, then the 1.3065 + // delta values are not meaningful and the overflow area is stored 1.3066 + // as a separate rect property. 1.3067 + struct VisualDeltas { 1.3068 + uint8_t mLeft; 1.3069 + uint8_t mTop; 1.3070 + uint8_t mRight; 1.3071 + uint8_t mBottom; 1.3072 + bool operator==(const VisualDeltas& aOther) const 1.3073 + { 1.3074 + return mLeft == aOther.mLeft && mTop == aOther.mTop && 1.3075 + mRight == aOther.mRight && mBottom == aOther.mBottom; 1.3076 + } 1.3077 + bool operator!=(const VisualDeltas& aOther) const 1.3078 + { 1.3079 + return !(*this == aOther); 1.3080 + } 1.3081 + }; 1.3082 + union { 1.3083 + uint32_t mType; 1.3084 + VisualDeltas mVisualDeltas; 1.3085 + } mOverflow; 1.3086 + 1.3087 + // Helpers 1.3088 + /** 1.3089 + * Can we stop inside this frame when we're skipping non-rendered whitespace? 1.3090 + * @param aForward [in] Are we moving forward (or backward) in content order. 1.3091 + * @param aOffset [in/out] At what offset into the frame to start looking. 1.3092 + * on output - what offset was reached (whether or not we found a place to stop). 1.3093 + * @return STOP: An appropriate offset was found within this frame, 1.3094 + * and is given by aOffset. 1.3095 + * CONTINUE: Not found within this frame, need to try the next frame. 1.3096 + * see enum FrameSearchResult for more details. 1.3097 + */ 1.3098 + virtual FrameSearchResult PeekOffsetNoAmount(bool aForward, int32_t* aOffset) = 0; 1.3099 + 1.3100 + /** 1.3101 + * Search the frame for the next character 1.3102 + * @param aForward [in] Are we moving forward (or backward) in content order. 1.3103 + * @param aOffset [in/out] At what offset into the frame to start looking. 1.3104 + * on output - what offset was reached (whether or not we found a place to stop). 1.3105 + * @param aRespectClusters [in] Whether to restrict result to valid cursor locations 1.3106 + * (between grapheme clusters) - default TRUE maintains "normal" behavior, 1.3107 + * FALSE is used for selection by "code unit" (instead of "character") 1.3108 + * @return STOP: An appropriate offset was found within this frame, 1.3109 + * and is given by aOffset. 1.3110 + * CONTINUE: Not found within this frame, need to try the next frame. 1.3111 + * see enum FrameSearchResult for more details. 1.3112 + */ 1.3113 + virtual FrameSearchResult PeekOffsetCharacter(bool aForward, int32_t* aOffset, 1.3114 + bool aRespectClusters = true) = 0; 1.3115 + 1.3116 + /** 1.3117 + * Search the frame for the next word boundary 1.3118 + * @param aForward [in] Are we moving forward (or backward) in content order. 1.3119 + * @param aWordSelectEatSpace [in] true: look for non-whitespace following 1.3120 + * whitespace (in the direction of movement). 1.3121 + * false: look for whitespace following non-whitespace (in the 1.3122 + * direction of movement). 1.3123 + * @param aIsKeyboardSelect [in] Was the action initiated by a keyboard operation? 1.3124 + * If true, punctuation immediately following a word is considered part 1.3125 + * of that word. Otherwise, a sequence of punctuation is always considered 1.3126 + * as a word on its own. 1.3127 + * @param aOffset [in/out] At what offset into the frame to start looking. 1.3128 + * on output - what offset was reached (whether or not we found a place to stop). 1.3129 + * @param aState [in/out] the state that is carried from frame to frame 1.3130 + * @return true: An appropriate offset was found within this frame, 1.3131 + * and is given by aOffset. 1.3132 + * false: Not found within this frame, need to try the next frame. 1.3133 + */ 1.3134 + struct PeekWordState { 1.3135 + // true when we're still at the start of the search, i.e., we can't return 1.3136 + // this point as a valid offset! 1.3137 + bool mAtStart; 1.3138 + // true when we've encountered at least one character of the pre-boundary type 1.3139 + // (whitespace if aWordSelectEatSpace is true, non-whitespace otherwise) 1.3140 + bool mSawBeforeType; 1.3141 + // true when the last character encountered was punctuation 1.3142 + bool mLastCharWasPunctuation; 1.3143 + // true when the last character encountered was whitespace 1.3144 + bool mLastCharWasWhitespace; 1.3145 + // true when we've seen non-punctuation since the last whitespace 1.3146 + bool mSeenNonPunctuationSinceWhitespace; 1.3147 + // text that's *before* the current frame when aForward is true, *after* 1.3148 + // the current frame when aForward is false. Only includes the text 1.3149 + // on the current line. 1.3150 + nsAutoString mContext; 1.3151 + 1.3152 + PeekWordState() : mAtStart(true), mSawBeforeType(false), 1.3153 + mLastCharWasPunctuation(false), mLastCharWasWhitespace(false), 1.3154 + mSeenNonPunctuationSinceWhitespace(false) {} 1.3155 + void SetSawBeforeType() { mSawBeforeType = true; } 1.3156 + void Update(bool aAfterPunctuation, bool aAfterWhitespace) { 1.3157 + mLastCharWasPunctuation = aAfterPunctuation; 1.3158 + mLastCharWasWhitespace = aAfterWhitespace; 1.3159 + if (aAfterWhitespace) { 1.3160 + mSeenNonPunctuationSinceWhitespace = false; 1.3161 + } else if (!aAfterPunctuation) { 1.3162 + mSeenNonPunctuationSinceWhitespace = true; 1.3163 + } 1.3164 + mAtStart = false; 1.3165 + } 1.3166 + }; 1.3167 + virtual FrameSearchResult PeekOffsetWord(bool aForward, bool aWordSelectEatSpace, bool aIsKeyboardSelect, 1.3168 + int32_t* aOffset, PeekWordState* aState) = 0; 1.3169 + 1.3170 + /** 1.3171 + * Search for the first paragraph boundary before or after the given position 1.3172 + * @param aPos See description in nsFrameSelection.h. The following fields are 1.3173 + * used by this method: 1.3174 + * Input: mDirection 1.3175 + * Output: mResultContent, mContentOffset 1.3176 + */ 1.3177 + nsresult PeekOffsetParagraph(nsPeekOffsetStruct *aPos); 1.3178 + 1.3179 +private: 1.3180 + nsOverflowAreas* GetOverflowAreasProperty(); 1.3181 + nsRect GetVisualOverflowFromDeltas() const { 1.3182 + NS_ABORT_IF_FALSE(mOverflow.mType != NS_FRAME_OVERFLOW_LARGE, 1.3183 + "should not be called when overflow is in a property"); 1.3184 + // Calculate the rect using deltas from the frame's border rect. 1.3185 + // Note that the mOverflow.mDeltas fields are unsigned, but we will often 1.3186 + // need to return negative values for the left and top, so take care 1.3187 + // to cast away the unsigned-ness. 1.3188 + return nsRect(-(int32_t)mOverflow.mVisualDeltas.mLeft, 1.3189 + -(int32_t)mOverflow.mVisualDeltas.mTop, 1.3190 + mRect.width + mOverflow.mVisualDeltas.mRight + 1.3191 + mOverflow.mVisualDeltas.mLeft, 1.3192 + mRect.height + mOverflow.mVisualDeltas.mBottom + 1.3193 + mOverflow.mVisualDeltas.mTop); 1.3194 + } 1.3195 + /** 1.3196 + * Returns true if any overflow changed. 1.3197 + */ 1.3198 + bool SetOverflowAreas(const nsOverflowAreas& aOverflowAreas); 1.3199 + nsPoint GetOffsetToCrossDoc(const nsIFrame* aOther, const int32_t aAPD) const; 1.3200 + 1.3201 + // Helper-functions for SortFrameList(): 1.3202 + template<bool IsLessThanOrEqual(nsIFrame*, nsIFrame*)> 1.3203 + static nsIFrame* SortedMerge(nsIFrame *aLeft, nsIFrame *aRight); 1.3204 + 1.3205 + template<bool IsLessThanOrEqual(nsIFrame*, nsIFrame*)> 1.3206 + static nsIFrame* MergeSort(nsIFrame *aSource); 1.3207 + 1.3208 + bool HasOpacityInternal(float aThreshold) const; 1.3209 + 1.3210 +#ifdef DEBUG_FRAME_DUMP 1.3211 +public: 1.3212 + static void IndentBy(FILE* out, int32_t aIndent) { 1.3213 + while (--aIndent >= 0) fputs(" ", out); 1.3214 + } 1.3215 + void ListTag(FILE* out) const { 1.3216 + ListTag(out, this); 1.3217 + } 1.3218 + static void ListTag(FILE* out, const nsIFrame* aFrame) { 1.3219 + nsAutoCString t; 1.3220 + ListTag(t, aFrame); 1.3221 + fputs(t.get(), out); 1.3222 + } 1.3223 + void ListTag(nsACString& aTo) const; 1.3224 + static void ListTag(nsACString& aTo, const nsIFrame* aFrame); 1.3225 + void ListGeneric(nsACString& aTo, const char* aPrefix = "", uint32_t aFlags = 0) const; 1.3226 + enum { 1.3227 + TRAVERSE_SUBDOCUMENT_FRAMES = 0x01 1.3228 + }; 1.3229 + virtual void List(FILE* out = stderr, const char* aPrefix = "", uint32_t aFlags = 0) const; 1.3230 + /** 1.3231 + * lists the frames beginning from the root frame 1.3232 + * - calls root frame's List(...) 1.3233 + */ 1.3234 + static void RootFrameList(nsPresContext* aPresContext, 1.3235 + FILE* out = stderr, const char* aPrefix = ""); 1.3236 + virtual void DumpFrameTree(); 1.3237 + void DumpFrameTreeLimited(); 1.3238 + 1.3239 + virtual nsresult GetFrameName(nsAString& aResult) const = 0; 1.3240 +#endif 1.3241 + 1.3242 +#ifdef DEBUG 1.3243 +public: 1.3244 + virtual nsFrameState GetDebugStateBits() const = 0; 1.3245 + virtual nsresult DumpRegressionData(nsPresContext* aPresContext, 1.3246 + FILE* out, int32_t aIndent) = 0; 1.3247 +#endif 1.3248 +}; 1.3249 + 1.3250 +//---------------------------------------------------------------------- 1.3251 + 1.3252 +/** 1.3253 + * nsWeakFrame can be used to keep a reference to a nsIFrame in a safe way. 1.3254 + * Whenever an nsIFrame object is deleted, the nsWeakFrames pointing 1.3255 + * to it will be cleared. 1.3256 + * 1.3257 + * Create nsWeakFrame object when it is sure that nsIFrame object 1.3258 + * is alive and after some operations which may destroy the nsIFrame 1.3259 + * (for example any DOM modifications) use IsAlive() or GetFrame() methods to 1.3260 + * check whether it is safe to continue to use the nsIFrame object. 1.3261 + * 1.3262 + * @note The usage of this class should be kept to a minimum. 1.3263 + */ 1.3264 + 1.3265 +class nsWeakFrame { 1.3266 +public: 1.3267 + nsWeakFrame() : mPrev(nullptr), mFrame(nullptr) { } 1.3268 + 1.3269 + nsWeakFrame(const nsWeakFrame& aOther) : mPrev(nullptr), mFrame(nullptr) 1.3270 + { 1.3271 + Init(aOther.GetFrame()); 1.3272 + } 1.3273 + 1.3274 + nsWeakFrame(nsIFrame* aFrame) : mPrev(nullptr), mFrame(nullptr) 1.3275 + { 1.3276 + Init(aFrame); 1.3277 + } 1.3278 + 1.3279 + nsWeakFrame& operator=(nsWeakFrame& aOther) { 1.3280 + Init(aOther.GetFrame()); 1.3281 + return *this; 1.3282 + } 1.3283 + 1.3284 + nsWeakFrame& operator=(nsIFrame* aFrame) { 1.3285 + Init(aFrame); 1.3286 + return *this; 1.3287 + } 1.3288 + 1.3289 + nsIFrame* operator->() 1.3290 + { 1.3291 + return mFrame; 1.3292 + } 1.3293 + 1.3294 + operator nsIFrame*() 1.3295 + { 1.3296 + return mFrame; 1.3297 + } 1.3298 + 1.3299 + void Clear(nsIPresShell* aShell) { 1.3300 + if (aShell) { 1.3301 + aShell->RemoveWeakFrame(this); 1.3302 + } 1.3303 + mFrame = nullptr; 1.3304 + mPrev = nullptr; 1.3305 + } 1.3306 + 1.3307 + bool IsAlive() { return !!mFrame; } 1.3308 + 1.3309 + nsIFrame* GetFrame() const { return mFrame; } 1.3310 + 1.3311 + nsWeakFrame* GetPreviousWeakFrame() { return mPrev; } 1.3312 + 1.3313 + void SetPreviousWeakFrame(nsWeakFrame* aPrev) { mPrev = aPrev; } 1.3314 + 1.3315 + ~nsWeakFrame() 1.3316 + { 1.3317 + Clear(mFrame ? mFrame->PresContext()->GetPresShell() : nullptr); 1.3318 + } 1.3319 +private: 1.3320 + void Init(nsIFrame* aFrame); 1.3321 + 1.3322 + nsWeakFrame* mPrev; 1.3323 + nsIFrame* mFrame; 1.3324 +}; 1.3325 + 1.3326 +inline bool 1.3327 +nsFrameList::ContinueRemoveFrame(nsIFrame* aFrame) 1.3328 +{ 1.3329 + MOZ_ASSERT(!aFrame->GetPrevSibling() || !aFrame->GetNextSibling(), 1.3330 + "Forgot to call StartRemoveFrame?"); 1.3331 + if (aFrame == mLastChild) { 1.3332 + MOZ_ASSERT(!aFrame->GetNextSibling(), "broken frame list"); 1.3333 + nsIFrame* prevSibling = aFrame->GetPrevSibling(); 1.3334 + if (!prevSibling) { 1.3335 + MOZ_ASSERT(aFrame == mFirstChild, "broken frame list"); 1.3336 + mFirstChild = mLastChild = nullptr; 1.3337 + return true; 1.3338 + } 1.3339 + MOZ_ASSERT(prevSibling->GetNextSibling() == aFrame, "Broken frame linkage"); 1.3340 + prevSibling->SetNextSibling(nullptr); 1.3341 + mLastChild = prevSibling; 1.3342 + return true; 1.3343 + } 1.3344 + if (aFrame == mFirstChild) { 1.3345 + MOZ_ASSERT(!aFrame->GetPrevSibling(), "broken frame list"); 1.3346 + mFirstChild = aFrame->GetNextSibling(); 1.3347 + aFrame->SetNextSibling(nullptr); 1.3348 + MOZ_ASSERT(mFirstChild, "broken frame list"); 1.3349 + return true; 1.3350 + } 1.3351 + return false; 1.3352 +} 1.3353 + 1.3354 +inline bool 1.3355 +nsFrameList::StartRemoveFrame(nsIFrame* aFrame) 1.3356 +{ 1.3357 + if (aFrame->GetPrevSibling() && aFrame->GetNextSibling()) { 1.3358 + UnhookFrameFromSiblings(aFrame); 1.3359 + return true; 1.3360 + } 1.3361 + return ContinueRemoveFrame(aFrame); 1.3362 +} 1.3363 + 1.3364 +inline void 1.3365 +nsFrameList::Enumerator::Next() 1.3366 +{ 1.3367 + NS_ASSERTION(!AtEnd(), "Should have checked AtEnd()!"); 1.3368 + mFrame = mFrame->GetNextSibling(); 1.3369 +} 1.3370 + 1.3371 +inline 1.3372 +nsFrameList::FrameLinkEnumerator:: 1.3373 +FrameLinkEnumerator(const nsFrameList& aList, nsIFrame* aPrevFrame) 1.3374 + : Enumerator(aList) 1.3375 +{ 1.3376 + mPrev = aPrevFrame; 1.3377 + mFrame = aPrevFrame ? aPrevFrame->GetNextSibling() : aList.FirstChild(); 1.3378 +} 1.3379 + 1.3380 +inline void 1.3381 +nsFrameList::FrameLinkEnumerator::Next() 1.3382 +{ 1.3383 + mPrev = mFrame; 1.3384 + Enumerator::Next(); 1.3385 +} 1.3386 + 1.3387 +// Helper-functions for nsIFrame::SortFrameList() 1.3388 +// --------------------------------------------------- 1.3389 + 1.3390 +template<bool IsLessThanOrEqual(nsIFrame*, nsIFrame*)> 1.3391 +/* static */ nsIFrame* 1.3392 +nsIFrame::SortedMerge(nsIFrame *aLeft, nsIFrame *aRight) 1.3393 +{ 1.3394 + NS_PRECONDITION(aLeft && aRight, "SortedMerge must have non-empty lists"); 1.3395 + 1.3396 + nsIFrame *result; 1.3397 + // Unroll first iteration to avoid null-check 'result' inside the loop. 1.3398 + if (IsLessThanOrEqual(aLeft, aRight)) { 1.3399 + result = aLeft; 1.3400 + aLeft = aLeft->GetNextSibling(); 1.3401 + if (!aLeft) { 1.3402 + result->SetNextSibling(aRight); 1.3403 + return result; 1.3404 + } 1.3405 + } 1.3406 + else { 1.3407 + result = aRight; 1.3408 + aRight = aRight->GetNextSibling(); 1.3409 + if (!aRight) { 1.3410 + result->SetNextSibling(aLeft); 1.3411 + return result; 1.3412 + } 1.3413 + } 1.3414 + 1.3415 + nsIFrame *last = result; 1.3416 + for (;;) { 1.3417 + if (IsLessThanOrEqual(aLeft, aRight)) { 1.3418 + last->SetNextSibling(aLeft); 1.3419 + last = aLeft; 1.3420 + aLeft = aLeft->GetNextSibling(); 1.3421 + if (!aLeft) { 1.3422 + last->SetNextSibling(aRight); 1.3423 + return result; 1.3424 + } 1.3425 + } 1.3426 + else { 1.3427 + last->SetNextSibling(aRight); 1.3428 + last = aRight; 1.3429 + aRight = aRight->GetNextSibling(); 1.3430 + if (!aRight) { 1.3431 + last->SetNextSibling(aLeft); 1.3432 + return result; 1.3433 + } 1.3434 + } 1.3435 + } 1.3436 +} 1.3437 + 1.3438 +template<bool IsLessThanOrEqual(nsIFrame*, nsIFrame*)> 1.3439 +/* static */ nsIFrame* 1.3440 +nsIFrame::MergeSort(nsIFrame *aSource) 1.3441 +{ 1.3442 + NS_PRECONDITION(aSource, "MergeSort null arg"); 1.3443 + 1.3444 + nsIFrame *sorted[32] = { nullptr }; 1.3445 + nsIFrame **fill = &sorted[0]; 1.3446 + nsIFrame **left; 1.3447 + nsIFrame *rest = aSource; 1.3448 + 1.3449 + do { 1.3450 + nsIFrame *current = rest; 1.3451 + rest = rest->GetNextSibling(); 1.3452 + current->SetNextSibling(nullptr); 1.3453 + 1.3454 + // Merge it with sorted[0] if present; then merge the result with sorted[1] etc. 1.3455 + // sorted[0] is a list of length 1 (or nullptr). 1.3456 + // sorted[1] is a list of length 2 (or nullptr). 1.3457 + // sorted[2] is a list of length 4 (or nullptr). etc. 1.3458 + for (left = &sorted[0]; left != fill && *left; ++left) { 1.3459 + current = SortedMerge<IsLessThanOrEqual>(*left, current); 1.3460 + *left = nullptr; 1.3461 + } 1.3462 + 1.3463 + // Fill the empty slot that we couldn't merge with the last result. 1.3464 + *left = current; 1.3465 + 1.3466 + if (left == fill) 1.3467 + ++fill; 1.3468 + } while (rest); 1.3469 + 1.3470 + // Collect and merge the results. 1.3471 + nsIFrame *result = nullptr; 1.3472 + for (left = &sorted[0]; left != fill; ++left) { 1.3473 + if (*left) { 1.3474 + result = result ? SortedMerge<IsLessThanOrEqual>(*left, result) : *left; 1.3475 + } 1.3476 + } 1.3477 + return result; 1.3478 +} 1.3479 + 1.3480 +template<bool IsLessThanOrEqual(nsIFrame*, nsIFrame*)> 1.3481 +/* static */ void 1.3482 +nsIFrame::SortFrameList(nsFrameList& aFrameList) 1.3483 +{ 1.3484 + nsIFrame* head = MergeSort<IsLessThanOrEqual>(aFrameList.FirstChild()); 1.3485 + aFrameList = nsFrameList(head, nsLayoutUtils::GetLastSibling(head)); 1.3486 + MOZ_ASSERT(IsFrameListSorted<IsLessThanOrEqual>(aFrameList), 1.3487 + "After we sort a frame list, it should be in sorted order..."); 1.3488 +} 1.3489 + 1.3490 +template<bool IsLessThanOrEqual(nsIFrame*, nsIFrame*)> 1.3491 +/* static */ bool 1.3492 +nsIFrame::IsFrameListSorted(nsFrameList& aFrameList) 1.3493 +{ 1.3494 + if (aFrameList.IsEmpty()) { 1.3495 + // empty lists are trivially sorted. 1.3496 + return true; 1.3497 + } 1.3498 + 1.3499 + // We'll walk through the list with two iterators, one trailing behind the 1.3500 + // other. The list is sorted IFF trailingIter <= iter, across the whole list. 1.3501 + nsFrameList::Enumerator trailingIter(aFrameList); 1.3502 + nsFrameList::Enumerator iter(aFrameList); 1.3503 + iter.Next(); // Skip |iter| past first frame. (List is nonempty, so we can.) 1.3504 + 1.3505 + // Now, advance the iterators in parallel, comparing each adjacent pair. 1.3506 + while (!iter.AtEnd()) { 1.3507 + MOZ_ASSERT(!trailingIter.AtEnd(), "trailing iter shouldn't finish first"); 1.3508 + if (!IsLessThanOrEqual(trailingIter.get(), iter.get())) { 1.3509 + return false; 1.3510 + } 1.3511 + trailingIter.Next(); 1.3512 + iter.Next(); 1.3513 + } 1.3514 + 1.3515 + // We made it to the end without returning early, so the list is sorted. 1.3516 + return true; 1.3517 +} 1.3518 + 1.3519 +#endif /* nsIFrame_h___ */