LCOV - code coverage report
Current view: top level - layout/generic - WritingModes.h (source / functions) Hit Total Coverage
Test: output.info Lines: 140 600 23.3 %
Date: 2018-08-07 16:35:00 Functions: 0 0 -
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13-14-ga5dd952