LCOV - code coverage report
Current view: top level - layout/generic - RubyUtils.h (source / functions) Hit Total Coverage
Test: output.info Lines: 15 51 29.4 %
Date: 2017-07-14 16:53:18 Functions: 4 22 18.2 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; 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 mozilla_RubyUtils_h_
       8             : #define mozilla_RubyUtils_h_
       9             : 
      10             : #include "nsCSSAnonBoxes.h"
      11             : #include "nsGkAtoms.h"
      12             : #include "nsIFrame.h"
      13             : #include "nsTArray.h"
      14             : 
      15             : #define RTC_ARRAY_SIZE 1
      16             : 
      17             : class nsRubyFrame;
      18             : class nsRubyBaseFrame;
      19             : class nsRubyTextFrame;
      20             : class nsRubyContentFrame;
      21             : class nsRubyBaseContainerFrame;
      22             : class nsRubyTextContainerFrame;
      23             : 
      24             : namespace mozilla {
      25             : 
      26             : /**
      27             :  * Reserved ISize
      28             :  *
      29             :  * With some exceptions, each ruby internal box has two isizes, which
      30             :  * are the reflowed isize and the final isize. The reflowed isize is
      31             :  * what a box itself needs. It is determined when the box gets reflowed.
      32             :  *
      33             :  * The final isize is what a box should be as the final result. For a
      34             :  * ruby base/text box, the final isize is the size of its ruby column.
      35             :  * For a ruby base/text container, the final isize is the size of its
      36             :  * ruby segment. The final isize is never smaller than the reflowed
      37             :  * isize. It is initially determined when a ruby column/segment gets
      38             :  * fully reflowed, and may be advanced when a box is expanded, e.g.
      39             :  * for justification.
      40             :  *
      41             :  * The difference between the reflowed isize and the final isize is
      42             :  * reserved in the line layout after reflowing a box, hence it is called
      43             :  * "Reserved ISize" here. It is used to expand the ruby boxes from their
      44             :  * reflowed isize to the final isize during alignment of the line.
      45             :  *
      46             :  * There are three exceptions for the final isize:
      47             :  * 1. A ruby text container has a larger final isize only if it is for
      48             :  *    a span or collapsed annotations.
      49             :  * 2. A ruby base container has a larger final isize only if at least
      50             :  *    one of its ruby text containers does.
      51             :  * 3. If a ruby text container has a larger final isize, its children
      52             :  *    must not have.
      53             :  */
      54             : 
      55             : class RubyUtils
      56             : {
      57             : public:
      58         520 :   static inline bool IsRubyContentBox(LayoutFrameType aFrameType)
      59             :   {
      60         520 :     return aFrameType == mozilla::LayoutFrameType::RubyBase ||
      61         520 :            aFrameType == mozilla::LayoutFrameType::RubyText;
      62             :   }
      63             : 
      64         512 :   static inline bool IsRubyContainerBox(LayoutFrameType aFrameType)
      65             :   {
      66         512 :     return aFrameType == mozilla::LayoutFrameType::RubyBaseContainer ||
      67         512 :            aFrameType == mozilla::LayoutFrameType::RubyTextContainer;
      68             :   }
      69             : 
      70         435 :   static inline bool IsRubyBox(LayoutFrameType aFrameType)
      71             :   {
      72         435 :     return aFrameType == mozilla::LayoutFrameType::Ruby ||
      73         870 :            IsRubyContentBox(aFrameType) || IsRubyContainerBox(aFrameType);
      74             :   }
      75             : 
      76           0 :   static inline bool IsExpandableRubyBox(nsIFrame* aFrame)
      77             :   {
      78           0 :     mozilla::LayoutFrameType type = aFrame->Type();
      79           0 :     return IsRubyContentBox(type) || IsRubyContainerBox(type);
      80             :   }
      81             : 
      82         276 :   static inline bool IsRubyPseudo(nsIAtom* aPseudo)
      83             :   {
      84         552 :     return aPseudo == nsCSSAnonBoxes::ruby ||
      85         552 :            aPseudo == nsCSSAnonBoxes::rubyBase ||
      86         552 :            aPseudo == nsCSSAnonBoxes::rubyText ||
      87         828 :            aPseudo == nsCSSAnonBoxes::rubyBaseContainer ||
      88         552 :            aPseudo == nsCSSAnonBoxes::rubyTextContainer;
      89             :   }
      90             : 
      91             :   static void SetReservedISize(nsIFrame* aFrame, nscoord aISize);
      92             :   static void ClearReservedISize(nsIFrame* aFrame);
      93             :   static nscoord GetReservedISize(nsIFrame* aFrame);
      94             : };
      95             : 
      96             : /**
      97             :  * This array stores all ruby text containers of the ruby segment
      98             :  * of the given ruby base container.
      99             :  */
     100           0 : class MOZ_RAII AutoRubyTextContainerArray final
     101             :   : public AutoTArray<nsRubyTextContainerFrame*, RTC_ARRAY_SIZE>
     102             : {
     103             : public:
     104             :   explicit AutoRubyTextContainerArray(nsRubyBaseContainerFrame* aBaseContainer);
     105             : };
     106             : 
     107             : /**
     108             :  * This enumerator enumerates each ruby segment.
     109             :  */
     110             : class MOZ_STACK_CLASS RubySegmentEnumerator
     111             : {
     112             : public:
     113             :   explicit RubySegmentEnumerator(nsRubyFrame* aRubyFrame);
     114             : 
     115             :   void Next();
     116           0 :   bool AtEnd() const { return !mBaseContainer; }
     117             : 
     118           0 :   nsRubyBaseContainerFrame* GetBaseContainer() const
     119             :   {
     120           0 :     return mBaseContainer;
     121             :   }
     122             : 
     123             : private:
     124             :   nsRubyBaseContainerFrame* mBaseContainer;
     125             : };
     126             : 
     127             : /**
     128             :  * Ruby column is a unit consists of one ruby base and all ruby
     129             :  * annotations paired with it.
     130             :  * See http://dev.w3.org/csswg/css-ruby/#ruby-pairing
     131             :  */
     132           0 : struct MOZ_STACK_CLASS RubyColumn
     133             : {
     134             :   nsRubyBaseFrame* mBaseFrame;
     135             :   AutoTArray<nsRubyTextFrame*, RTC_ARRAY_SIZE> mTextFrames;
     136             :   bool mIsIntraLevelWhitespace;
     137             : 
     138           0 :   RubyColumn() : mBaseFrame(nullptr), mIsIntraLevelWhitespace(false) { }
     139             : 
     140             :   // Helper class to support iteration across the frames within a single
     141             :   // RubyColumn (the column's ruby base and its annotations).
     142             :   class MOZ_STACK_CLASS Iterator
     143             :   {
     144             :   public:
     145             :     nsIFrame* operator*() const;
     146             : 
     147           0 :     Iterator& operator++() { ++mIndex; SkipUntilExistingFrame(); return *this; }
     148             :     Iterator operator++(int) { auto ret = *this; ++*this; return ret; }
     149             : 
     150           0 :     friend bool operator==(const Iterator& aIter1, const Iterator& aIter2)
     151             :     {
     152           0 :       MOZ_ASSERT(&aIter1.mColumn == &aIter2.mColumn,
     153             :                  "Should only compare iterators of the same ruby column");
     154           0 :       return aIter1.mIndex == aIter2.mIndex;
     155             :     }
     156           0 :     friend bool operator!=(const Iterator& aIter1, const Iterator& aIter2)
     157             :     {
     158           0 :       return !(aIter1 == aIter2);
     159             :     }
     160             : 
     161             :   private:
     162           0 :     Iterator(const RubyColumn& aColumn, int32_t aIndex)
     163           0 :       : mColumn(aColumn)
     164           0 :       , mIndex(aIndex)
     165             :     {
     166           0 :       MOZ_ASSERT(aIndex == -1 ||
     167             :                  (aIndex >= 0 &&
     168             :                   aIndex <= int32_t(aColumn.mTextFrames.Length())));
     169           0 :       SkipUntilExistingFrame();
     170           0 :     }
     171             :     friend struct RubyColumn; // for the constructor
     172             : 
     173             :     void SkipUntilExistingFrame();
     174             : 
     175             :     const RubyColumn& mColumn;
     176             :     // -1 means the ruby base frame,
     177             :     // non-negative means the index of ruby text frame
     178             :     // a value of mTextFrames.Length() means we're done iterating
     179             :     int32_t mIndex = -1;
     180             :   };
     181             : 
     182           0 :   Iterator begin() const { return Iterator(*this, -1); }
     183           0 :   Iterator end() const { return Iterator(*this, mTextFrames.Length()); }
     184             :   Iterator cbegin() const { return begin(); }
     185             :   Iterator cend() const { return end(); }
     186             : };
     187             : 
     188             : /**
     189             :  * This enumerator enumerates ruby columns in a segment.
     190             :  */
     191           0 : class MOZ_STACK_CLASS RubyColumnEnumerator
     192             : {
     193             : public:
     194             :   RubyColumnEnumerator(nsRubyBaseContainerFrame* aRBCFrame,
     195             :                        const AutoRubyTextContainerArray& aRTCFrames);
     196             : 
     197             :   void Next();
     198             :   bool AtEnd() const;
     199             : 
     200           0 :   uint32_t GetLevelCount() const { return mFrames.Length(); }
     201             :   nsRubyContentFrame* GetFrameAtLevel(uint32_t aIndex) const;
     202             :   void GetColumn(RubyColumn& aColumn) const;
     203             : 
     204             : private:
     205             :   // Frames in this array are NOT necessary part of the current column.
     206             :   // When in doubt, use GetFrameAtLevel to access it.
     207             :   // See GetFrameAtLevel() and Next() for more info.
     208             :   AutoTArray<nsRubyContentFrame*, RTC_ARRAY_SIZE + 1> mFrames;
     209             :   // Whether we are on a column for intra-level whitespaces
     210             :   bool mAtIntraLevelWhitespace;
     211             : };
     212             : 
     213             : /**
     214             :  * Stores block-axis leadings produced from ruby annotations.
     215             :  */
     216           0 : struct RubyBlockLeadings
     217             : {
     218             :   nscoord mStart = 0;
     219             :   nscoord mEnd = 0;
     220             : 
     221           0 :   void Reset() {
     222           0 :     mStart = mEnd = 0;
     223           0 :   }
     224           0 :   void Update(nscoord aStart, nscoord aEnd) {
     225           0 :     mStart = std::max(mStart, aStart);
     226           0 :     mEnd = std::max(mEnd, aEnd);
     227           0 :   }
     228           0 :   void Update(const RubyBlockLeadings& aOther) {
     229           0 :     Update(aOther.mStart, aOther.mEnd);
     230           0 :   }
     231             : };
     232             : 
     233             : } // namespace mozilla
     234             : 
     235             : #endif /* !defined(mozilla_RubyUtils_h_) */

Generated by: LCOV version 1.13