[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