tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

nsSplittableFrame.h (6392B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 /*
      8 * base class for rendering objects that can be split across lines,
      9 * columns, or pages
     10 */
     11 
     12 #ifndef nsSplittableFrame_h___
     13 #define nsSplittableFrame_h___
     14 
     15 #include "nsIFrame.h"
     16 
     17 // Derived class that allows splitting
     18 class nsSplittableFrame : public nsIFrame {
     19 public:
     20  NS_DECL_ABSTRACT_FRAME(nsSplittableFrame)
     21  NS_DECL_QUERYFRAME_TARGET(nsSplittableFrame)
     22  NS_DECL_QUERYFRAME
     23 
     24  void Init(nsIContent* aContent, nsContainerFrame* aParent,
     25            nsIFrame* aPrevInFlow) override;
     26 
     27  void Destroy(DestroyContext&) override;
     28 
     29  /*
     30   * Frame continuations can be either fluid or non-fluid.
     31   *
     32   * Fluid continuations ("in-flows") are the result of line breaking,
     33   * column breaking, or page breaking.
     34   *
     35   * Non-fluid continuations can be the result of BiDi frame splitting,
     36   * column-span splitting, or <col span="N"> where N > 1.
     37   *
     38   * A "flow" is a chain of fluid continuations.
     39   *
     40   * For more information, see
     41   * https://firefox-source-docs.mozilla.org/layout/LayoutOverview.html#fragmentation
     42   */
     43 
     44  // Get the previous/next continuation, regardless of its type (fluid or
     45  // non-fluid).
     46  nsIFrame* GetPrevContinuation() const final;
     47  nsIFrame* GetNextContinuation() const final;
     48 
     49  // Set a previous non-fluid continuation.
     50  //
     51  // WARNING: this method updates caches for next-continuations, so it has O(n)
     52  // time complexity over the length of next-continuations in the chain.
     53  void SetPrevContinuation(nsIFrame*) final;
     54 
     55  // Set a next non-fluid continuation.
     56  void SetNextContinuation(nsIFrame*) final;
     57 
     58  // Get the first/last continuation for this frame.
     59  nsIFrame* FirstContinuation() const final;
     60  nsIFrame* LastContinuation() const final;
     61 
     62 #ifdef DEBUG
     63  // Can aFrame2 be reached from aFrame1 by following prev/next continuations?
     64  static bool IsInPrevContinuationChain(nsIFrame* aFrame1, nsIFrame* aFrame2);
     65  static bool IsInNextContinuationChain(nsIFrame* aFrame1, nsIFrame* aFrame2);
     66 #endif
     67 
     68  // Get the previous/next continuation, only if it is fluid (an "in-flow").
     69  nsIFrame* GetPrevInFlow() const final;
     70  nsIFrame* GetNextInFlow() const final;
     71 
     72  // Set a previous fluid continuation.
     73  //
     74  // WARNING: this method updates caches for next-continuations, so it has O(n)
     75  // time complexity over the length of next-continuations in the chain.
     76  void SetPrevInFlow(nsIFrame*) final;
     77 
     78  // Set a next fluid continuation.
     79  void SetNextInFlow(nsIFrame*) final;
     80 
     81  // Get the first/last frame in the current flow.
     82  nsIFrame* FirstInFlow() const final;
     83  nsIFrame* LastInFlow() const final;
     84 
     85  // Remove the frame from the flow. Connects the frame's prev-in-flow and its
     86  // next-in-flow. This should only be called during frame destruction, e.g. in
     87  // frame's Destroy() method.
     88  static void RemoveFromFlow(nsIFrame* aFrame);
     89 
     90  /**
     91   * A version of GetLogicalSkipSides() that is intended to be used inside
     92   * Reflow before it's known if |this| frame will be COMPLETE or not.
     93   * It returns a result that assumes this fragment is the last and thus
     94   * should apply the block-end border/padding etc (except for "true" overflow
     95   * containers which always skip block sides).  You're then expected to
     96   * recalculate the block-end side (as needed) when you know |this| frame's
     97   * reflow status is INCOMPLETE.
     98   * This method is intended for frames that break in the block axis.
     99   */
    100  LogicalSides PreReflowBlockLevelLogicalSkipSides() const {
    101    return GetBlockLevelLogicalSkipSides(false);
    102  };
    103 
    104 protected:
    105  nsSplittableFrame(ComputedStyle* aStyle, nsPresContext* aPresContext,
    106                    ClassID aID)
    107      : nsIFrame(aStyle, aPresContext, aID) {}
    108 
    109  // Update the first-continuation and first-in-flow cache for this frame and
    110  // the next-continuations in the chain.
    111  //
    112  // Note: this function assumes that the first-continuation and first-in-flow
    113  // caches are already up-to-date on this frame's
    114  // prev-continuation/prev-in-flow frame (if there is such a frame).
    115  void UpdateFirstContinuationAndFirstInFlowCache();
    116 
    117  /**
    118   * Return the sum of the block-axis content size of our previous
    119   * continuations.
    120   *
    121   * Classes that call this are _required_ to call this at least once for each
    122   * reflow (unless you're the first continuation, in which case you can skip
    123   * it, because as an optimization we don't cache it there).
    124   *
    125   * This guarantees that the internal cache works, by refreshing it. Calling it
    126   * multiple times in the same reflow is wasteful, but not an error.
    127   */
    128  nscoord CalcAndCacheConsumedBSize();
    129 
    130  /**
    131   * This static wrapper over CalcAndCacheConsumedBSize() is intended for a
    132   * specific scenario where an nsSplittableFrame's subclass needs to access
    133   * another subclass' consumed block-size. For ordinary use cases,
    134   * CalcAndCacheConsumedBSize() should be called.
    135   *
    136   * This has the same requirements as CalcAndCacheConsumedBSize(). In
    137   * particular, classes that call this are _required_ to call this at least
    138   * once for each reflow.
    139   */
    140  static nscoord ConsumedBSize(nsSplittableFrame* aFrame) {
    141    return aFrame->CalcAndCacheConsumedBSize();
    142  }
    143 
    144  /**
    145   * Retrieve the effective computed block size of this frame, which is the
    146   * computed block size, minus the block size consumed by any previous
    147   * continuations.
    148   */
    149  nscoord GetEffectiveComputedBSize(const ReflowInput& aReflowInput,
    150                                    nscoord aConsumed) const;
    151 
    152  /**
    153   * @see nsIFrame::GetLogicalSkipSides()
    154   */
    155  LogicalSides GetLogicalSkipSides() const override {
    156    return GetBlockLevelLogicalSkipSides(true);
    157  }
    158 
    159  LogicalSides GetBlockLevelLogicalSkipSides(bool aAfterReflow) const;
    160 
    161  nsIFrame* mPrevContinuation = nullptr;
    162  nsIFrame* mNextContinuation = nullptr;
    163 
    164  /**
    165   * Cached pointers to the first-continuation and first-in-flow, if currently
    166   * known. These may be null, in which case the first-* will need to be found
    167   * by following the chain.
    168   */
    169  nsIFrame* mFirstContinuation = nullptr;
    170  nsIFrame* mFirstInFlow = nullptr;
    171 };
    172 
    173 #endif /* nsSplittableFrame_h___ */