layout/generic/nsIFrame.h

changeset 0
6474c204b198
     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___ */

mercurial