[Libreoffice-commits] core.git: sw/source

Mark Hung marklh9 at gmail.com
Sun Jan 21 07:43:40 UTC 2018


 sw/source/core/text/itrform2.cxx |   17 --------
 sw/source/core/text/pormulti.cxx |   79 +++++++++++++++++++++++++++------------
 sw/source/core/text/pormulti.hxx |   19 ++++++---
 3 files changed, 70 insertions(+), 45 deletions(-)

New commits:
commit d1bc14b318c9a412a761d243085da0895a1aed4a
Author: Mark Hung <marklh9 at gmail.com>
Date:   Sat Jan 20 23:35:44 2018 +0800

    tdf#35301 Formatting ruby text on right side.
    
    * BuildMultiPortion(): preserve room for the ruby text by
      increasing the width of the last portion of the base text.
      This allows the ruby portion to be selected with the base
      text so that they seemd like attached to each other.
    
    * CalcSize(): we need to be careful because the width and
      height of the base text line is swapped.
    
    * PaintMultiPortion(): render the base text on top of the
      preserved room mentioned above, by shifting the position
      back.
    
    * SwRubyPortion(): RubyPortion::RIGHT is designed for
      horizontal writing mode only. In vertical writing
      mode it fallback to RubyPortion::ABOVE.
    
    Change-Id: I5291e32221b6b2fc1c3e152b3a5defe857428163
    Reviewed-on: https://gerrit.libreoffice.org/48244
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Mark Hung <marklh9 at gmail.com>

diff --git a/sw/source/core/text/itrform2.cxx b/sw/source/core/text/itrform2.cxx
index 1346390589cc..fbaa66dedc7b 100644
--- a/sw/source/core/text/itrform2.cxx
+++ b/sw/source/core/text/itrform2.cxx
@@ -1252,24 +1252,9 @@ SwLinePortion *SwTextFormatter::NewPortion( SwTextFormatInfo &rInf )
                     pTmp = new SwBidiPortion( nEnd, pCreate->nLevel );
                 else if ( SwMultiCreatorId::Ruby == pCreate->nId )
                 {
-                    Seek( rInf.GetIdx() );
-                    bool bRubyTop = false;
-                    bool* pRubyPos = nullptr;
-
-                    if ( rInf.SnapToGrid() )
-                    {
-                        SwTextGridItem const*const pGrid(
-                                GetGridItem(GetTextFrame()->FindPageFrame()));
-                        if ( pGrid )
-                        {
-                            bRubyTop = ! pGrid->GetRubyTextBelow();
-                            pRubyPos = &bRubyTop;
-                        }
-                    }
-
                     pTmp = new SwRubyPortion( *pCreate, *rInf.GetFont(),
                                               *GetTextFrame()->GetTextNode()->getIDocumentSettingAccess(),
-                                              nEnd, 0, pRubyPos );
+                                              nEnd, 0, rInf );
                 }
                 else if( SwMultiCreatorId::Rotate == pCreate->nId )
                     pTmp = new SwRotatedPortion( *pCreate, nEnd,
diff --git a/sw/source/core/text/pormulti.cxx b/sw/source/core/text/pormulti.cxx
index b35760f763ba..03f7e8592625 100644
--- a/sw/source/core/text/pormulti.cxx
+++ b/sw/source/core/text/pormulti.cxx
@@ -92,7 +92,17 @@ void SwMultiPortion::CalcSize( SwTextFormatter& rLine, SwTextFormatInfo &rInf )
         }
         else
             SetAscent( GetAscent() + pLay->GetAscent() );
-        Height( Height() + pLay->Height() );
+
+        // Increase the line height, except for ruby text on the right.
+        if ( !IsRuby() || !OnRight() || pLay == &GetRoot() )
+            Height( Height() + pLay->Height() );
+        else
+        {
+            // We already added the width after building the portion,
+            // so no need to add it twice.
+            break;
+        }
+
         if( Width() < pLay->Width() )
             Width( pLay->Width() );
         pLay = pLay->GetNext();
@@ -538,7 +548,7 @@ SwRubyPortion::SwRubyPortion( const SwRubyPortion& rRuby, sal_Int32 nEnd ) :
     nAdjustment( rRuby.GetAdjustment() )
 {
     SetDirection( rRuby.GetDirection() );
-    SetTop( rRuby.OnTop() );
+    SetRubyPosition( rRuby.GetRubyPosition() );
     SetRuby();
 }
 
@@ -547,7 +557,7 @@ SwRubyPortion::SwRubyPortion( const SwRubyPortion& rRuby, sal_Int32 nEnd ) :
 SwRubyPortion::SwRubyPortion( const SwMultiCreator& rCreate, const SwFont& rFnt,
                               const IDocumentSettingAccess& rIDocumentSettingAccess,
                               sal_Int32 nEnd, sal_Int32 nOffs,
-                              const bool* pForceRubyPos )
+                              const SwTextSizeInfo &rInf )
      : SwMultiPortion( nEnd )
 {
     SetRuby();
@@ -557,11 +567,22 @@ SwRubyPortion::SwRubyPortion( const SwMultiCreator& rCreate, const SwFont& rFnt,
     nAdjustment = rRuby.GetAdjustment();
     nRubyOffset = nOffs;
 
-    // in grid mode we force the ruby text to the upper or lower line
-    if ( pForceRubyPos )
-        SetTop( *pForceRubyPos );
-    else
-        SetTop( ! rRuby.GetPosition() );
+    const SwTextFrame *pFrame = rInf.GetTextFrame();
+    RubyPosition ePos = static_cast<RubyPosition>( rRuby.GetPosition() );
+
+    // RIGHT is designed for horizontal writing mode only.
+    if ( ePos == RubyPosition::RIGHT && pFrame->IsVertical() )
+        ePos = RubyPosition::ABOVE;
+
+    // In grid mode we force the ruby text to the upper or lower line
+    if ( rInf.SnapToGrid() )
+    {
+        SwTextGridItem const*const pGrid( GetGridItem(pFrame->FindPageFrame()) );
+        if ( pGrid )
+            ePos = pGrid->GetRubyTextBelow() ? RubyPosition::BELOW : RubyPosition::ABOVE;
+    }
+
+    SetRubyPosition( ePos );
 
     const SwCharFormat *const pFormat =
         static_txtattr_cast<SwTextRuby const*>(rCreate.pAttr)->GetCharFormat();
@@ -573,7 +594,7 @@ SwRubyPortion::SwRubyPortion( const SwMultiCreator& rCreate, const SwFont& rFnt,
         pRubyFont->SetDiffFnt( &rSet, &rIDocumentSettingAccess );
 
         // we do not allow a vertical font for the ruby text
-        pRubyFont->SetVertical( rFnt.GetOrientation() );
+        pRubyFont->SetVertical( rFnt.GetOrientation() , OnRight() );
     }
     else
         pRubyFont = nullptr;
@@ -1393,6 +1414,9 @@ void SwTextPainter::PaintMultiPortion( const SwRect &rPaint,
     OSL_ENSURE( nullptr == GetInfo().GetUnderFnt() || rMulti.IsBidi(),
             " Only BiDi portions are allowed to use the common underlining font" );
 
+    if ( rMulti.IsRuby() )
+        GetInfo().SetRuby( rMulti.OnTop() );
+
     do
     {
         if ( bHasGrid && pGrid->IsSquaredMode() )
@@ -1431,6 +1455,13 @@ void SwTextPainter::PaintMultiPortion( const SwRect &rPaint,
             else
                 GetInfo().X( nOfst + AdjustBaseLine( *pLay, pPor ) );
         }
+        else if ( rMulti.IsRuby() && rMulti.OnRight() && GetInfo().IsRuby() )
+        {
+            SwTwips nLineDiff = std::max(( rMulti.GetRoot().Height() - pPor->Width() ) / 2, 0 );
+            GetInfo().Y( nOfst + nLineDiff );
+            // Draw the ruby text on top of the preserved space.
+            GetInfo().X( GetInfo().X() - pPor->Height() );
+        }
         else
             GetInfo().Y( nOfst + AdjustBaseLine( *pLay, pPor ) );
 
@@ -1535,6 +1566,11 @@ void SwTextPainter::PaintMultiPortion( const SwRect &rPaint,
                 {
                     nOfst += rMulti.GetRoot().Height();
                 }
+            }
+            else if ( rMulti.IsRuby() && rMulti.OnRight() )
+            {
+                GetInfo().SetDirection( DIR_TOP2BOTTOM );
+                GetInfo().SetRuby( true );
             } else
             {
                 GetInfo().X( nTmpX );
@@ -1840,6 +1876,15 @@ bool SwTextFormatter::BuildMultiPortion( SwTextFormatInfo &rInf,
 
             BuildPortions( aTmp );
 
+            if ( rMulti.OnRight() )
+            {
+                // The ruby text on the right is vertical.
+                // The width and the height are swapped.
+                SwTwips nHeight = rMulti.GetRoot().GetNext()->GetPortion()->Height();
+                // Keep room for the ruby text.
+                rMulti.GetRoot().FindLastPortion()->AddPrtWidth( nHeight );
+            }
+
             aTmp.SetSnapToGrid( bOldGridModeAllowed );
 
             rMulti.CalcSize( *this, aInf );
@@ -2191,24 +2236,10 @@ SwLinePortion* SwTextFormatter::MakeRestPortion( const SwLineLayout* pLine,
             pTmp = new SwBidiPortion( nMultiPos, pCreate->nLevel );
         else if( pHelpMulti->IsRuby() )
         {
-            bool bRubyTop;
-            bool* pRubyPos = nullptr;
-
-            if ( GetInfo().SnapToGrid() )
-            {
-                SwTextGridItem const*const pGrid(
-                        GetGridItem(m_pFrame->FindPageFrame()));
-                if ( pGrid )
-                {
-                    bRubyTop = ! pGrid->GetRubyTextBelow();
-                    pRubyPos = &bRubyTop;
-                }
-            }
-
             pTmp = new SwRubyPortion( *pCreate, *GetInfo().GetFont(),
                                       *m_pFrame->GetTextNode()->getIDocumentSettingAccess(),
                                        nMultiPos, static_cast<const SwRubyPortion*>(pHelpMulti)->GetRubyOffset(),
-                                       pRubyPos );
+                                       GetInfo() );
         }
         else if( pHelpMulti->HasRotation() )
             pTmp = new SwRotatedPortion( nMultiPos, pHelpMulti->GetDirection() );
diff --git a/sw/source/core/text/pormulti.hxx b/sw/source/core/text/pormulti.hxx
index 2061c035c6e7..62cb236f5bb8 100644
--- a/sw/source/core/text/pormulti.hxx
+++ b/sw/source/core/text/pormulti.hxx
@@ -43,6 +43,13 @@ enum class SwMultiCreatorId
     Double, Ruby, Rotate, Bidi
 };
 
+enum class RubyPosition : sal_uInt16
+{
+    ABOVE = 0,
+    BELOW = 1,
+    RIGHT = 2
+};
+
 struct SwMultiCreator
 {
     const SwTextAttr* pAttr;
@@ -80,10 +87,10 @@ class SwMultiPortion : public SwLinePortion
     bool bDouble    :1;     // Double line
     bool bRuby      :1;     // Phonetics
     bool bBidi      :1;
-    bool bTop       :1;     // Phonetic position
     bool bFormatted :1;     // Already formatted
     bool bFollowField :1;     // Field follow inside
     bool bFlyInContent:1;     // Fly as character inside
+    RubyPosition eRubyPosition;     // Phonetic position
     sal_uInt8 nDirection:2; // Direction (0/90/180/270 degrees)
 protected:
     explicit SwMultiPortion(sal_Int32 nEnd)
@@ -92,10 +99,10 @@ protected:
         , bDouble(false)
         , bRuby(false)
         , bBidi(false)
-        , bTop(false)
         , bFormatted(false)
         , bFollowField(false)
         , bFlyInContent(false)
+        , eRubyPosition( RubyPosition::ABOVE )
         , nDirection(0)
     {
         SetWhichPor(POR_MULTI);
@@ -104,7 +111,7 @@ protected:
     void SetDouble() { bDouble = true; }
     void SetRuby() { bRuby = true; }
     void SetBidi() { bBidi = true; }
-    void SetTop( bool bNew ) { bTop = bNew; }
+    void SetRubyPosition( RubyPosition eNew ) { eRubyPosition = eNew; }
     void SetTab1( bool bNew ) { bTab1 = bNew; }
     void SetTab2( bool bNew ) { bTab2 = bNew; }
     void SetDirection( sal_uInt8 nNew ) { nDirection = nNew; }
@@ -125,7 +132,9 @@ public:
     bool IsDouble() const { return bDouble; }
     bool IsRuby() const { return bRuby; }
     bool IsBidi() const { return bBidi; }
-    bool OnTop() const { return bTop; }
+    bool OnTop() const { return eRubyPosition == RubyPosition::ABOVE; }
+    bool OnRight() const { return eRubyPosition == RubyPosition::RIGHT; }
+    RubyPosition GetRubyPosition() const { return eRubyPosition; }
     void ActualizeTabulator();
 
     virtual void Paint( const SwTextPaintInfo &rInf ) const override;
@@ -188,7 +197,7 @@ public:
     SwRubyPortion( const SwMultiCreator& rCreate, const SwFont& rFnt,
                    const IDocumentSettingAccess& rIDocumentSettingAccess,
                    sal_Int32 nEnd, sal_Int32 nOffs,
-                   const bool* pForceRubyPos );
+                   const SwTextSizeInfo &rInf );
 
     void CalcRubyOffset();
     void Adjust( SwTextFormatInfo &rInf )


More information about the Libreoffice-commits mailing list