summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Hung <marklh9@gmail.com>2018-01-20 23:35:44 +0800
committerMark Hung <marklh9@gmail.com>2018-01-21 08:43:14 +0100
commitd1bc14b318c9a412a761d243085da0895a1aed4a (patch)
treeea4dbeaf9c053974e690dc8b856fb4b66638ffe5
parent121f6f3c79ea2dceb7cc3d61a56f5a56a1cb0d0d (diff)
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@libreoffice.org> Reviewed-by: Mark Hung <marklh9@gmail.com>
-rw-r--r--sw/source/core/text/itrform2.cxx17
-rw-r--r--sw/source/core/text/pormulti.cxx79
-rw-r--r--sw/source/core/text/pormulti.hxx19
3 files changed, 70 insertions, 45 deletions
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 )