LCOV - code coverage report
Current view: top level - layout/generic - WritingModes.h (source / functions) Hit Total Coverage
Test: output.info Lines: 388 680 57.1 %
Date: 2017-07-14 16:53:18 Functions: 139 209 66.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : #ifndef WritingModes_h_
       7             : #define WritingModes_h_
       8             : 
       9             : #include "nsRect.h"
      10             : #include "nsStyleContext.h"
      11             : #include "nsStyleContextInlines.h"
      12             : #include "nsBidiUtils.h"
      13             : 
      14             : // It is the caller's responsibility to operate on logical-coordinate objects
      15             : // with matched writing modes. Failure to do so will be a runtime bug; the
      16             : // compiler can't catch it, but in debug mode, we'll throw an assertion.
      17             : // NOTE that in non-debug builds, a writing mode mismatch error will NOT be
      18             : // detected, yet the results will be nonsense (and may lead to further layout
      19             : // failures). Therefore, it is important to test (and fuzz-test) writing-mode
      20             : // support using debug builds.
      21             : 
      22             : // Methods in logical-coordinate classes that take another logical-coordinate
      23             : // object as a parameter should call CHECK_WRITING_MODE on it to verify that
      24             : // the writing modes match.
      25             : // (In some cases, there are internal (private) methods that don't do this;
      26             : // such methods should only be used by other methods that have already checked
      27             : // the writing modes.)
      28             : // The check ignores the eSidewaysMask bit of writing mode, because this does
      29             : // not affect the interpretation of logical coordinates.
      30             : 
      31             : #define CHECK_WRITING_MODE(param) \
      32             :    NS_ASSERTION(param.IgnoreSideways() == GetWritingMode().IgnoreSideways(), \
      33             :                 "writing-mode mismatch")
      34             : 
      35             : namespace mozilla {
      36             : 
      37             : namespace widget {
      38             : struct IMENotification;
      39             : } // namespace widget
      40             : 
      41             : // Physical axis constants.
      42             : enum PhysicalAxis {
      43             :   eAxisVertical      = 0x0,
      44             :   eAxisHorizontal    = 0x1
      45             : };
      46             : 
      47           0 : inline LogicalAxis GetOrthogonalAxis(LogicalAxis aAxis)
      48             : {
      49           0 :   return aAxis == eLogicalAxisBlock ? eLogicalAxisInline : eLogicalAxisBlock;
      50             : }
      51             : 
      52        2482 : inline bool IsInline(LogicalSide aSide) { return aSide & 0x2; }
      53        2482 : inline bool IsBlock(LogicalSide aSide) { return !IsInline(aSide); }
      54        2482 : inline bool IsEnd(LogicalSide aSide) { return aSide & 0x1; }
      55             : inline bool IsStart(LogicalSide aSide) { return !IsEnd(aSide); }
      56             : 
      57           0 : inline LogicalAxis GetAxis(LogicalSide aSide)
      58             : {
      59           0 :   return IsInline(aSide) ? eLogicalAxisInline : eLogicalAxisBlock;
      60             : }
      61             : 
      62        2482 : inline LogicalEdge GetEdge(LogicalSide aSide)
      63             : {
      64        2482 :   return IsEnd(aSide) ? eLogicalEdgeEnd : eLogicalEdgeStart;
      65             : }
      66             : 
      67           0 : inline LogicalEdge GetOppositeEdge(LogicalEdge aEdge)
      68             : {
      69             :   // This relies on the only two LogicalEdge enum values being 0 and 1.
      70           0 :   return LogicalEdge(1 - aEdge);
      71             : }
      72             : 
      73             : inline LogicalSide
      74         154 : MakeLogicalSide(LogicalAxis aAxis, LogicalEdge aEdge)
      75             : {
      76         154 :   return LogicalSide((aAxis << 1) | aEdge);
      77             : }
      78             : 
      79           0 : inline LogicalSide GetOppositeSide(LogicalSide aSide)
      80             : {
      81           0 :   return MakeLogicalSide(GetAxis(aSide), GetOppositeEdge(GetEdge(aSide)));
      82             : }
      83             : 
      84             : enum LogicalSideBits {
      85             :   eLogicalSideBitsNone   = 0,
      86             :   eLogicalSideBitsBStart = 1 << eLogicalSideBStart,
      87             :   eLogicalSideBitsBEnd   = 1 << eLogicalSideBEnd,
      88             :   eLogicalSideBitsIEnd   = 1 << eLogicalSideIEnd,
      89             :   eLogicalSideBitsIStart = 1 << eLogicalSideIStart,
      90             :   eLogicalSideBitsBBoth = eLogicalSideBitsBStart | eLogicalSideBitsBEnd,
      91             :   eLogicalSideBitsIBoth = eLogicalSideBitsIStart | eLogicalSideBitsIEnd,
      92             :   eLogicalSideBitsAll = eLogicalSideBitsBBoth | eLogicalSideBitsIBoth
      93             : };
      94             : 
      95             : enum LineRelativeDir {
      96             :   eLineRelativeDirOver  = eLogicalSideBStart,
      97             :   eLineRelativeDirUnder = eLogicalSideBEnd,
      98             :   eLineRelativeDirLeft  = eLogicalSideIStart,
      99             :   eLineRelativeDirRight = eLogicalSideIEnd
     100             : };
     101             : 
     102             : /**
     103             :  * LogicalSides represents a set of logical sides.
     104             :  */
     105             : struct LogicalSides final {
     106        2398 :   LogicalSides() : mBits(0) {}
     107           0 :   explicit LogicalSides(LogicalSideBits aSideBits)
     108           0 :   {
     109           0 :     MOZ_ASSERT((aSideBits & ~eLogicalSideBitsAll) == 0, "illegal side bits");
     110           0 :     mBits = aSideBits;
     111           0 :   }
     112             :   bool IsEmpty() const { return mBits == 0; }
     113        2550 :   bool BStart()  const { return mBits & eLogicalSideBitsBStart; }
     114        2550 :   bool BEnd()    const { return mBits & eLogicalSideBitsBEnd; }
     115        2398 :   bool IStart()  const { return mBits & eLogicalSideBitsIStart; }
     116        2398 :   bool IEnd()    const { return mBits & eLogicalSideBitsIEnd; }
     117             :   bool Contains(LogicalSideBits aSideBits) const
     118             :   {
     119             :     MOZ_ASSERT((aSideBits & ~eLogicalSideBitsAll) == 0, "illegal side bits");
     120             :     return (mBits & aSideBits) == aSideBits;
     121             :   }
     122           0 :   LogicalSides operator|(LogicalSides aOther) const
     123             :   {
     124           0 :     return LogicalSides(LogicalSideBits(mBits | aOther.mBits));
     125             :   }
     126             :   LogicalSides operator|(LogicalSideBits aSideBits) const
     127             :   {
     128             :     return *this | LogicalSides(aSideBits);
     129             :   }
     130           0 :   LogicalSides& operator|=(LogicalSides aOther)
     131             :   {
     132           0 :     mBits |= aOther.mBits;
     133           0 :     return *this;
     134             :   }
     135           0 :   LogicalSides& operator|=(LogicalSideBits aSideBits)
     136             :   {
     137           0 :     return *this |= LogicalSides(aSideBits);
     138             :   }
     139           0 :   bool operator==(LogicalSides aOther) const
     140             :   {
     141           0 :     return mBits == aOther.mBits;
     142             :   }
     143           0 :   bool operator!=(LogicalSides aOther) const
     144             :   {
     145           0 :     return !(*this == aOther);
     146             :   }
     147             : 
     148             : private:
     149             :   uint8_t mBits;
     150             : };
     151             : 
     152             : /**
     153             :  * mozilla::WritingMode is an immutable class representing a
     154             :  * writing mode.
     155             :  *
     156             :  * It efficiently stores the writing mode and can rapidly compute
     157             :  * interesting things about it for use in layout.
     158             :  *
     159             :  * Writing modes are computed from the CSS 'direction',
     160             :  * 'writing-mode', and 'text-orientation' properties.
     161             :  * See CSS3 Writing Modes for more information
     162             :  *   http://www.w3.org/TR/css3-writing-modes/
     163             :  */
     164             : class WritingMode {
     165             : public:
     166             :   /**
     167             :    * Absolute inline flow direction
     168             :    */
     169             :   enum InlineDir {
     170             :     eInlineLTR = 0x00, // text flows horizontally left to right
     171             :     eInlineRTL = 0x02, // text flows horizontally right to left
     172             :     eInlineTTB = 0x01, // text flows vertically top to bottom
     173             :     eInlineBTT = 0x03, // text flows vertically bottom to top
     174             :   };
     175             : 
     176             :   /**
     177             :    * Absolute block flow direction
     178             :    */
     179             :   enum BlockDir {
     180             :     eBlockTB = 0x00, // horizontal lines stack top to bottom
     181             :     eBlockRL = 0x01, // vertical lines stack right to left
     182             :     eBlockLR = 0x05, // vertical lines stack left to right
     183             :   };
     184             : 
     185             :   /**
     186             :    * Line-relative (bidi-relative) inline flow direction
     187             :    */
     188             :   enum BidiDir {
     189             :     eBidiLTR = 0x00, // inline flow matches bidi LTR text
     190             :     eBidiRTL = 0x10, // inline flow matches bidi RTL text
     191             :   };
     192             : 
     193             :   /**
     194             :    * Unknown writing mode (should never actually be stored or used anywhere).
     195             :    */
     196             :   enum {
     197             :     eUnknownWritingMode = 0xff
     198             :   };
     199             : 
     200             :   /**
     201             :    * Return the absolute inline flow direction as an InlineDir
     202             :    */
     203           0 :   InlineDir GetInlineDir() const { return InlineDir(mWritingMode & eInlineMask); }
     204             : 
     205             :   /**
     206             :    * Return the absolute block flow direction as a BlockDir
     207             :    */
     208        1790 :   BlockDir GetBlockDir() const { return BlockDir(mWritingMode & eBlockMask); }
     209             : 
     210             :   /**
     211             :    * Return the line-relative inline flow direction as a BidiDir
     212             :    */
     213        3372 :   BidiDir GetBidiDir() const { return BidiDir(mWritingMode & eBidiMask); }
     214             : 
     215             :   /**
     216             :    * Return true if the inline flow direction is against physical direction
     217             :    * (i.e. right-to-left or bottom-to-top).
     218             :    * This occurs when writing-mode is sideways-lr OR direction is rtl (but not
     219             :    * if both of those are true).
     220             :    */
     221        9140 :   bool IsInlineReversed() const { return !!(mWritingMode & eInlineFlowMask); }
     222             : 
     223             :   /**
     224             :    * Return true if bidi direction is LTR. (Convenience method)
     225             :    */
     226        3372 :   bool IsBidiLTR() const { return eBidiLTR == GetBidiDir(); }
     227             : 
     228             :   /**
     229             :    * True if vertical-mode block direction is LR (convenience method).
     230             :    */
     231           0 :   bool IsVerticalLR() const { return eBlockLR == GetBlockDir(); }
     232             : 
     233             :   /**
     234             :    * True if vertical-mode block direction is RL (convenience method).
     235             :    */
     236        1016 :   bool IsVerticalRL() const { return eBlockRL == GetBlockDir(); }
     237             : 
     238             :   /**
     239             :    * True if vertical writing mode, i.e. when
     240             :    * writing-mode: vertical-lr | vertical-rl.
     241             :    */
     242       58890 :   bool IsVertical() const { return !!(mWritingMode & eOrientationMask); }
     243             : 
     244             :   /**
     245             :    * True if line-over/line-under are inverted from block-start/block-end.
     246             :    * This is true only when writing-mode is vertical-lr.
     247             :    */
     248         770 :   bool IsLineInverted() const { return !!(mWritingMode & eLineOrientMask); }
     249             : 
     250             :   /**
     251             :    * Block-axis flow-relative to line-relative factor.
     252             :    * May be used as a multiplication factor for block-axis coordinates
     253             :    * to convert between flow- and line-relative coordinate systems (e.g.
     254             :    * positioning an over- or under-line decoration).
     255             :    */
     256           0 :   int FlowRelativeToLineRelativeFactor() const
     257             :   {
     258           0 :     return IsLineInverted() ? -1 : 1;
     259             :   }
     260             : 
     261             :   /**
     262             :    * True if the text-orientation will force all text to be rendered sideways
     263             :    * in vertical lines, in which case we should prefer an alphabetic baseline;
     264             :    * otherwise, the default is centered.
     265             :    * Note that some glyph runs may be rendered sideways even if this is false,
     266             :    * due to text-orientation:mixed resolution, but in that case the dominant
     267             :    * baseline remains centered.
     268             :    */
     269           0 :   bool IsSideways() const { return !!(mWritingMode & eSidewaysMask); }
     270             : 
     271             : #ifdef DEBUG // Used by CHECK_WRITING_MODE to compare modes without regard
     272             :              // for the eSidewaysMask flag.
     273       79918 :   WritingMode IgnoreSideways() const {
     274       79918 :     return WritingMode(mWritingMode & ~eSidewaysMask);
     275             :   }
     276             : #endif
     277             : 
     278             :   /**
     279             :    * Return true if boxes with this writing mode should use central baselines.
     280             :    */
     281          30 :   bool IsCentralBaseline() const { return IsVertical() && !IsSideways(); }
     282             : 
     283             :   /**
     284             :    * Return true if boxes with this writing mode should use alphabetical
     285             :    * baselines.
     286             :    */
     287          30 :   bool IsAlphabeticalBaseline() const { return !IsCentralBaseline(); }
     288             : 
     289             : 
     290          50 :   static mozilla::PhysicalAxis PhysicalAxisForLogicalAxis(
     291             :                                               uint8_t aWritingModeValue,
     292             :                                               LogicalAxis aAxis)
     293             :   {
     294             :     // This relies on bit 0 of a writing-value mode indicating vertical
     295             :     // orientation and bit 0 of a LogicalAxis value indicating the inline axis,
     296             :     // so that it can correctly form mozilla::PhysicalAxis values using bit
     297             :     // manipulation.
     298             :     static_assert(NS_STYLE_WRITING_MODE_HORIZONTAL_TB == 0 &&
     299             :                   NS_STYLE_WRITING_MODE_VERTICAL_RL == 1 &&
     300             :                   NS_STYLE_WRITING_MODE_VERTICAL_LR == 3 &&
     301             :                   eLogicalAxisBlock == 0 &&
     302             :                   eLogicalAxisInline == 1 &&
     303             :                   eAxisVertical == 0 &&
     304             :                   eAxisHorizontal == 1,
     305             :                   "unexpected writing-mode, logical axis or physical axis "
     306             :                   "constant values");
     307          50 :     return mozilla::PhysicalAxis((aWritingModeValue ^ aAxis) & 0x1);
     308             :   }
     309             : 
     310          50 :   mozilla::PhysicalAxis PhysicalAxis(LogicalAxis aAxis) const
     311             :   {
     312             :     // This will set wm to either NS_STYLE_WRITING_MODE_HORIZONTAL_TB or
     313             :     // NS_STYLE_WRITING_MODE_VERTICAL_RL, and not the other two (real
     314             :     // and hypothetical) values.  But this is fine; we only need to
     315             :     // distinguish between vertical and horizontal in
     316             :     // PhysicalAxisForLogicalAxis.
     317          50 :     int wm = mWritingMode & eOrientationMask;
     318          50 :     return PhysicalAxisForLogicalAxis(wm, aAxis);
     319             :   }
     320             : 
     321        2174 :   static mozilla::Side PhysicalSideForBlockAxis(uint8_t aWritingModeValue,
     322             :                                                 LogicalEdge aEdge)
     323             :   {
     324             :     // indexes are NS_STYLE_WRITING_MODE_* values, which are the same as these
     325             :     // two-bit values:
     326             :     //   bit 0 = the eOrientationMask value
     327             :     //   bit 1 = the eBlockFlowMask value
     328             :     static const mozilla::Side kLogicalBlockSides[][2] = {
     329             :       { eSideTop,    eSideBottom },  // horizontal-tb
     330             :       { eSideRight,  eSideLeft   },  // vertical-rl
     331             :       { eSideBottom, eSideTop    },  // (horizontal-bt)
     332             :       { eSideLeft,   eSideRight  },  // vertical-lr
     333             :     };
     334             : 
     335             :     // Ignore the SIDEWAYS_MASK bit of the writing-mode value, as this has no
     336             :     // effect on the side mappings.
     337        2174 :     aWritingModeValue &= ~NS_STYLE_WRITING_MODE_SIDEWAYS_MASK;
     338             : 
     339             :     // What's left of the writing-mode should be in the range 0-3:
     340        2174 :     NS_ASSERTION(aWritingModeValue < 4, "invalid aWritingModeValue value");
     341             : 
     342        2174 :     return kLogicalBlockSides[aWritingModeValue][aEdge];
     343             :   }
     344             : 
     345         510 :   mozilla::Side PhysicalSideForInlineAxis(LogicalEdge aEdge) const
     346             :   {
     347             :     // indexes are four-bit values:
     348             :     //   bit 0 = the eOrientationMask value
     349             :     //   bit 1 = the eInlineFlowMask value
     350             :     //   bit 2 = the eBlockFlowMask value
     351             :     //   bit 3 = the eLineOrientMask value
     352             :     // Not all of these combinations can actually be specified via CSS: there
     353             :     // is no horizontal-bt writing-mode, and no text-orientation value that
     354             :     // produces "inverted" text. (The former 'sideways-left' value, no longer
     355             :     // in the spec, would have produced this in vertical-rl mode.)
     356             :     static const mozilla::Side kLogicalInlineSides[][2] = {
     357             :       { eSideLeft,   eSideRight  },  // horizontal-tb               ltr
     358             :       { eSideTop,    eSideBottom },  // vertical-rl                 ltr
     359             :       { eSideRight,  eSideLeft   },  // horizontal-tb               rtl
     360             :       { eSideBottom, eSideTop    },  // vertical-rl                 rtl
     361             :       { eSideRight,  eSideLeft   },  // (horizontal-bt)  (inverted) ltr
     362             :       { eSideTop,    eSideBottom },  // sideways-lr                 rtl
     363             :       { eSideLeft,   eSideRight  },  // (horizontal-bt)  (inverted) rtl
     364             :       { eSideBottom, eSideTop    },  // sideways-lr                 ltr
     365             :       { eSideLeft,   eSideRight  },  // horizontal-tb    (inverted) rtl
     366             :       { eSideTop,    eSideBottom },  // vertical-rl      (inverted) rtl
     367             :       { eSideRight,  eSideLeft   },  // horizontal-tb    (inverted) ltr
     368             :       { eSideBottom, eSideTop    },  // vertical-rl      (inverted) ltr
     369             :       { eSideLeft,   eSideRight  },  // (horizontal-bt)             ltr
     370             :       { eSideTop,    eSideBottom },  // vertical-lr                 ltr
     371             :       { eSideRight,  eSideLeft   },  // (horizontal-bt)             rtl
     372             :       { eSideBottom, eSideTop    },  // vertical-lr                 rtl
     373             :     };
     374             : 
     375             :     // Inline axis sides depend on all three of writing-mode, text-orientation
     376             :     // and direction, which are encoded in the eOrientationMask,
     377             :     // eInlineFlowMask, eBlockFlowMask and eLineOrientMask bits.  Use these four
     378             :     // bits to index into kLogicalInlineSides.
     379             :     static_assert(eOrientationMask == 0x01 && eInlineFlowMask == 0x02 &&
     380             :                   eBlockFlowMask == 0x04 && eLineOrientMask == 0x08,
     381             :                   "unexpected mask values");
     382         510 :     int index = mWritingMode & 0x0F;
     383         510 :     return kLogicalInlineSides[index][aEdge];
     384             :   }
     385             : 
     386             :   /**
     387             :    * Returns the physical side corresponding to the specified logical side,
     388             :    * given the current writing mode.
     389             :    */
     390        2482 :   mozilla::Side PhysicalSide(LogicalSide aSide) const
     391             :   {
     392        2482 :     if (IsBlock(aSide)) {
     393             :       static_assert(eOrientationMask == 0x01 && eBlockFlowMask == 0x04,
     394             :                     "unexpected mask values");
     395        2174 :       int wm = ((mWritingMode & eBlockFlowMask) >> 1) |
     396        2174 :                (mWritingMode & eOrientationMask);
     397        2174 :       return PhysicalSideForBlockAxis(wm, GetEdge(aSide));
     398             :     }
     399             : 
     400         308 :     return PhysicalSideForInlineAxis(GetEdge(aSide));
     401             :   }
     402             : 
     403             :   /**
     404             :    * Returns the logical side corresponding to the specified physical side,
     405             :    * given the current writing mode.
     406             :    * (This is the inverse of the PhysicalSide() method above.)
     407             :    */
     408           0 :   LogicalSide LogicalSideForPhysicalSide(mozilla::Side aSide) const
     409             :   {
     410             :     // indexes are four-bit values:
     411             :     //   bit 0 = the eOrientationMask value
     412             :     //   bit 1 = the eInlineFlowMask value
     413             :     //   bit 2 = the eBlockFlowMask value
     414             :     //   bit 3 = the eLineOrientMask value
     415             :     static const LogicalSide kPhysicalToLogicalSides[][4] = {
     416             :       // top                right
     417             :       // bottom             left
     418             :       { eLogicalSideBStart, eLogicalSideIEnd,
     419             :         eLogicalSideBEnd,   eLogicalSideIStart },  // horizontal-tb         ltr
     420             :       { eLogicalSideIStart, eLogicalSideBStart,
     421             :         eLogicalSideIEnd,   eLogicalSideBEnd   },  // vertical-rl           ltr
     422             :       { eLogicalSideBStart, eLogicalSideIStart,
     423             :         eLogicalSideBEnd,   eLogicalSideIEnd   },  // horizontal-tb         rtl
     424             :       { eLogicalSideIEnd,   eLogicalSideBStart,
     425             :         eLogicalSideIStart, eLogicalSideBEnd   },  // vertical-rl           rtl
     426             :       { eLogicalSideBEnd,   eLogicalSideIStart,
     427             :         eLogicalSideBStart, eLogicalSideIEnd   },  // (horizontal-bt) (inv) ltr
     428             :       { eLogicalSideIStart, eLogicalSideBEnd,
     429             :         eLogicalSideIEnd,   eLogicalSideBStart },  // vertical-lr   sw-left rtl
     430             :       { eLogicalSideBEnd,   eLogicalSideIEnd,
     431             :         eLogicalSideBStart, eLogicalSideIStart },  // (horizontal-bt) (inv) rtl
     432             :       { eLogicalSideIEnd,   eLogicalSideBEnd,
     433             :         eLogicalSideIStart, eLogicalSideBStart },  // vertical-lr   sw-left ltr
     434             :       { eLogicalSideBStart, eLogicalSideIEnd,
     435             :         eLogicalSideBEnd,   eLogicalSideIStart },  // horizontal-tb   (inv) rtl
     436             :       { eLogicalSideIStart, eLogicalSideBStart,
     437             :         eLogicalSideIEnd,   eLogicalSideBEnd   },  // vertical-rl   sw-left rtl
     438             :       { eLogicalSideBStart, eLogicalSideIStart,
     439             :         eLogicalSideBEnd,   eLogicalSideIEnd   },  // horizontal-tb   (inv) ltr
     440             :       { eLogicalSideIEnd,   eLogicalSideBStart,
     441             :         eLogicalSideIStart, eLogicalSideBEnd   },  // vertical-rl   sw-left ltr
     442             :       { eLogicalSideBEnd,   eLogicalSideIEnd,
     443             :         eLogicalSideBStart, eLogicalSideIStart },  // (horizontal-bt)       ltr
     444             :       { eLogicalSideIStart, eLogicalSideBEnd,
     445             :         eLogicalSideIEnd,   eLogicalSideBStart },  // vertical-lr           ltr
     446             :       { eLogicalSideBEnd,   eLogicalSideIStart,
     447             :         eLogicalSideBStart, eLogicalSideIEnd   },  // (horizontal-bt)       rtl
     448             :       { eLogicalSideIEnd,   eLogicalSideBEnd,
     449             :         eLogicalSideIStart, eLogicalSideBStart },  // vertical-lr           rtl
     450             :     };
     451             : 
     452             :     static_assert(eOrientationMask == 0x01 && eInlineFlowMask == 0x02 &&
     453             :                   eBlockFlowMask == 0x04 && eLineOrientMask == 0x08,
     454             :                   "unexpected mask values");
     455           0 :     int index = mWritingMode & 0x0F;
     456           0 :     return kPhysicalToLogicalSides[index][aSide];
     457             :   }
     458             : 
     459             :   /**
     460             :    * Returns the logical side corresponding to the specified
     461             :    * line-relative direction, given the current writing mode.
     462             :    */
     463           0 :   LogicalSide LogicalSideForLineRelativeDir(LineRelativeDir aDir) const
     464             :   {
     465           0 :     auto side = static_cast<LogicalSide>(aDir);
     466           0 :     if (IsInline(side)) {
     467           0 :       return IsBidiLTR() ? side : GetOppositeSide(side);
     468             :     }
     469           0 :     return !IsLineInverted() ? side : GetOppositeSide(side);
     470             :   }
     471             : 
     472             :   /**
     473             :    * Default constructor gives us a horizontal, LTR writing mode.
     474             :    * XXX We will probably eliminate this and require explicit initialization
     475             :    *     in all cases once transition is complete.
     476             :    */
     477         892 :   WritingMode()
     478         892 :     : mWritingMode(0)
     479         892 :   { }
     480             : 
     481             :   /**
     482             :    * Construct writing mode based on a style context
     483             :    */
     484        1805 :   explicit WritingMode(nsStyleContext* aStyleContext)
     485        1805 :   {
     486        1805 :     NS_ASSERTION(aStyleContext, "we need an nsStyleContext here");
     487        1805 :     InitFromStyleVisibility(aStyleContext->StyleVisibility());
     488        1805 :   }
     489             : 
     490         289 :   explicit WritingMode(const nsStyleVisibility* aStyleVisibility)
     491         289 :   {
     492         289 :     NS_ASSERTION(aStyleVisibility, "we need an nsStyleVisibility here");
     493         289 :     InitFromStyleVisibility(aStyleVisibility);
     494         289 :   }
     495             : 
     496             : private:
     497        2094 :   void InitFromStyleVisibility(const nsStyleVisibility* aStyleVisibility)
     498             :   {
     499        2094 :     switch (aStyleVisibility->mWritingMode) {
     500             :       case NS_STYLE_WRITING_MODE_HORIZONTAL_TB:
     501        2094 :         mWritingMode = 0;
     502        2094 :         break;
     503             : 
     504             :       case NS_STYLE_WRITING_MODE_VERTICAL_LR:
     505             :       {
     506           0 :         mWritingMode = eBlockFlowMask |
     507             :                        eLineOrientMask |
     508             :                        eOrientationMask;
     509           0 :         uint8_t textOrientation = aStyleVisibility->mTextOrientation;
     510           0 :         if (textOrientation == NS_STYLE_TEXT_ORIENTATION_SIDEWAYS) {
     511           0 :           mWritingMode |= eSidewaysMask;
     512             :         }
     513           0 :         break;
     514             :       }
     515             : 
     516             :       case NS_STYLE_WRITING_MODE_VERTICAL_RL:
     517             :       {
     518           0 :         mWritingMode = eOrientationMask;
     519           0 :         uint8_t textOrientation = aStyleVisibility->mTextOrientation;
     520           0 :         if (textOrientation == NS_STYLE_TEXT_ORIENTATION_SIDEWAYS) {
     521           0 :           mWritingMode |= eSidewaysMask;
     522             :         }
     523           0 :         break;
     524             :       }
     525             : 
     526             :       case NS_STYLE_WRITING_MODE_SIDEWAYS_LR:
     527           0 :         mWritingMode = eBlockFlowMask |
     528             :                        eInlineFlowMask |
     529             :                        eOrientationMask |
     530             :                        eSidewaysMask;
     531           0 :         break;
     532             : 
     533             :       case NS_STYLE_WRITING_MODE_SIDEWAYS_RL:
     534           0 :         mWritingMode = eOrientationMask |
     535             :                        eSidewaysMask;
     536           0 :         break;
     537             : 
     538             :       default:
     539           0 :         NS_NOTREACHED("unknown writing mode!");
     540           0 :         mWritingMode = 0;
     541           0 :         break;
     542             :     }
     543             : 
     544        2094 :     if (NS_STYLE_DIRECTION_RTL == aStyleVisibility->mDirection) {
     545           0 :       mWritingMode ^= eInlineFlowMask | eBidiMask;
     546             :     }
     547        2094 :   }
     548             : public:
     549             : 
     550             :   /**
     551             :    * This function performs fixup for elements with 'unicode-bidi: plaintext',
     552             :    * where inline directionality is derived from the Unicode bidi categories
     553             :    * of the element's content, and not the CSS 'direction' property.
     554             :    *
     555             :    * The WritingMode constructor will have already incorporated the 'direction'
     556             :    * property into our flag bits, so such elements need to use this method
     557             :    * (after resolving the bidi level of their content) to update the direction
     558             :    * bits as needed.
     559             :    *
     560             :    * If it turns out that our bidi direction already matches what plaintext
     561             :    * resolution determined, there's nothing to do here. If it didn't (i.e. if
     562             :    * the rtl-ness doesn't match), then we correct the direction by flipping the
     563             :    * same bits that get flipped in the constructor's CSS 'direction'-based
     564             :    * chunk.
     565             :    *
     566             :    * XXX change uint8_t to UBiDiLevel after bug 924851
     567             :    */
     568        1642 :   void SetDirectionFromBidiLevel(uint8_t level)
     569             :   {
     570        1642 :     if (IS_LEVEL_RTL(level) == IsBidiLTR()) {
     571           0 :       mWritingMode ^= eBidiMask | eInlineFlowMask;
     572             :     }
     573        1642 :   }
     574             : 
     575             :   /**
     576             :    * Compare two WritingModes for equality.
     577             :    */
     578       43987 :   bool operator==(const WritingMode& aOther) const
     579             :   {
     580       43987 :     return mWritingMode == aOther.mWritingMode;
     581             :   }
     582             : 
     583             :   bool operator!=(const WritingMode& aOther) const
     584             :   {
     585             :     return mWritingMode != aOther.mWritingMode;
     586             :   }
     587             : 
     588             :   /**
     589             :    * Check whether two modes are orthogonal to each other.
     590             :    */
     591        4781 :   bool IsOrthogonalTo(const WritingMode& aOther) const
     592             :   {
     593        4781 :     return IsVertical() != aOther.IsVertical();
     594             :   }
     595             : 
     596             :   /**
     597             :    * Returns true if this WritingMode's aLogicalAxis has the same physical
     598             :    * start side as the parallel axis of WritingMode |aOther|.
     599             :    *
     600             :    * @param aLogicalAxis The axis to compare from this WritingMode.
     601             :    * @param aOther The other WritingMode (from which we'll choose the axis
     602             :    *               that's parallel to this WritingMode's aLogicalAxis, for
     603             :    *               comparison).
     604             :    */
     605           0 :   bool ParallelAxisStartsOnSameSide(LogicalAxis aLogicalAxis,
     606             :                                     const WritingMode& aOther) const
     607             :   {
     608             :     Side myStartSide =
     609           0 :       this->PhysicalSide(MakeLogicalSide(aLogicalAxis,
     610           0 :                                          eLogicalEdgeStart));
     611             : 
     612             :     // Figure out which of aOther's axes is parallel to |this| WritingMode's
     613             :     // aLogicalAxis, and get its physical start side as well.
     614           0 :     LogicalAxis otherWMAxis = aOther.IsOrthogonalTo(*this) ?
     615           0 :       GetOrthogonalAxis(aLogicalAxis) : aLogicalAxis;
     616             :     Side otherWMStartSide =
     617           0 :       aOther.PhysicalSide(MakeLogicalSide(otherWMAxis,
     618           0 :                                           eLogicalEdgeStart));
     619             : 
     620           0 :     NS_ASSERTION(myStartSide % 2 == otherWMStartSide % 2,
     621             :                  "Should end up with sides in the same physical axis");
     622           0 :     return myStartSide == otherWMStartSide;
     623             :   }
     624             : 
     625         241 :   uint8_t GetBits() const { return mWritingMode; }
     626             : 
     627           0 :   const char* DebugString() const {
     628           0 :     return IsVertical()
     629           0 :       ? IsVerticalLR()
     630           0 :         ? IsBidiLTR()
     631           0 :           ? IsSideways() ? "sw-lr-ltr" : "v-lr-ltr"
     632           0 :           : IsSideways() ? "sw-lr-rtl" : "v-lr-rtl"
     633           0 :         : IsBidiLTR()
     634           0 :           ? IsSideways() ? "sw-rl-ltr" : "v-rl-ltr"
     635           0 :           : IsSideways() ? "sw-rl-rtl" : "v-rl-rtl"
     636           0 :       : IsBidiLTR() ? "h-ltr" : "h-rtl"
     637             :       ;
     638             :   }
     639             : 
     640             : private:
     641             :   friend class LogicalPoint;
     642             :   friend class LogicalSize;
     643             :   friend class LogicalMargin;
     644             :   friend class LogicalRect;
     645             : 
     646             :   friend struct IPC::ParamTraits<WritingMode>;
     647             :   // IMENotification cannot store this class directly since this has some
     648             :   // constructors.  Therefore, it stores mWritingMode and recreate the
     649             :   // instance from it.
     650             :   friend struct widget::IMENotification;
     651             : 
     652             :   /**
     653             :    * Return a WritingMode representing an unknown value.
     654             :    */
     655             :   static inline WritingMode Unknown()
     656             :   {
     657             :     return WritingMode(eUnknownWritingMode);
     658             :   }
     659             : 
     660             :   /**
     661             :    * Constructing a WritingMode with an arbitrary value is a private operation
     662             :    * currently only used by the Unknown() static method.
     663             :    */
     664       79918 :   explicit WritingMode(uint8_t aValue)
     665       79918 :     : mWritingMode(aValue)
     666       79918 :   { }
     667             : 
     668             :   uint8_t mWritingMode;
     669             : 
     670             :   enum Masks {
     671             :     // Masks for our bits; true chosen as opposite of commonest case
     672             :     eOrientationMask = 0x01, // true means vertical text
     673             :     eInlineFlowMask  = 0x02, // true means absolute RTL/BTT (against physical coords)
     674             :     eBlockFlowMask   = 0x04, // true means vertical-LR (or horizontal-BT if added)
     675             :     eLineOrientMask  = 0x08, // true means over != block-start
     676             :     eBidiMask        = 0x10, // true means line-relative RTL (bidi RTL)
     677             :     // Note: We have one excess bit of info; WritingMode can pack into 4 bits.
     678             :     // But since we have space, we're caching interesting things for fast access.
     679             : 
     680             :     eSidewaysMask    = 0x20, // true means text is being rendered vertically
     681             :                              // using rotated glyphs (i.e. writing-mode is
     682             :                              // sideways-*, or writing-mode is vertical-* AND
     683             :                              // text-orientation is sideways),
     684             :                              // which means we'll use alphabetic instead of
     685             :                              // centered default baseline for vertical text
     686             : 
     687             :     // Masks for output enums
     688             :     eInlineMask = 0x03,
     689             :     eBlockMask  = 0x05
     690             :   };
     691             : };
     692             : 
     693             : 
     694             : /**
     695             :  * Logical-coordinate classes:
     696             :  *
     697             :  * There are three sets of coordinate space:
     698             :  *   - physical (top, left, bottom, right)
     699             :  *       relative to graphics coord system
     700             :  *   - flow-relative (block-start, inline-start, block-end, inline-end)
     701             :  *       relative to block/inline flow directions
     702             :  *   - line-relative (line-over, line-left, line-under, line-right)
     703             :  *       relative to glyph orientation / inline bidi directions
     704             :  * See CSS3 Writing Modes for more information
     705             :  *   http://www.w3.org/TR/css3-writing-modes/#abstract-box
     706             :  *
     707             :  * For shorthand, B represents the block-axis
     708             :  *                I represents the inline-axis
     709             :  *
     710             :  * The flow-relative geometric classes store coords in flow-relative space.
     711             :  * They use a private ns{Point,Size,Rect,Margin} member to store the actual
     712             :  * coordinate values, but reinterpret them as logical instead of physical.
     713             :  * This allows us to easily perform calculations in logical space (provided
     714             :  * writing modes of the operands match), by simply mapping to nsPoint (etc)
     715             :  * methods.
     716             :  *
     717             :  * Physical-coordinate accessors/setters are responsible to translate these
     718             :  * internal logical values as necessary.
     719             :  *
     720             :  * In DEBUG builds, the logical types store their WritingMode and check
     721             :  * that the same WritingMode is passed whenever callers ask them to do a
     722             :  * writing-mode-dependent operation. Non-DEBUG builds do NOT check this,
     723             :  * to avoid the overhead of storing WritingMode fields.
     724             :  *
     725             :  * Open question: do we need a different set optimized for line-relative
     726             :  * math, for use in nsLineLayout and the like? Or is multiplying values
     727             :  * by FlowRelativeToLineRelativeFactor() enough?
     728             :  */
     729             : 
     730             : /**
     731             :  * Flow-relative point
     732             :  */
     733          10 : class LogicalPoint {
     734             : public:
     735         254 :   explicit LogicalPoint(WritingMode aWritingMode)
     736         254 :     :
     737             : #ifdef DEBUG
     738             :       mWritingMode(aWritingMode),
     739             : #endif
     740         254 :       mPoint(0, 0)
     741         254 :   { }
     742             : 
     743             :   // Construct from a writing mode and individual coordinates (which MUST be
     744             :   // values in that writing mode, NOT physical coordinates!)
     745          79 :   LogicalPoint(WritingMode aWritingMode, nscoord aI, nscoord aB)
     746          79 :     :
     747             : #ifdef DEBUG
     748             :       mWritingMode(aWritingMode),
     749             : #endif
     750          79 :       mPoint(aI, aB)
     751          79 :   { }
     752             : 
     753             :   // Construct from a writing mode and a physical point, within a given
     754             :   // containing rectangle's size (defining the conversion between LTR
     755             :   // and RTL coordinates, and between TTB and BTT coordinates).
     756         209 :   LogicalPoint(WritingMode aWritingMode,
     757             :                const nsPoint& aPoint,
     758             :                const nsSize& aContainerSize)
     759             : #ifdef DEBUG
     760         209 :     : mWritingMode(aWritingMode)
     761             : #endif
     762             :   {
     763         209 :     if (aWritingMode.IsVertical()) {
     764           0 :       I() = aWritingMode.IsInlineReversed() ? aContainerSize.height - aPoint.y
     765             :                                             : aPoint.y;
     766           0 :       B() = aWritingMode.IsVerticalLR() ? aPoint.x
     767           0 :                                         : aContainerSize.width - aPoint.x;
     768             :     } else {
     769         209 :       I() = aWritingMode.IsInlineReversed() ? aContainerSize.width - aPoint.x
     770             :                                             : aPoint.x;
     771         209 :       B() = aPoint.y;
     772             :     }
     773         209 :   }
     774             : 
     775             :   /**
     776             :    * Read-only (const) access to the logical coordinates.
     777             :    */
     778           0 :   nscoord I(WritingMode aWritingMode) const // inline-axis
     779             :   {
     780           0 :     CHECK_WRITING_MODE(aWritingMode);
     781           0 :     return mPoint.x;
     782             :   }
     783           0 :   nscoord B(WritingMode aWritingMode) const // block-axis
     784             :   {
     785           0 :     CHECK_WRITING_MODE(aWritingMode);
     786           0 :     return mPoint.y;
     787             :   }
     788           0 :   nscoord LineRelative(WritingMode aWritingMode,
     789             :                        const nsSize& aContainerSize) const // line-axis
     790             :   {
     791           0 :     CHECK_WRITING_MODE(aWritingMode);
     792           0 :     if (aWritingMode.IsBidiLTR()) {
     793           0 :       return I();
     794             :     }
     795           0 :     return (aWritingMode.IsVertical() ? aContainerSize.height
     796           0 :                                       : aContainerSize.width) - I();
     797             :   }
     798             : 
     799             :   /**
     800             :    * These non-const accessors return a reference (lvalue) that can be
     801             :    * assigned to by callers.
     802             :    */
     803          77 :   nscoord& I(WritingMode aWritingMode) // inline-axis
     804             :   {
     805          77 :     CHECK_WRITING_MODE(aWritingMode);
     806          77 :     return mPoint.x;
     807             :   }
     808         154 :   nscoord& B(WritingMode aWritingMode) // block-axis
     809             :   {
     810         154 :     CHECK_WRITING_MODE(aWritingMode);
     811         154 :     return mPoint.y;
     812             :   }
     813             : 
     814             :   /**
     815             :    * Return a physical point corresponding to our logical coordinates,
     816             :    * converted according to our writing mode.
     817             :    */
     818         100 :   nsPoint GetPhysicalPoint(WritingMode aWritingMode,
     819             :                            const nsSize& aContainerSize) const
     820             :   {
     821         100 :     CHECK_WRITING_MODE(aWritingMode);
     822         100 :     if (aWritingMode.IsVertical()) {
     823           0 :       return nsPoint(aWritingMode.IsVerticalLR()
     824           0 :                      ? B() : aContainerSize.width - B(),
     825           0 :                      aWritingMode.IsInlineReversed()
     826           0 :                      ? aContainerSize.height - I() : I());
     827             :     } else {
     828         100 :       return nsPoint(aWritingMode.IsInlineReversed()
     829           0 :                      ? aContainerSize.width - I() : I(),
     830         200 :                      B());
     831             :     }
     832             :   }
     833             : 
     834             :   /**
     835             :    * Return the equivalent point in a different writing mode.
     836             :    */
     837          10 :   LogicalPoint ConvertTo(WritingMode aToMode, WritingMode aFromMode,
     838             :                          const nsSize& aContainerSize) const
     839             :   {
     840          10 :     CHECK_WRITING_MODE(aFromMode);
     841          10 :     return aToMode == aFromMode ?
     842             :       *this : LogicalPoint(aToMode,
     843          10 :                            GetPhysicalPoint(aFromMode, aContainerSize),
     844          30 :                            aContainerSize);
     845             :   }
     846             : 
     847           0 :   bool operator==(const LogicalPoint& aOther) const
     848             :   {
     849           0 :     CHECK_WRITING_MODE(aOther.GetWritingMode());
     850           0 :     return mPoint == aOther.mPoint;
     851             :   }
     852             : 
     853           0 :   bool operator!=(const LogicalPoint& aOther) const
     854             :   {
     855           0 :     CHECK_WRITING_MODE(aOther.GetWritingMode());
     856           0 :     return mPoint != aOther.mPoint;
     857             :   }
     858             : 
     859           0 :   LogicalPoint operator+(const LogicalPoint& aOther) const
     860             :   {
     861           0 :     CHECK_WRITING_MODE(aOther.GetWritingMode());
     862             :     // In non-debug builds, LogicalPoint does not store the WritingMode,
     863             :     // so the first parameter here (which will always be eUnknownWritingMode)
     864             :     // is ignored.
     865             :     return LogicalPoint(GetWritingMode(),
     866           0 :                         mPoint.x + aOther.mPoint.x,
     867           0 :                         mPoint.y + aOther.mPoint.y);
     868             :   }
     869             : 
     870           0 :   LogicalPoint& operator+=(const LogicalPoint& aOther)
     871             :   {
     872           0 :     CHECK_WRITING_MODE(aOther.GetWritingMode());
     873           0 :     I() += aOther.I();
     874           0 :     B() += aOther.B();
     875           0 :     return *this;
     876             :   }
     877             : 
     878           0 :   LogicalPoint operator-(const LogicalPoint& aOther) const
     879             :   {
     880           0 :     CHECK_WRITING_MODE(aOther.GetWritingMode());
     881             :     // In non-debug builds, LogicalPoint does not store the WritingMode,
     882             :     // so the first parameter here (which will always be eUnknownWritingMode)
     883             :     // is ignored.
     884             :     return LogicalPoint(GetWritingMode(),
     885           0 :                         mPoint.x - aOther.mPoint.x,
     886           0 :                         mPoint.y - aOther.mPoint.y);
     887             :   }
     888             : 
     889             :   LogicalPoint& operator-=(const LogicalPoint& aOther)
     890             :   {
     891             :     CHECK_WRITING_MODE(aOther.GetWritingMode());
     892             :     I() -= aOther.I();
     893             :     B() -= aOther.B();
     894             :     return *this;
     895             :   }
     896             : 
     897             : private:
     898             :   friend class LogicalRect;
     899             : 
     900             :   /**
     901             :    * NOTE that in non-DEBUG builds, GetWritingMode() always returns
     902             :    * eUnknownWritingMode, as the current mode is not stored in the logical-
     903             :    * geometry classes. Therefore, this method is private; it is used ONLY
     904             :    * by the DEBUG-mode checking macros in this class and its friends;
     905             :    * other code is not allowed to ask a logical point for its writing mode,
     906             :    * as this info will simply not be available in non-DEBUG builds.
     907             :    *
     908             :    * Also, in non-DEBUG builds, CHECK_WRITING_MODE does nothing, and the
     909             :    * WritingMode parameter to logical methods will generally be optimized
     910             :    * away altogether.
     911             :    */
     912             : #ifdef DEBUG
     913         420 :   WritingMode GetWritingMode() const { return mWritingMode; }
     914             : #else
     915             :   WritingMode GetWritingMode() const { return WritingMode::Unknown(); }
     916             : #endif
     917             : 
     918             :   // We don't allow construction of a LogicalPoint with no writing mode.
     919             :   LogicalPoint() = delete;
     920             : 
     921             :   // Accessors that don't take or check a WritingMode value.
     922             :   // These are for internal use only; they are called by methods that have
     923             :   // themselves already checked the WritingMode passed by the caller.
     924         100 :   nscoord I() const // inline-axis
     925             :   {
     926         100 :     return mPoint.x;
     927             :   }
     928         100 :   nscoord B() const // block-axis
     929             :   {
     930         100 :     return mPoint.y;
     931             :   }
     932             : 
     933         209 :   nscoord& I() // inline-axis
     934             :   {
     935         209 :     return mPoint.x;
     936             :   }
     937         209 :   nscoord& B() // block-axis
     938             :   {
     939         209 :     return mPoint.y;
     940             :   }
     941             : 
     942             : #ifdef DEBUG
     943             :   WritingMode mWritingMode;
     944             : #endif
     945             : 
     946             :   // We use an nsPoint to hold the coordinates, but reinterpret its .x and .y
     947             :   // fields as the inline and block directions. Hence, this is not exposed
     948             :   // directly, but only through accessors that will map them according to the
     949             :   // writing mode.
     950             :   nsPoint mPoint;
     951             : };
     952             : 
     953             : /**
     954             :  * Flow-relative size
     955             :  */
     956             : class LogicalSize {
     957             : public:
     958        1634 :   explicit LogicalSize(WritingMode aWritingMode)
     959        1634 :     :
     960             : #ifdef DEBUG
     961             :       mWritingMode(aWritingMode),
     962             : #endif
     963        1634 :       mSize(0, 0)
     964        1634 :   { }
     965             : 
     966        5928 :   LogicalSize(WritingMode aWritingMode, nscoord aISize, nscoord aBSize)
     967        5928 :     :
     968             : #ifdef DEBUG
     969             :       mWritingMode(aWritingMode),
     970             : #endif
     971        5928 :       mSize(aISize, aBSize)
     972        5928 :   { }
     973             : 
     974        2089 :   LogicalSize(WritingMode aWritingMode, const nsSize& aPhysicalSize)
     975             : #ifdef DEBUG
     976        2089 :     : mWritingMode(aWritingMode)
     977             : #endif
     978             :   {
     979        2089 :     if (aWritingMode.IsVertical()) {
     980           0 :       ISize() = aPhysicalSize.height;
     981           0 :       BSize() = aPhysicalSize.width;
     982             :     } else {
     983        2089 :       ISize() = aPhysicalSize.width;
     984        2089 :       BSize() = aPhysicalSize.height;
     985             :     }
     986        2089 :   }
     987             : 
     988           0 :   void SizeTo(WritingMode aWritingMode, nscoord aISize, nscoord aBSize)
     989             :   {
     990           0 :     CHECK_WRITING_MODE(aWritingMode);
     991           0 :     mSize.SizeTo(aISize, aBSize);
     992           0 :   }
     993             : 
     994             :   /**
     995             :    * Dimensions in logical and physical terms
     996             :    */
     997        4042 :   nscoord ISize(WritingMode aWritingMode) const // inline-size
     998             :   {
     999        4042 :     CHECK_WRITING_MODE(aWritingMode);
    1000        4042 :     return mSize.width;
    1001             :   }
    1002        2188 :   nscoord BSize(WritingMode aWritingMode) const // block-size
    1003             :   {
    1004        2188 :     CHECK_WRITING_MODE(aWritingMode);
    1005        2188 :     return mSize.height;
    1006             :   }
    1007             : 
    1008           0 :   nscoord Width(WritingMode aWritingMode) const
    1009             :   {
    1010           0 :     CHECK_WRITING_MODE(aWritingMode);
    1011           0 :     return aWritingMode.IsVertical() ? BSize() : ISize();
    1012             :   }
    1013          37 :   nscoord Height(WritingMode aWritingMode) const
    1014             :   {
    1015          37 :     CHECK_WRITING_MODE(aWritingMode);
    1016          37 :     return aWritingMode.IsVertical() ? ISize() : BSize();
    1017             :   }
    1018             : 
    1019             :   /**
    1020             :    * Writable references to the logical dimensions
    1021             :    */
    1022        7057 :   nscoord& ISize(WritingMode aWritingMode) // inline-size
    1023             :   {
    1024        7057 :     CHECK_WRITING_MODE(aWritingMode);
    1025        7057 :     return mSize.width;
    1026             :   }
    1027        5502 :   nscoord& BSize(WritingMode aWritingMode) // block-size
    1028             :   {
    1029        5502 :     CHECK_WRITING_MODE(aWritingMode);
    1030        5502 :     return mSize.height;
    1031             :   }
    1032             : 
    1033             :   /**
    1034             :    * Return an nsSize containing our physical dimensions
    1035             :    */
    1036         606 :   nsSize GetPhysicalSize(WritingMode aWritingMode) const
    1037             :   {
    1038         606 :     CHECK_WRITING_MODE(aWritingMode);
    1039         606 :     return aWritingMode.IsVertical() ?
    1040         606 :       nsSize(BSize(), ISize()) : nsSize(ISize(), BSize());
    1041             :   }
    1042             : 
    1043             :   /**
    1044             :    * Return a LogicalSize representing this size in a different writing mode
    1045             :    */
    1046        2577 :   LogicalSize ConvertTo(WritingMode aToMode, WritingMode aFromMode) const
    1047             :   {
    1048             : #ifdef DEBUG
    1049             :     // In DEBUG builds make sure to return a LogicalSize with the
    1050             :     // expected writing mode
    1051        2577 :     CHECK_WRITING_MODE(aFromMode);
    1052        2577 :     return aToMode == aFromMode ?
    1053        2577 :       *this : LogicalSize(aToMode, GetPhysicalSize(aFromMode));
    1054             : #else
    1055             :     // optimization for non-DEBUG builds where LogicalSize doesn't store
    1056             :     // the writing mode
    1057             :     return (aToMode == aFromMode || !aToMode.IsOrthogonalTo(aFromMode))
    1058             :            ? *this : LogicalSize(aToMode, BSize(), ISize());
    1059             : #endif
    1060             :   }
    1061             : 
    1062             :   /**
    1063             :    * Test if a size is (0, 0).
    1064             :    */
    1065           0 :   bool IsAllZero() const
    1066             :   {
    1067           0 :     return ISize() == 0 && BSize() == 0;
    1068             :   }
    1069             : 
    1070             :   /**
    1071             :    * Various binary operators on LogicalSize. These are valid ONLY for operands
    1072             :    * that share the same writing mode.
    1073             :    */
    1074         397 :   bool operator==(const LogicalSize& aOther) const
    1075             :   {
    1076         397 :     CHECK_WRITING_MODE(aOther.GetWritingMode());
    1077         397 :     return mSize == aOther.mSize;
    1078             :   }
    1079             : 
    1080           0 :   bool operator!=(const LogicalSize& aOther) const
    1081             :   {
    1082           0 :     CHECK_WRITING_MODE(aOther.GetWritingMode());
    1083           0 :     return mSize != aOther.mSize;
    1084             :   }
    1085             : 
    1086         177 :   LogicalSize operator+(const LogicalSize& aOther) const
    1087             :   {
    1088         177 :     CHECK_WRITING_MODE(aOther.GetWritingMode());
    1089         354 :     return LogicalSize(GetWritingMode(), ISize() + aOther.ISize(),
    1090         531 :                                          BSize() + aOther.BSize());
    1091             :   }
    1092           0 :   LogicalSize& operator+=(const LogicalSize& aOther)
    1093             :   {
    1094           0 :     CHECK_WRITING_MODE(aOther.GetWritingMode());
    1095           0 :     ISize() += aOther.ISize();
    1096           0 :     BSize() += aOther.BSize();
    1097           0 :     return *this;
    1098             :   }
    1099             : 
    1100         511 :   LogicalSize operator-(const LogicalSize& aOther) const
    1101             :   {
    1102         511 :     CHECK_WRITING_MODE(aOther.GetWritingMode());
    1103        1022 :     return LogicalSize(GetWritingMode(), ISize() - aOther.ISize(),
    1104        1533 :                                          BSize() - aOther.BSize());
    1105             :   }
    1106           0 :   LogicalSize& operator-=(const LogicalSize& aOther)
    1107             :   {
    1108           0 :     CHECK_WRITING_MODE(aOther.GetWritingMode());
    1109           0 :     ISize() -= aOther.ISize();
    1110           0 :     BSize() -= aOther.BSize();
    1111           0 :     return *this;
    1112             :   }
    1113             : 
    1114             : private:
    1115             :   friend class LogicalRect;
    1116             : 
    1117             :   LogicalSize() = delete;
    1118             : 
    1119             : #ifdef DEBUG
    1120       24946 :   WritingMode GetWritingMode() const { return mWritingMode; }
    1121             : #else
    1122             :   WritingMode GetWritingMode() const { return WritingMode::Unknown(); }
    1123             : #endif
    1124             : 
    1125        1982 :   nscoord ISize() const // inline-size
    1126             :   {
    1127        1982 :     return mSize.width;
    1128             :   }
    1129        2019 :   nscoord BSize() const // block-size
    1130             :   {
    1131        2019 :     return mSize.height;
    1132             :   }
    1133             : 
    1134        2089 :   nscoord& ISize() // inline-size
    1135             :   {
    1136        2089 :     return mSize.width;
    1137             :   }
    1138        2089 :   nscoord& BSize() // block-size
    1139             :   {
    1140        2089 :     return mSize.height;
    1141             :   }
    1142             : 
    1143             : #ifdef DEBUG
    1144             :   WritingMode mWritingMode;
    1145             : #endif
    1146             :   nsSize      mSize;
    1147             : };
    1148             : 
    1149             : /**
    1150             :  * Flow-relative margin
    1151             :  */
    1152        1291 : class LogicalMargin {
    1153             : public:
    1154         450 :   explicit LogicalMargin(WritingMode aWritingMode)
    1155         450 :     :
    1156             : #ifdef DEBUG
    1157             :       mWritingMode(aWritingMode),
    1158             : #endif
    1159         450 :       mMargin(0, 0, 0, 0)
    1160         450 :   { }
    1161             : 
    1162          77 :   LogicalMargin(WritingMode aWritingMode,
    1163             :                 nscoord aBStart, nscoord aIEnd,
    1164             :                 nscoord aBEnd, nscoord aIStart)
    1165          77 :     :
    1166             : #ifdef DEBUG
    1167             :       mWritingMode(aWritingMode),
    1168             : #endif
    1169          77 :       mMargin(aBStart, aIEnd, aBEnd, aIStart)
    1170          77 :   { }
    1171             : 
    1172        6035 :   LogicalMargin(WritingMode aWritingMode, const nsMargin& aPhysicalMargin)
    1173             : #ifdef DEBUG
    1174        6035 :     : mWritingMode(aWritingMode)
    1175             : #endif
    1176             :   {
    1177        6035 :     if (aWritingMode.IsVertical()) {
    1178           0 :       if (aWritingMode.IsVerticalLR()) {
    1179           0 :         mMargin.top = aPhysicalMargin.left;
    1180           0 :         mMargin.bottom = aPhysicalMargin.right;
    1181             :       } else {
    1182           0 :         mMargin.top = aPhysicalMargin.right;
    1183           0 :         mMargin.bottom = aPhysicalMargin.left;
    1184             :       }
    1185           0 :       if (aWritingMode.IsInlineReversed()) {
    1186           0 :         mMargin.left = aPhysicalMargin.bottom;
    1187           0 :         mMargin.right = aPhysicalMargin.top;
    1188             :       } else {
    1189           0 :         mMargin.left = aPhysicalMargin.top;
    1190           0 :         mMargin.right = aPhysicalMargin.bottom;
    1191             :       }
    1192             :     } else {
    1193        6035 :       mMargin.top = aPhysicalMargin.top;
    1194        6035 :       mMargin.bottom = aPhysicalMargin.bottom;
    1195        6035 :       if (aWritingMode.IsInlineReversed()) {
    1196           0 :         mMargin.left = aPhysicalMargin.right;
    1197           0 :         mMargin.right = aPhysicalMargin.left;
    1198             :       } else {
    1199        6035 :         mMargin.left = aPhysicalMargin.left;
    1200        6035 :         mMargin.right = aPhysicalMargin.right;
    1201             :       }
    1202             :     }
    1203        6035 :   }
    1204             : 
    1205         266 :   nscoord IStart(WritingMode aWritingMode) const // inline-start margin
    1206             :   {
    1207         266 :     CHECK_WRITING_MODE(aWritingMode);
    1208         266 :     return mMargin.left;
    1209             :   }
    1210         162 :   nscoord IEnd(WritingMode aWritingMode) const // inline-end margin
    1211             :   {
    1212         162 :     CHECK_WRITING_MODE(aWritingMode);
    1213         162 :     return mMargin.right;
    1214             :   }
    1215         406 :   nscoord BStart(WritingMode aWritingMode) const // block-start margin
    1216             :   {
    1217         406 :     CHECK_WRITING_MODE(aWritingMode);
    1218         406 :     return mMargin.top;
    1219             :   }
    1220         324 :   nscoord BEnd(WritingMode aWritingMode) const // block-end margin
    1221             :   {
    1222         324 :     CHECK_WRITING_MODE(aWritingMode);
    1223         324 :     return mMargin.bottom;
    1224             :   }
    1225             : 
    1226         863 :   nscoord& IStart(WritingMode aWritingMode) // inline-start margin
    1227             :   {
    1228         863 :     CHECK_WRITING_MODE(aWritingMode);
    1229         863 :     return mMargin.left;
    1230             :   }
    1231         336 :   nscoord& IEnd(WritingMode aWritingMode) // inline-end margin
    1232             :   {
    1233         336 :     CHECK_WRITING_MODE(aWritingMode);
    1234         336 :     return mMargin.right;
    1235             :   }
    1236         798 :   nscoord& BStart(WritingMode aWritingMode) // block-start margin
    1237             :   {
    1238         798 :     CHECK_WRITING_MODE(aWritingMode);
    1239         798 :     return mMargin.top;
    1240             :   }
    1241         346 :   nscoord& BEnd(WritingMode aWritingMode) // block-end margin
    1242             :   {
    1243         346 :     CHECK_WRITING_MODE(aWritingMode);
    1244         346 :     return mMargin.bottom;
    1245             :   }
    1246             : 
    1247        2399 :   nscoord IStartEnd(WritingMode aWritingMode) const // inline margins
    1248             :   {
    1249        2399 :     CHECK_WRITING_MODE(aWritingMode);
    1250        2399 :     return mMargin.LeftRight();
    1251             :   }
    1252         579 :   nscoord BStartEnd(WritingMode aWritingMode) const // block margins
    1253             :   {
    1254         579 :     CHECK_WRITING_MODE(aWritingMode);
    1255         579 :     return mMargin.TopBottom();
    1256             :   }
    1257             : 
    1258             :   /*
    1259             :    * Return margin values for line-relative sides, as defined in
    1260             :    * http://www.w3.org/TR/css-writing-modes-3/#line-directions:
    1261             :    *
    1262             :    * line-left
    1263             :    *     Nominally the side from which LTR text would start.
    1264             :    * line-right
    1265             :    *     Nominally the side from which RTL text would start. (Opposite of
    1266             :    *     line-left.)
    1267             :    */
    1268           0 :   nscoord LineLeft(WritingMode aWritingMode) const
    1269             :   {
    1270             :     // We don't need to CHECK_WRITING_MODE here because the IStart or IEnd
    1271             :     // accessor that we call will do it.
    1272           0 :     return aWritingMode.IsBidiLTR()
    1273           0 :            ? IStart(aWritingMode) : IEnd(aWritingMode);
    1274             :   }
    1275           0 :   nscoord LineRight(WritingMode aWritingMode) const
    1276             :   {
    1277           0 :     return aWritingMode.IsBidiLTR()
    1278           0 :            ? IEnd(aWritingMode) : IStart(aWritingMode);
    1279             :   }
    1280             : 
    1281             :   /**
    1282             :    * Return a LogicalSize representing the total size of the inline-
    1283             :    * and block-dimension margins.
    1284             :    */
    1285        1967 :   LogicalSize Size(WritingMode aWritingMode) const
    1286             :   {
    1287        1967 :     CHECK_WRITING_MODE(aWritingMode);
    1288        1967 :     return LogicalSize(aWritingMode, IStartEnd(), BStartEnd());
    1289             :   }
    1290             : 
    1291             :   /**
    1292             :    * Accessors for physical margins, using our writing mode to convert from
    1293             :    * logical values.
    1294             :    */
    1295           0 :   nscoord Top(WritingMode aWritingMode) const
    1296             :   {
    1297           0 :     CHECK_WRITING_MODE(aWritingMode);
    1298           0 :     return aWritingMode.IsVertical() ?
    1299           0 :       (aWritingMode.IsInlineReversed() ? IEnd() : IStart()) : BStart();
    1300             :   }
    1301             : 
    1302             :   nscoord Bottom(WritingMode aWritingMode) const
    1303             :   {
    1304             :     CHECK_WRITING_MODE(aWritingMode);
    1305             :     return aWritingMode.IsVertical() ?
    1306             :       (aWritingMode.IsInlineReversed() ? IStart() : IEnd()) : BEnd();
    1307             :   }
    1308             : 
    1309           0 :   nscoord Left(WritingMode aWritingMode) const
    1310             :   {
    1311           0 :     CHECK_WRITING_MODE(aWritingMode);
    1312           0 :     return aWritingMode.IsVertical() ?
    1313           0 :       (aWritingMode.IsVerticalLR() ? BStart() : BEnd()) :
    1314           0 :       (aWritingMode.IsInlineReversed() ? IEnd() : IStart());
    1315             :   }
    1316             : 
    1317             :   nscoord Right(WritingMode aWritingMode) const
    1318             :   {
    1319             :     CHECK_WRITING_MODE(aWritingMode);
    1320             :     return aWritingMode.IsVertical() ?
    1321             :       (aWritingMode.IsVerticalLR() ? BEnd() : BStart()) :
    1322             :       (aWritingMode.IsInlineReversed() ? IStart() : IEnd());
    1323             :   }
    1324             : 
    1325         162 :   nscoord LeftRight(WritingMode aWritingMode) const
    1326             :   {
    1327         162 :     CHECK_WRITING_MODE(aWritingMode);
    1328         162 :     return aWritingMode.IsVertical() ? BStartEnd() : IStartEnd();
    1329             :   }
    1330             : 
    1331         162 :   nscoord TopBottom(WritingMode aWritingMode) const
    1332             :   {
    1333         162 :     CHECK_WRITING_MODE(aWritingMode);
    1334         162 :     return aWritingMode.IsVertical() ? IStartEnd() : BStartEnd();
    1335             :   }
    1336             : 
    1337           0 :   void SizeTo(WritingMode aWritingMode,
    1338             :               nscoord aBStart, nscoord aIEnd, nscoord aBEnd, nscoord aIStart)
    1339             :   {
    1340           0 :     CHECK_WRITING_MODE(aWritingMode);
    1341           0 :     mMargin.SizeTo(aBStart, aIEnd, aBEnd, aIStart);
    1342           0 :   }
    1343             : 
    1344             :   /**
    1345             :    * Return an nsMargin containing our physical coordinates
    1346             :    */
    1347         449 :   nsMargin GetPhysicalMargin(WritingMode aWritingMode) const
    1348             :   {
    1349         449 :     CHECK_WRITING_MODE(aWritingMode);
    1350         449 :     return aWritingMode.IsVertical()
    1351           0 :            ? (aWritingMode.IsVerticalLR()
    1352           0 :              ? (aWritingMode.IsInlineReversed()
    1353             :                ? nsMargin(IEnd(), BEnd(), IStart(), BStart())
    1354             :                : nsMargin(IStart(), BEnd(), IEnd(), BStart()))
    1355           0 :              : (aWritingMode.IsInlineReversed()
    1356             :                ? nsMargin(IEnd(), BStart(), IStart(), BEnd())
    1357             :                : nsMargin(IStart(), BStart(), IEnd(), BEnd())))
    1358         449 :            : (aWritingMode.IsInlineReversed()
    1359             :              ? nsMargin(BStart(), IStart(), BEnd(), IEnd())
    1360         898 :              : nsMargin(BStart(), IEnd(), BEnd(), IStart()));
    1361             :   }
    1362             : 
    1363             :   /**
    1364             :    * Return a LogicalMargin representing this margin in a different
    1365             :    * writing mode
    1366             :    */
    1367        1291 :   LogicalMargin ConvertTo(WritingMode aToMode, WritingMode aFromMode) const
    1368             :   {
    1369        1291 :     CHECK_WRITING_MODE(aFromMode);
    1370        1291 :     return aToMode == aFromMode ?
    1371        1291 :       *this : LogicalMargin(aToMode, GetPhysicalMargin(aFromMode));
    1372             :   }
    1373             : 
    1374         162 :   void ApplySkipSides(LogicalSides aSkipSides)
    1375             :   {
    1376         162 :     if (aSkipSides.BStart()) {
    1377           0 :       BStart() = 0;
    1378             :     }
    1379         162 :     if (aSkipSides.BEnd()) {
    1380           0 :       BEnd() = 0;
    1381             :     }
    1382         162 :     if (aSkipSides.IStart()) {
    1383           0 :       IStart() = 0;
    1384             :     }
    1385         162 :     if (aSkipSides.IEnd()) {
    1386           0 :       IEnd() = 0;
    1387             :     }
    1388         162 :   }
    1389             : 
    1390           0 :   bool IsAllZero() const
    1391             :   {
    1392           0 :     return (mMargin.left == 0 && mMargin.top == 0 &&
    1393           0 :             mMargin.right == 0 && mMargin.bottom == 0);
    1394             :   }
    1395             : 
    1396             :   LogicalMargin operator+(const LogicalMargin& aMargin) const {
    1397             :     CHECK_WRITING_MODE(aMargin.GetWritingMode());
    1398             :     return LogicalMargin(GetWritingMode(),
    1399             :                          BStart() + aMargin.BStart(),
    1400             :                          IEnd() + aMargin.IEnd(),
    1401             :                          BEnd() + aMargin.BEnd(),
    1402             :                          IStart() + aMargin.IStart());
    1403             :   }
    1404             : 
    1405           0 :   LogicalMargin operator+=(const LogicalMargin& aMargin)
    1406             :   {
    1407           0 :     CHECK_WRITING_MODE(aMargin.GetWritingMode());
    1408           0 :     mMargin += aMargin.mMargin;
    1409           0 :     return *this;
    1410             :   }
    1411             : 
    1412          77 :   LogicalMargin operator-(const LogicalMargin& aMargin) const {
    1413          77 :     CHECK_WRITING_MODE(aMargin.GetWritingMode());
    1414             :     return LogicalMargin(GetWritingMode(),
    1415          77 :                          BStart() - aMargin.BStart(),
    1416          77 :                          IEnd() - aMargin.IEnd(),
    1417          77 :                          BEnd() - aMargin.BEnd(),
    1418         308 :                          IStart() - aMargin.IStart());
    1419             :   }
    1420             : 
    1421             : private:
    1422             :   friend class LogicalRect;
    1423             : 
    1424             :   LogicalMargin() = delete;
    1425             : 
    1426             : #ifdef DEBUG
    1427       10765 :   WritingMode GetWritingMode() const { return mWritingMode; }
    1428             : #else
    1429             :   WritingMode GetWritingMode() const { return WritingMode::Unknown(); }
    1430             : #endif
    1431             : 
    1432         603 :   nscoord IStart() const // inline-start margin
    1433             :   {
    1434         603 :     return mMargin.left;
    1435             :   }
    1436         603 :   nscoord IEnd() const // inline-end margin
    1437             :   {
    1438         603 :     return mMargin.right;
    1439             :   }
    1440         603 :   nscoord BStart() const // block-start margin
    1441             :   {
    1442         603 :     return mMargin.top;
    1443             :   }
    1444         603 :   nscoord BEnd() const // block-end margin
    1445             :   {
    1446         603 :     return mMargin.bottom;
    1447             :   }
    1448             : 
    1449           0 :   nscoord& IStart() // inline-start margin
    1450             :   {
    1451           0 :     return mMargin.left;
    1452             :   }
    1453           0 :   nscoord& IEnd() // inline-end margin
    1454             :   {
    1455           0 :     return mMargin.right;
    1456             :   }
    1457           0 :   nscoord& BStart() // block-start margin
    1458             :   {
    1459           0 :     return mMargin.top;
    1460             :   }
    1461           0 :   nscoord& BEnd() // block-end margin
    1462             :   {
    1463           0 :     return mMargin.bottom;
    1464             :   }
    1465             : 
    1466        2129 :   nscoord IStartEnd() const // inline margins
    1467             :   {
    1468        2129 :     return mMargin.LeftRight();
    1469             :   }
    1470        2129 :   nscoord BStartEnd() const // block margins
    1471             :   {
    1472        2129 :     return mMargin.TopBottom();
    1473             :   }
    1474             : 
    1475             : #ifdef DEBUG
    1476             :   WritingMode mWritingMode;
    1477             : #endif
    1478             :   nsMargin    mMargin;
    1479             : };
    1480             : 
    1481             : /**
    1482             :  * Flow-relative rectangle
    1483             :  */
    1484        1849 : class LogicalRect {
    1485             : public:
    1486         365 :   explicit LogicalRect(WritingMode aWritingMode)
    1487         365 :     :
    1488             : #ifdef DEBUG
    1489             :       mWritingMode(aWritingMode),
    1490             : #endif
    1491         365 :       mRect(0, 0, 0, 0)
    1492         365 :   { }
    1493             : 
    1494         482 :   LogicalRect(WritingMode aWritingMode,
    1495             :               nscoord aIStart, nscoord aBStart,
    1496             :               nscoord aISize, nscoord aBSize)
    1497         482 :     :
    1498             : #ifdef DEBUG
    1499             :       mWritingMode(aWritingMode),
    1500             : #endif
    1501         482 :       mRect(aIStart, aBStart, aISize, aBSize)
    1502         482 :   { }
    1503             : 
    1504          79 :   LogicalRect(WritingMode aWritingMode,
    1505             :               const LogicalPoint& aOrigin,
    1506             :               const LogicalSize& aSize)
    1507          79 :     :
    1508             : #ifdef DEBUG
    1509             :       mWritingMode(aWritingMode),
    1510             : #endif
    1511          79 :       mRect(aOrigin.mPoint, aSize.mSize)
    1512             :   {
    1513          79 :     CHECK_WRITING_MODE(aOrigin.GetWritingMode());
    1514          79 :     CHECK_WRITING_MODE(aSize.GetWritingMode());
    1515          79 :   }
    1516             : 
    1517          24 :   LogicalRect(WritingMode aWritingMode,
    1518             :               const nsRect& aRect,
    1519             :               const nsSize& aContainerSize)
    1520             : #ifdef DEBUG
    1521          24 :     : mWritingMode(aWritingMode)
    1522             : #endif
    1523             :   {
    1524          24 :     if (aWritingMode.IsVertical()) {
    1525           0 :       mRect.y = aWritingMode.IsVerticalLR()
    1526           0 :                 ? aRect.x : aContainerSize.width - aRect.XMost();
    1527           0 :       mRect.x = aWritingMode.IsInlineReversed()
    1528           0 :                 ? aContainerSize.height - aRect.YMost() : aRect.y;
    1529           0 :       mRect.height = aRect.width;
    1530           0 :       mRect.width = aRect.height;
    1531             :     } else {
    1532          48 :       mRect.x = aWritingMode.IsInlineReversed()
    1533          24 :                 ? aContainerSize.width - aRect.XMost() : aRect.x;
    1534          24 :       mRect.y = aRect.y;
    1535          24 :       mRect.width = aRect.width;
    1536          24 :       mRect.height = aRect.height;
    1537             :     }
    1538          24 :   }
    1539             : 
    1540             :   /**
    1541             :    * Inline- and block-dimension geometry.
    1542             :    */
    1543         309 :   nscoord IStart(WritingMode aWritingMode) const // inline-start edge
    1544             :   {
    1545         309 :     CHECK_WRITING_MODE(aWritingMode);
    1546         309 :     return mRect.X();
    1547             :   }
    1548         334 :   nscoord IEnd(WritingMode aWritingMode) const // inline-end edge
    1549             :   {
    1550         334 :     CHECK_WRITING_MODE(aWritingMode);
    1551         334 :     return mRect.XMost();
    1552             :   }
    1553         223 :   nscoord ISize(WritingMode aWritingMode) const // inline-size
    1554             :   {
    1555         223 :     CHECK_WRITING_MODE(aWritingMode);
    1556         223 :     return mRect.Width();
    1557             :   }
    1558             : 
    1559         454 :   nscoord BStart(WritingMode aWritingMode) const // block-start edge
    1560             :   {
    1561         454 :     CHECK_WRITING_MODE(aWritingMode);
    1562         454 :     return mRect.Y();
    1563             :   }
    1564         451 :   nscoord BEnd(WritingMode aWritingMode) const // block-end edge
    1565             :   {
    1566         451 :     CHECK_WRITING_MODE(aWritingMode);
    1567         451 :     return mRect.YMost();
    1568             :   }
    1569         352 :   nscoord BSize(WritingMode aWritingMode) const // block-size
    1570             :   {
    1571         352 :     CHECK_WRITING_MODE(aWritingMode);
    1572         352 :     return mRect.Height();
    1573             :   }
    1574             : 
    1575             :   /**
    1576             :    * Writable (reference) accessors are only available for the basic logical
    1577             :    * fields (Start and Size), not derivatives like End.
    1578             :    */
    1579         678 :   nscoord& IStart(WritingMode aWritingMode) // inline-start edge
    1580             :   {
    1581         678 :     CHECK_WRITING_MODE(aWritingMode);
    1582         678 :     return mRect.x;
    1583             :   }
    1584        1145 :   nscoord& ISize(WritingMode aWritingMode) // inline-size
    1585             :   {
    1586        1145 :     CHECK_WRITING_MODE(aWritingMode);
    1587        1145 :     return mRect.width;
    1588             :   }
    1589         548 :   nscoord& BStart(WritingMode aWritingMode) // block-start edge
    1590             :   {
    1591         548 :     CHECK_WRITING_MODE(aWritingMode);
    1592         548 :     return mRect.y;
    1593             :   }
    1594         376 :   nscoord& BSize(WritingMode aWritingMode) // block-size
    1595             :   {
    1596         376 :     CHECK_WRITING_MODE(aWritingMode);
    1597         376 :     return mRect.height;
    1598             :   }
    1599             : 
    1600             :   /**
    1601             :    * Accessors for line-relative coordinates
    1602             :    */
    1603          85 :   nscoord LineLeft(WritingMode aWritingMode,
    1604             :                    const nsSize& aContainerSize) const
    1605             :   {
    1606          85 :     CHECK_WRITING_MODE(aWritingMode);
    1607          85 :     if (aWritingMode.IsBidiLTR()) {
    1608          85 :       return IStart();
    1609             :     }
    1610             :     nscoord containerISize =
    1611           0 :       aWritingMode.IsVertical() ? aContainerSize.height : aContainerSize.width;
    1612           0 :     return containerISize - IEnd();
    1613             :   }
    1614           0 :   nscoord LineRight(WritingMode aWritingMode,
    1615             :                     const nsSize& aContainerSize) const
    1616             :   {
    1617           0 :     CHECK_WRITING_MODE(aWritingMode);
    1618           0 :     if (aWritingMode.IsBidiLTR()) {
    1619           0 :       return IEnd();
    1620             :     }
    1621             :     nscoord containerISize =
    1622           0 :       aWritingMode.IsVertical() ? aContainerSize.height : aContainerSize.width;
    1623           0 :     return containerISize - IStart();
    1624             :   }
    1625             : 
    1626             :   /**
    1627             :    * Physical coordinates of the rect.
    1628             :    */
    1629             :   nscoord X(WritingMode aWritingMode, nscoord aContainerWidth) const
    1630             :   {
    1631             :     CHECK_WRITING_MODE(aWritingMode);
    1632             :     if (aWritingMode.IsVertical()) {
    1633             :       return aWritingMode.IsVerticalLR() ?
    1634             :              mRect.Y() : aContainerWidth - mRect.YMost();
    1635             :     } else {
    1636             :       return aWritingMode.IsInlineReversed() ?
    1637             :              aContainerWidth - mRect.XMost() : mRect.X();
    1638             :     }
    1639             :   }
    1640             : 
    1641             :   nscoord Y(WritingMode aWritingMode, nscoord aContainerHeight) const
    1642             :   {
    1643             :     CHECK_WRITING_MODE(aWritingMode);
    1644             :     if (aWritingMode.IsVertical()) {
    1645             :       return aWritingMode.IsInlineReversed() ? aContainerHeight - mRect.XMost()
    1646             :                                              : mRect.X();
    1647             :     } else {
    1648             :       return mRect.Y();
    1649             :     }
    1650             :   }
    1651             : 
    1652           0 :   nscoord Width(WritingMode aWritingMode) const
    1653             :   {
    1654           0 :     CHECK_WRITING_MODE(aWritingMode);
    1655           0 :     return aWritingMode.IsVertical() ? mRect.Height() : mRect.Width();
    1656             :   }
    1657             : 
    1658           0 :   nscoord Height(WritingMode aWritingMode) const
    1659             :   {
    1660           0 :     CHECK_WRITING_MODE(aWritingMode);
    1661           0 :     return aWritingMode.IsVertical() ? mRect.Width() : mRect.Height();
    1662             :   }
    1663             : 
    1664             :   nscoord XMost(WritingMode aWritingMode, nscoord aContainerWidth) const
    1665             :   {
    1666             :     CHECK_WRITING_MODE(aWritingMode);
    1667             :     if (aWritingMode.IsVertical()) {
    1668             :       return aWritingMode.IsVerticalLR() ?
    1669             :              mRect.YMost() : aContainerWidth - mRect.Y();
    1670             :     } else {
    1671             :       return aWritingMode.IsInlineReversed() ?
    1672             :              aContainerWidth - mRect.X() : mRect.XMost();
    1673             :     }
    1674             :   }
    1675             : 
    1676             :   nscoord YMost(WritingMode aWritingMode, nscoord aContainerHeight) const
    1677             :   {
    1678             :     CHECK_WRITING_MODE(aWritingMode);
    1679             :     if (aWritingMode.IsVertical()) {
    1680             :       return aWritingMode.IsInlineReversed() ? aContainerHeight - mRect.x
    1681             :                                              : mRect.XMost();
    1682             :     } else {
    1683             :       return mRect.YMost();
    1684             :     }
    1685             :   }
    1686             : 
    1687             :   bool IsEmpty() const
    1688             :   {
    1689             :     return mRect.IsEmpty();
    1690             :   }
    1691             : 
    1692         323 :   bool IsAllZero() const
    1693             :   {
    1694         689 :     return (mRect.x == 0 && mRect.y == 0 &&
    1695         570 :             mRect.width == 0 && mRect.height == 0);
    1696             :   }
    1697             : 
    1698           0 :   bool IsZeroSize() const
    1699             :   {
    1700           0 :     return (mRect.width == 0 && mRect.height == 0);
    1701             :   }
    1702             : 
    1703           0 :   void SetEmpty() { mRect.SetEmpty(); }
    1704             : 
    1705           0 :   bool IsEqualEdges(const LogicalRect aOther) const
    1706             :   {
    1707           0 :     CHECK_WRITING_MODE(aOther.GetWritingMode());
    1708           0 :     return mRect.IsEqualEdges(aOther.mRect);
    1709             :   }
    1710             : 
    1711           0 :   LogicalPoint Origin(WritingMode aWritingMode) const
    1712             :   {
    1713           0 :     CHECK_WRITING_MODE(aWritingMode);
    1714           0 :     return LogicalPoint(aWritingMode, IStart(), BStart());
    1715             :   }
    1716           0 :   void SetOrigin(WritingMode aWritingMode, const LogicalPoint& aPoint)
    1717             :   {
    1718           0 :     IStart(aWritingMode) = aPoint.I(aWritingMode);
    1719           0 :     BStart(aWritingMode) = aPoint.B(aWritingMode);
    1720           0 :   }
    1721             : 
    1722          20 :   LogicalSize Size(WritingMode aWritingMode) const
    1723             :   {
    1724          20 :     CHECK_WRITING_MODE(aWritingMode);
    1725          20 :     return LogicalSize(aWritingMode, ISize(), BSize());
    1726             :   }
    1727             : 
    1728             :   LogicalRect operator+(const LogicalPoint& aPoint) const
    1729             :   {
    1730             :     CHECK_WRITING_MODE(aPoint.GetWritingMode());
    1731             :     return LogicalRect(GetWritingMode(),
    1732             :                        IStart() + aPoint.I(), BStart() + aPoint.B(),
    1733             :                        ISize(), BSize());
    1734             :   }
    1735             : 
    1736           0 :   LogicalRect& operator+=(const LogicalPoint& aPoint)
    1737             :   {
    1738           0 :     CHECK_WRITING_MODE(aPoint.GetWritingMode());
    1739           0 :     mRect += aPoint.mPoint;
    1740           0 :     return *this;
    1741             :   }
    1742             : 
    1743           0 :   LogicalRect operator-(const LogicalPoint& aPoint) const
    1744             :   {
    1745           0 :     CHECK_WRITING_MODE(aPoint.GetWritingMode());
    1746             :     return LogicalRect(GetWritingMode(),
    1747           0 :                        IStart() - aPoint.I(), BStart() - aPoint.B(),
    1748           0 :                        ISize(), BSize());
    1749             :   }
    1750             : 
    1751             :   LogicalRect& operator-=(const LogicalPoint& aPoint)
    1752             :   {
    1753             :     CHECK_WRITING_MODE(aPoint.GetWritingMode());
    1754             :     mRect -= aPoint.mPoint;
    1755             :     return *this;
    1756             :   }
    1757             : 
    1758           0 :   void MoveBy(WritingMode aWritingMode, const LogicalPoint& aDelta)
    1759             :   {
    1760           0 :     CHECK_WRITING_MODE(aWritingMode);
    1761           0 :     CHECK_WRITING_MODE(aDelta.GetWritingMode());
    1762           0 :     IStart() += aDelta.I();
    1763           0 :     BStart() += aDelta.B();
    1764           0 :   }
    1765             : 
    1766             :   void Inflate(nscoord aD) { mRect.Inflate(aD); }
    1767             :   void Inflate(nscoord aDI, nscoord aDB) { mRect.Inflate(aDI, aDB); }
    1768           0 :   void Inflate(WritingMode aWritingMode, const LogicalMargin& aMargin)
    1769             :   {
    1770           0 :     CHECK_WRITING_MODE(aWritingMode);
    1771           0 :     CHECK_WRITING_MODE(aMargin.GetWritingMode());
    1772           0 :     mRect.Inflate(aMargin.mMargin);
    1773           0 :   }
    1774             : 
    1775             :   void Deflate(nscoord aD) { mRect.Deflate(aD); }
    1776             :   void Deflate(nscoord aDI, nscoord aDB) { mRect.Deflate(aDI, aDB); }
    1777          24 :   void Deflate(WritingMode aWritingMode, const LogicalMargin& aMargin)
    1778             :   {
    1779          24 :     CHECK_WRITING_MODE(aWritingMode);
    1780          24 :     CHECK_WRITING_MODE(aMargin.GetWritingMode());
    1781          24 :     mRect.Deflate(aMargin.mMargin);
    1782          24 :   }
    1783             : 
    1784             :   /**
    1785             :    * Return an nsRect containing our physical coordinates within the given
    1786             :    * container size.
    1787             :    */
    1788         681 :   nsRect GetPhysicalRect(WritingMode aWritingMode,
    1789             :                          const nsSize& aContainerSize) const
    1790             :   {
    1791         681 :     CHECK_WRITING_MODE(aWritingMode);
    1792         681 :     if (aWritingMode.IsVertical()) {
    1793           0 :       return nsRect(aWritingMode.IsVerticalLR()
    1794           0 :                     ? BStart() : aContainerSize.width - BEnd(),
    1795           0 :                     aWritingMode.IsInlineReversed()
    1796           0 :                     ?  aContainerSize.height - IEnd() : IStart(),
    1797           0 :                     BSize(), ISize());
    1798             :     } else {
    1799         681 :       return nsRect(aWritingMode.IsInlineReversed()
    1800           0 :                     ? aContainerSize.width - IEnd() : IStart(),
    1801        1362 :                     BStart(), ISize(), BSize());
    1802             :     }
    1803             :   }
    1804             : 
    1805             :   /**
    1806             :    * Return a LogicalRect representing this rect in a different writing mode
    1807             :    */
    1808          75 :   LogicalRect ConvertTo(WritingMode aToMode, WritingMode aFromMode,
    1809             :                         const nsSize& aContainerSize) const
    1810             :   {
    1811          75 :     CHECK_WRITING_MODE(aFromMode);
    1812          75 :     return aToMode == aFromMode ?
    1813          75 :       *this : LogicalRect(aToMode, GetPhysicalRect(aFromMode, aContainerSize),
    1814         225 :                           aContainerSize);
    1815             :   }
    1816             : 
    1817             :   /**
    1818             :    * Set *this to be the rectangle containing the intersection of aRect1
    1819             :    * and aRect2, return whether the intersection is non-empty.
    1820             :    */
    1821           0 :   bool IntersectRect(const LogicalRect& aRect1, const LogicalRect& aRect2)
    1822             :   {
    1823           0 :     CHECK_WRITING_MODE(aRect1.mWritingMode);
    1824           0 :     CHECK_WRITING_MODE(aRect2.mWritingMode);
    1825           0 :     return mRect.IntersectRect(aRect1.mRect, aRect2.mRect);
    1826             :   }
    1827             : 
    1828             : private:
    1829             :   LogicalRect() = delete;
    1830             : 
    1831             : #ifdef DEBUG
    1832        5937 :   WritingMode GetWritingMode() const { return mWritingMode; }
    1833             : #else
    1834             :   WritingMode GetWritingMode() const { return WritingMode::Unknown(); }
    1835             : #endif
    1836             : 
    1837         766 :   nscoord IStart() const // inline-start edge
    1838             :   {
    1839         766 :     return mRect.X();
    1840             :   }
    1841           0 :   nscoord IEnd() const // inline-end edge
    1842             :   {
    1843           0 :     return mRect.XMost();
    1844             :   }
    1845         701 :   nscoord ISize() const // inline-size
    1846             :   {
    1847         701 :     return mRect.Width();
    1848             :   }
    1849             : 
    1850         681 :   nscoord BStart() const // block-start edge
    1851             :   {
    1852         681 :     return mRect.Y();
    1853             :   }
    1854           0 :   nscoord BEnd() const // block-end edge
    1855             :   {
    1856           0 :     return mRect.YMost();
    1857             :   }
    1858         701 :   nscoord BSize() const // block-size
    1859             :   {
    1860         701 :     return mRect.Height();
    1861             :   }
    1862             : 
    1863           0 :   nscoord& IStart() // inline-start edge
    1864             :   {
    1865           0 :     return mRect.x;
    1866             :   }
    1867             :   nscoord& ISize() // inline-size
    1868             :   {
    1869             :     return mRect.width;
    1870             :   }
    1871           0 :   nscoord& BStart() // block-start edge
    1872             :   {
    1873           0 :     return mRect.y;
    1874             :   }
    1875             :   nscoord& BSize() // block-size
    1876             :   {
    1877             :     return mRect.height;
    1878             :   }
    1879             : 
    1880             : #ifdef DEBUG
    1881             :   WritingMode mWritingMode;
    1882             : #endif
    1883             :   nsRect      mRect;
    1884             : };
    1885             : 
    1886             : } // namespace mozilla
    1887             : 
    1888             : // Definitions of inline methods for nsStyleSides, declared in nsStyleCoord.h
    1889             : // but not defined there because they need WritingMode.
    1890        1307 : inline nsStyleUnit nsStyleSides::GetUnit(mozilla::WritingMode aWM,
    1891             :                                          mozilla::LogicalSide aSide) const
    1892             : {
    1893        1307 :   return GetUnit(aWM.PhysicalSide(aSide));
    1894             : }
    1895             : 
    1896          77 : inline nsStyleUnit nsStyleSides::GetIStartUnit(mozilla::WritingMode aWM) const
    1897             : {
    1898          77 :   return GetUnit(aWM, mozilla::eLogicalSideIStart);
    1899             : }
    1900             : 
    1901          77 : inline nsStyleUnit nsStyleSides::GetBStartUnit(mozilla::WritingMode aWM) const
    1902             : {
    1903          77 :   return GetUnit(aWM, mozilla::eLogicalSideBStart);
    1904             : }
    1905             : 
    1906          77 : inline nsStyleUnit nsStyleSides::GetIEndUnit(mozilla::WritingMode aWM) const
    1907             : {
    1908          77 :   return GetUnit(aWM, mozilla::eLogicalSideIEnd);
    1909             : }
    1910             : 
    1911        1076 : inline nsStyleUnit nsStyleSides::GetBEndUnit(mozilla::WritingMode aWM) const
    1912             : {
    1913        1076 :   return GetUnit(aWM, mozilla::eLogicalSideBEnd);
    1914             : }
    1915             : 
    1916           0 : inline bool nsStyleSides::HasBlockAxisAuto(mozilla::WritingMode aWM) const
    1917             : {
    1918           0 :   return GetBStartUnit(aWM) == eStyleUnit_Auto ||
    1919           0 :          GetBEndUnit(aWM) == eStyleUnit_Auto;
    1920             : }
    1921             : 
    1922           0 : inline bool nsStyleSides::HasInlineAxisAuto(mozilla::WritingMode aWM) const
    1923             : {
    1924           0 :   return GetIStartUnit(aWM) == eStyleUnit_Auto ||
    1925           0 :          GetIEndUnit(aWM) == eStyleUnit_Auto;
    1926             : }
    1927             : 
    1928          10 : inline nsStyleCoord nsStyleSides::Get(mozilla::WritingMode aWM,
    1929             :                                       mozilla::LogicalSide aSide) const
    1930             : {
    1931          10 :   return Get(aWM.PhysicalSide(aSide));
    1932             : }
    1933             : 
    1934           0 : inline nsStyleCoord nsStyleSides::GetIStart(mozilla::WritingMode aWM) const
    1935             : {
    1936           0 :   return Get(aWM, mozilla::eLogicalSideIStart);
    1937             : }
    1938             : 
    1939           5 : inline nsStyleCoord nsStyleSides::GetBStart(mozilla::WritingMode aWM) const
    1940             : {
    1941           5 :   return Get(aWM, mozilla::eLogicalSideBStart);
    1942             : }
    1943             : 
    1944           0 : inline nsStyleCoord nsStyleSides::GetIEnd(mozilla::WritingMode aWM) const
    1945             : {
    1946           0 :   return Get(aWM, mozilla::eLogicalSideIEnd);
    1947             : }
    1948             : 
    1949           5 : inline nsStyleCoord nsStyleSides::GetBEnd(mozilla::WritingMode aWM) const
    1950             : {
    1951           5 :   return Get(aWM, mozilla::eLogicalSideBEnd);
    1952             : }
    1953             : 
    1954             : // Definitions of inline methods for nsStylePosition, declared in
    1955             : // nsStyleStruct.h but not defined there because they need WritingMode.
    1956             : inline nsStyleCoord& nsStylePosition::ISize(mozilla::WritingMode aWM)
    1957             : {
    1958             :   return aWM.IsVertical() ? mHeight : mWidth;
    1959             : }
    1960             : inline nsStyleCoord& nsStylePosition::MinISize(mozilla::WritingMode aWM)
    1961             : {
    1962             :   return aWM.IsVertical() ? mMinHeight : mMinWidth;
    1963             : }
    1964             : inline nsStyleCoord& nsStylePosition::MaxISize(mozilla::WritingMode aWM)
    1965             : {
    1966             :   return aWM.IsVertical() ? mMaxHeight : mMaxWidth;
    1967             : }
    1968             : inline nsStyleCoord& nsStylePosition::BSize(mozilla::WritingMode aWM)
    1969             : {
    1970             :   return aWM.IsVertical() ? mWidth : mHeight;
    1971             : }
    1972             : inline nsStyleCoord& nsStylePosition::MinBSize(mozilla::WritingMode aWM)
    1973             : {
    1974             :   return aWM.IsVertical() ? mMinWidth : mMinHeight;
    1975             : }
    1976             : inline nsStyleCoord& nsStylePosition::MaxBSize(mozilla::WritingMode aWM)
    1977             : {
    1978             :   return aWM.IsVertical() ? mMaxWidth : mMaxHeight;
    1979             : }
    1980             : 
    1981             : inline const nsStyleCoord&
    1982         728 : nsStylePosition::ISize(mozilla::WritingMode aWM) const
    1983             : {
    1984         728 :   return aWM.IsVertical() ? mHeight : mWidth;
    1985             : }
    1986             : inline const nsStyleCoord&
    1987         792 : nsStylePosition::MinISize(mozilla::WritingMode aWM) const
    1988             : {
    1989         792 :   return aWM.IsVertical() ? mMinHeight : mMinWidth;
    1990             : }
    1991             : inline const nsStyleCoord&
    1992         792 : nsStylePosition::MaxISize(mozilla::WritingMode aWM) const
    1993             : {
    1994         792 :   return aWM.IsVertical() ? mMaxHeight : mMaxWidth;
    1995             : }
    1996             : inline const nsStyleCoord&
    1997        2527 : nsStylePosition::BSize(mozilla::WritingMode aWM) const
    1998             : {
    1999        2527 :   return aWM.IsVertical() ? mWidth : mHeight;
    2000             : }
    2001             : inline const nsStyleCoord&
    2002         430 : nsStylePosition::MinBSize(mozilla::WritingMode aWM) const
    2003             : {
    2004         430 :   return aWM.IsVertical() ? mMinWidth : mMinHeight;
    2005             : }
    2006             : inline const nsStyleCoord&
    2007        1496 : nsStylePosition::MaxBSize(mozilla::WritingMode aWM) const
    2008             : {
    2009        1496 :   return aWM.IsVertical() ? mMaxWidth : mMaxHeight;
    2010             : }
    2011             : 
    2012             : inline bool
    2013           0 : nsStylePosition::ISizeDependsOnContainer(mozilla::WritingMode aWM) const
    2014             : {
    2015           0 :   return aWM.IsVertical() ? HeightDependsOnContainer()
    2016           0 :                           : WidthDependsOnContainer();
    2017             : }
    2018             : inline bool
    2019           0 : nsStylePosition::MinISizeDependsOnContainer(mozilla::WritingMode aWM) const
    2020             : {
    2021           0 :   return aWM.IsVertical() ? MinHeightDependsOnContainer()
    2022           0 :                           : MinWidthDependsOnContainer();
    2023             : }
    2024             : inline bool
    2025           0 : nsStylePosition::MaxISizeDependsOnContainer(mozilla::WritingMode aWM) const
    2026             : {
    2027           0 :   return aWM.IsVertical() ? MaxHeightDependsOnContainer()
    2028           0 :                           : MaxWidthDependsOnContainer();
    2029             : }
    2030             : inline bool
    2031        1009 : nsStylePosition::BSizeDependsOnContainer(mozilla::WritingMode aWM) const
    2032             : {
    2033        1009 :   return aWM.IsVertical() ? WidthDependsOnContainer()
    2034        1009 :                           : HeightDependsOnContainer();
    2035             : }
    2036             : inline bool
    2037        1001 : nsStylePosition::MinBSizeDependsOnContainer(mozilla::WritingMode aWM) const
    2038             : {
    2039        1001 :   return aWM.IsVertical() ? MinWidthDependsOnContainer()
    2040        1001 :                           : MinHeightDependsOnContainer();
    2041             : }
    2042             : inline bool
    2043        1001 : nsStylePosition::MaxBSizeDependsOnContainer(mozilla::WritingMode aWM) const
    2044             : {
    2045        1001 :   return aWM.IsVertical() ? MaxWidthDependsOnContainer()
    2046        1001 :                           : MaxHeightDependsOnContainer();
    2047             : }
    2048             : 
    2049             : inline mozilla::StyleFloat
    2050           0 : nsStyleDisplay::PhysicalFloats(mozilla::WritingMode aWM) const
    2051             : {
    2052             :   using StyleFloat = mozilla::StyleFloat;
    2053           0 :   if (mFloat == StyleFloat::InlineStart) {
    2054           0 :     return aWM.IsBidiLTR() ? StyleFloat::Left : StyleFloat::Right;
    2055             :   }
    2056           0 :   if (mFloat == StyleFloat::InlineEnd) {
    2057           0 :     return aWM.IsBidiLTR() ? StyleFloat::Right : StyleFloat::Left;
    2058             :   }
    2059           0 :   return mFloat;
    2060             : }
    2061             : 
    2062             : inline mozilla::StyleClear
    2063          19 : nsStyleDisplay::PhysicalBreakType(mozilla::WritingMode aWM) const
    2064             : {
    2065             :   using StyleClear = mozilla::StyleClear;
    2066          19 :   if (mBreakType == StyleClear::InlineStart) {
    2067           0 :     return aWM.IsBidiLTR() ? StyleClear::Left : StyleClear::Right;
    2068             :   }
    2069          19 :   if (mBreakType == StyleClear::InlineEnd) {
    2070           0 :     return aWM.IsBidiLTR() ? StyleClear::Right : StyleClear::Left;
    2071             :   }
    2072          19 :   return mBreakType;
    2073             : }
    2074             : 
    2075             : inline bool
    2076           0 : nsStyleMargin::HasBlockAxisAuto(mozilla::WritingMode aWM) const
    2077             : {
    2078           0 :   return mMargin.HasBlockAxisAuto(aWM);
    2079             : }
    2080             : inline bool
    2081           0 : nsStyleMargin::HasInlineAxisAuto(mozilla::WritingMode aWM) const
    2082             : {
    2083           0 :   return mMargin.HasInlineAxisAuto(aWM);
    2084             : }
    2085             : 
    2086             : #endif // WritingModes_h_

Generated by: LCOV version 1.13