From 253e2035474b830c07bf327ca7204fa362312a47 Mon Sep 17 00:00:00 2001 From: Tamás Zolnai Date: Tue, 28 Mar 2017 19:24:49 +0200 Subject: tdf#105286: Implement text rotation for Impress tables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Typo: TopToBotton -> TopToBottom Change-Id: I1b4d3ab9ec1d1383d76a56c9662ffeeb9fe69655 Reviewed-on: https://gerrit.libreoffice.org/36014 Tested-by: Jenkins Reviewed-by: Tamás Zolnai (cherry picked from commit 334e6e2f1ad3da319be0849ec426aa64b18cb599) Add SvxTextRotateItem inherited from SvxCharRotatItem I will be use it later for text rotation inside a table. Change-Id: I4cbaf05953b0e71331d2f3fdb45b7c4254a2b8cc Reviewed-on: https://gerrit.libreoffice.org/36021 Reviewed-by: Tamás Zolnai Tested-by: Tamás Zolnai (cherry picked from commit 1e30d2aface12a31687e5a27126e2061efd4b0cd) Introduce text rotation for Impress tables * Introduce new table property for text rotation * Support only two rotation angle (270° and 90°) * Implement editing and rendering of 270° rotated text (90° rotation was already implemented) (cherry picked from commit c671094154ecec6f3ba5beea9d26ff0d2d4d86ad) Change-Id: Ifc2e0f171e9c840e86b365e9af2c30aa97ecd92e Implement RotateAngle API property for Impress table cells (cherry picked from commit a0755ab8772d01797f4945016a978a2bbd8fdf20) Change-Id: I01379c0fc21e8fe294bc882bf824f64502863ff4 tdf#100926: PPTX import of table with rotated text (cherry picked from commit 2436cf17304f25c7d34da52a321d6da0e9011d19) Change-Id: I05a8e979ac11b179e15784023032a56edc5b569b ODF import / export of rotated text in Impress table (cherry picked from commit bcb371b1a830442610ad7fda476eda5271427a50) Change-Id: I57136e32ed2db5e405a45e8e4bad1b8d459b7ae8 Fix vertical text and bitmap bullet rendering Change-Id: I881fce0511c81b164516d68f72c7e750687d4e0e (cherry picked from commit 15ac3f9f4dc65fc0c6020284064e3725956f5d0a) --- editeng/source/editeng/editdoc.cxx | 3 +- editeng/source/editeng/editdoc.hxx | 5 +- editeng/source/editeng/editeng.cxx | 21 ++++- editeng/source/editeng/editobj.cxx | 40 +++++++-- editeng/source/editeng/editobj2.hxx | 6 +- editeng/source/editeng/impedit.cxx | 82 ++++++++++++++---- editeng/source/editeng/impedit.hxx | 4 +- editeng/source/editeng/impedit3.cxx | 161 ++++++++++++++++++++++++++++------- editeng/source/editeng/impedit4.cxx | 4 +- editeng/source/items/svxitems.src | 8 ++ editeng/source/items/textitem.cxx | 119 +++++++++++++++++++++++--- editeng/source/outliner/outlin2.cxx | 9 +- editeng/source/outliner/outliner.cxx | 29 +++++-- editeng/source/outliner/outlobj.cxx | 12 ++- 14 files changed, 413 insertions(+), 90 deletions(-) (limited to 'editeng/source') diff --git a/editeng/source/editeng/editdoc.cxx b/editeng/source/editeng/editdoc.cxx index a7a73ceea4f6..8763b0733594 100644 --- a/editeng/source/editeng/editdoc.cxx +++ b/editeng/source/editeng/editdoc.cxx @@ -1982,6 +1982,7 @@ EditDoc::EditDoc( SfxItemPool* pPool ) : pItemPool(pPool ? pPool : new EditEngineItemPool(false)), nDefTab(DEFTAB), bIsVertical(false), + bIsTopToBottomVert(false), bIsFixedCellHeight(false), bOwnerOfPool(pPool == nullptr), bModified(false) @@ -2116,7 +2117,7 @@ void EditDoc::CreateDefFont( bool bUseStyles ) SfxItemSet aTmpSet( GetItemPool(), EE_PARA_START, EE_CHAR_END ); CreateFont( aDefFont, aTmpSet ); aDefFont.SetVertical( IsVertical() ); - aDefFont.SetOrientation( IsVertical() ? 2700 : 0 ); + aDefFont.SetOrientation( IsVertical() ? (IsTopToBottom() ? 2700 : 900) : 0 ); for ( sal_Int32 nNode = 0; nNode < Count(); nNode++ ) { diff --git a/editeng/source/editeng/editdoc.hxx b/editeng/source/editeng/editdoc.hxx index 63d5961165ac..bb647933fab5 100644 --- a/editeng/source/editeng/editdoc.hxx +++ b/editeng/source/editeng/editdoc.hxx @@ -739,6 +739,7 @@ private: SvxFont aDefFont; //faster than ever from the pool!! sal_uInt16 nDefTab; bool bIsVertical:1; + bool bIsTopToBottomVert : 1; bool bIsFixedCellHeight:1; bool bOwnerOfPool:1; @@ -765,8 +766,10 @@ public: void SetDefTab( sal_uInt16 nTab ) { nDefTab = nTab ? nTab : DEFTAB; } sal_uInt16 GetDefTab() const { return nDefTab; } - void SetVertical( bool bVertical ) { bIsVertical = bVertical; } + void SetVertical( bool bVertical, bool bTopToBottom = true ) + { bIsVertical = bVertical; bIsTopToBottomVert = bVertical && bTopToBottom; } bool IsVertical() const { return bIsVertical; } + bool IsTopToBottom() const { return bIsTopToBottomVert; } void SetFixedCellHeight( bool bUseFixedCellHeight ) { bIsFixedCellHeight = bUseFixedCellHeight; } bool IsFixedCellHeight() const { return bIsFixedCellHeight; } diff --git a/editeng/source/editeng/editeng.cxx b/editeng/source/editeng/editeng.cxx index bde286a10b72..5f88c0e36a10 100644 --- a/editeng/source/editeng/editeng.cxx +++ b/editeng/source/editeng/editeng.cxx @@ -429,9 +429,9 @@ const Size& EditEngine::GetPaperSize() const return pImpEditEngine->GetPaperSize(); } -void EditEngine::SetVertical( bool bVertical ) +void EditEngine::SetVertical( bool bVertical, bool bTopToBottom ) { - pImpEditEngine->SetVertical( bVertical ); + pImpEditEngine->SetVertical( bVertical, bTopToBottom); } bool EditEngine::IsVertical() const @@ -439,6 +439,11 @@ bool EditEngine::IsVertical() const return pImpEditEngine->IsVertical(); } +bool EditEngine::IsTopToBottom() const +{ + return pImpEditEngine->IsTopToBottom(); +} + void EditEngine::SetFixedCellHeight( bool bUseFixedCellHeight ) { pImpEditEngine->SetFixedCellHeight( bUseFixedCellHeight ); @@ -1767,8 +1772,16 @@ void EditEngine::StripPortions() Rectangle aBigRect( Point( 0, 0 ), Size( 0x7FFFFFFF, 0x7FFFFFFF ) ); if ( IsVertical() ) { - aBigRect.Right() = 0; - aBigRect.Left() = -0x7FFFFFFF; + if( IsTopToBottom() ) + { + aBigRect.Right() = 0; + aBigRect.Left() = -0x7FFFFFFF; + } + else + { + aBigRect.Top() = -0x7FFFFFFF; + aBigRect.Bottom() = 0; + } } pImpEditEngine->Paint( aTmpDev.get(), aBigRect, Point(), true ); } diff --git a/editeng/source/editeng/editobj.cxx b/editeng/source/editeng/editobj.cxx index 5a370837d350..e64793cddc00 100644 --- a/editeng/source/editeng/editobj.cxx +++ b/editeng/source/editeng/editobj.cxx @@ -355,9 +355,14 @@ bool EditTextObject::IsVertical() const return mpImpl->IsVertical(); } -void EditTextObject::SetVertical( bool bVertical ) +bool EditTextObject::IsTopToBottom() const { - return mpImpl->SetVertical(bVertical); + return mpImpl->IsTopToBottom(); +} + +void EditTextObject::SetVertical( bool bVertical, bool bTopToBottom ) +{ + return mpImpl->SetVertical(bVertical, bTopToBottom); } SvtScriptType EditTextObject::GetScriptType() const @@ -562,6 +567,7 @@ EditTextObjectImpl::EditTextObjectImpl( EditTextObject* pFront, SfxItemPool* pP } bVertical = false; + bIsTopToBottomVert = false; bStoreUnicodeStrings = false; nScriptType = SvtScriptType::NONE; } @@ -574,6 +580,7 @@ EditTextObjectImpl::EditTextObjectImpl( EditTextObject* pFront, const EditTextOb nUserType = r.nUserType; nObjSettings = r.nObjSettings; bVertical = r.bVertical; + bIsTopToBottomVert = r.bIsTopToBottomVert; nScriptType = r.nScriptType; pPortionInfo = nullptr; // Do not copy PortionInfo bStoreUnicodeStrings = false; @@ -655,12 +662,22 @@ std::vector EditTextObjectImpl::GetSharedStrings() const return aSSs; } +bool EditTextObjectImpl::IsVertical() const +{ + return bVertical; +} + +bool EditTextObjectImpl::IsTopToBottom() const +{ + return bIsTopToBottomVert; +} -void EditTextObjectImpl::SetVertical( bool b ) +void EditTextObjectImpl::SetVertical( bool bVert, bool bTopToBottom) { - if ( b != bVertical ) + if (bVert != bVertical || bTopToBottom != (bVert && bIsTopToBottomVert)) { - bVertical = b; + bVertical = bVert; + bIsTopToBottomVert = bVert && bTopToBottom; ClearPortionInfo(); } } @@ -1090,7 +1107,7 @@ public: void EditTextObjectImpl::StoreData( SvStream& rOStream ) const { - sal_uInt16 nVer = 602; + sal_uInt16 nVer = 603; rOStream.WriteUInt16( nVer ); rOStream.WriteBool( bOwnerOfPool ); @@ -1229,6 +1246,7 @@ void EditTextObjectImpl::StoreData( SvStream& rOStream ) const rOStream.WriteUInt32( nObjSettings ); rOStream.WriteBool( bVertical ); + rOStream.WriteBool( bIsTopToBottomVert ); rOStream.WriteUInt16( static_cast(nScriptType) ); rOStream.WriteBool( bStoreUnicodeStrings ); @@ -1481,6 +1499,13 @@ void EditTextObjectImpl::CreateData( SvStream& rIStream ) bVertical = bTmp; } + if (nVersion >= 603) + { + bool bTmp(false); + rIStream.ReadCharAsBool(bTmp); + bIsTopToBottomVert = bTmp; + } + if ( nVersion >= 602 ) { sal_uInt16 aTmp16; @@ -1571,7 +1596,8 @@ bool EditTextObjectImpl::operator==( const EditTextObjectImpl& rCompare ) const ( nMetric != rCompare.nMetric ) || ( nUserType!= rCompare.nUserType ) || ( nScriptType != rCompare.nScriptType ) || - ( bVertical != rCompare.bVertical ) ) + ( bVertical != rCompare.bVertical ) || + ( bIsTopToBottomVert != rCompare.bIsTopToBottomVert ) ) return false; for (size_t i = 0, n = aContents.size(); i < n; ++i) diff --git a/editeng/source/editeng/editobj2.hxx b/editeng/source/editeng/editobj2.hxx index 9aaef1d441eb..746635409d8f 100644 --- a/editeng/source/editeng/editobj2.hxx +++ b/editeng/source/editeng/editobj2.hxx @@ -182,6 +182,7 @@ private: bool bOwnerOfPool:1; bool bVertical:1; + bool bIsTopToBottomVert : 1; bool bStoreUnicodeStrings:1; bool ImpChangeStyleSheets( const OUString& rOldName, SfxStyleFamily eOldFamily, @@ -204,8 +205,9 @@ public: void NormalizeString( svl::SharedStringPool& rPool ); std::vector GetSharedStrings() const; - bool IsVertical() const { return bVertical;} - void SetVertical( bool b ); + bool IsVertical() const; + bool IsTopToBottom() const; + void SetVertical( bool bVert, bool bTopToBottom = true); SvtScriptType GetScriptType() const { return nScriptType;} void SetScriptType( SvtScriptType nType ); diff --git a/editeng/source/editeng/impedit.cxx b/editeng/source/editeng/impedit.cxx index e4eb6156b27e..a8af19d86982 100644 --- a/editeng/source/editeng/impedit.cxx +++ b/editeng/source/editeng/impedit.cxx @@ -513,6 +513,11 @@ bool ImpEditView::IsVertical() const return pEditEngine->pImpEditEngine->IsVertical(); } +bool ImpEditView::IsTopToBottom() const +{ + return pEditEngine->pImpEditEngine->IsTopToBottom(); +} + Rectangle ImpEditView::GetVisDocArea() const { return Rectangle( GetVisDocLeft(), GetVisDocTop(), GetVisDocRight(), GetVisDocBottom() ); @@ -530,8 +535,16 @@ Point ImpEditView::GetDocPos( const Point& rWindowPos ) const } else { - aPoint.X() = rWindowPos.Y() - aOutArea.Top() + GetVisDocLeft(); - aPoint.Y() = aOutArea.Right() - rWindowPos.X() + GetVisDocTop(); + if (pEditEngine->pImpEditEngine->IsTopToBottom()) + { + aPoint.X() = rWindowPos.Y() - aOutArea.Top() + GetVisDocLeft(); + aPoint.Y() = aOutArea.Right() - rWindowPos.X() + GetVisDocTop(); + } + else + { + aPoint.X() = aOutArea.Bottom() - rWindowPos.Y() + GetVisDocLeft(); + aPoint.Y() = rWindowPos.X() - aOutArea.Left() + GetVisDocTop(); + } } return aPoint; @@ -549,8 +562,16 @@ Point ImpEditView::GetWindowPos( const Point& rDocPos ) const } else { - aPoint.X() = aOutArea.Right() - rDocPos.Y() + GetVisDocTop(); - aPoint.Y() = rDocPos.X() + aOutArea.Top() - GetVisDocLeft(); + if (pEditEngine->pImpEditEngine->IsTopToBottom()) + { + aPoint.X() = aOutArea.Right() - rDocPos.Y() + GetVisDocTop(); + aPoint.Y() = rDocPos.X() + aOutArea.Top() - GetVisDocLeft(); + } + else + { + aPoint.X() = aOutArea.Left() + rDocPos.Y() - GetVisDocTop(); + aPoint.Y() = aOutArea.Bottom() - rDocPos.X() + GetVisDocLeft(); + } } return aPoint; @@ -916,8 +937,8 @@ void ImpEditView::ShowCursor( bool bGotoCursor, bool bForceVisCursor ) if ( nDocDiffX | nDocDiffY ) { - long nDiffX = !IsVertical() ? nDocDiffX : -nDocDiffY; - long nDiffY = !IsVertical() ? nDocDiffY : nDocDiffX; + long nDiffX = !IsVertical() ? nDocDiffX : (IsTopToBottom() ? -nDocDiffY : nDocDiffY); + long nDiffY = !IsVertical() ? nDocDiffY : (IsTopToBottom() ? nDocDiffX : -nDocDiffX); // Negative: Back to the top or left edge if ( ( std::abs( nDiffY ) > pEditEngine->GetOnePixelInRef() ) && DoBigScroll() ) @@ -993,7 +1014,7 @@ void ImpEditView::ShowCursor( bool bGotoCursor, bool bForceVisCursor ) aCursorSz.Width() = aOldSz.Height(); aCursorSz.Height() = aOldSz.Width(); GetCursor()->SetPos( aCursorRect.TopRight() ); - GetCursor()->SetOrientation( 2700 ); + GetCursor()->SetOrientation( IsTopToBottom() ? 2700 : 900 ); } else // #i32593# Reset correct orientation in horizontal layout @@ -1087,8 +1108,16 @@ Pair ImpEditView::Scroll( long ndX, long ndY, ScrollRangeCheck nRangeCheck ) } else { - aNewVisArea.Top() += ndX; - aNewVisArea.Bottom() += ndX; + if( IsTopToBottom() ) + { + aNewVisArea.Top() += ndX; + aNewVisArea.Bottom() += ndX; + } + else + { + aNewVisArea.Top() -= ndX; + aNewVisArea.Bottom() -= ndX; + } } if ( ( nRangeCheck == ScrollRangeCheck::PaperWidthTextSize ) && ( aNewVisArea.Bottom() > (long)pEditEngine->pImpEditEngine->GetTextHeight() ) ) { @@ -1107,8 +1136,16 @@ Pair ImpEditView::Scroll( long ndX, long ndY, ScrollRangeCheck nRangeCheck ) } else { - aNewVisArea.Left() -= ndY; - aNewVisArea.Right() -= ndY; + if (IsTopToBottom()) + { + aNewVisArea.Left() -= ndY; + aNewVisArea.Right() -= ndY; + } + else + { + aNewVisArea.Left() += ndY; + aNewVisArea.Right() += ndY; + } } if ( ( nRangeCheck == ScrollRangeCheck::PaperWidthTextSize ) && ( aNewVisArea.Right() > (long)pEditEngine->pImpEditEngine->CalcTextWidth( false ) ) ) { @@ -1119,8 +1156,8 @@ Pair ImpEditView::Scroll( long ndX, long ndY, ScrollRangeCheck nRangeCheck ) aNewVisArea.Move( -aNewVisArea.Left(), 0 ); // The difference must be alignt on pixel (due to scroll!) - long nDiffX = !IsVertical() ? ( GetVisDocLeft() - aNewVisArea.Left() ) : -( GetVisDocTop() - aNewVisArea.Top() ); - long nDiffY = !IsVertical() ? ( GetVisDocTop() - aNewVisArea.Top() ) : ( GetVisDocLeft() - aNewVisArea.Left() ); + long nDiffX = !IsVertical() ? ( GetVisDocLeft() - aNewVisArea.Left() ) : (IsTopToBottom() ? -( GetVisDocTop() - aNewVisArea.Top() ) : (GetVisDocTop() - aNewVisArea.Top())); + long nDiffY = !IsVertical() ? ( GetVisDocTop() - aNewVisArea.Top() ) : (IsTopToBottom() ? (GetVisDocLeft() - aNewVisArea.Left()) : -(GetVisDocTop() - aNewVisArea.Top())); Size aDiffs( nDiffX, nDiffY ); aDiffs = pOutWin->LogicToPixel( aDiffs ); @@ -1139,7 +1176,12 @@ Pair ImpEditView::Scroll( long ndX, long ndY, ScrollRangeCheck nRangeCheck ) if ( !IsVertical() ) aVisDocStartPos.Move( -nRealDiffX, -nRealDiffY ); else - aVisDocStartPos.Move( -nRealDiffY, nRealDiffX ); + { + if (IsTopToBottom()) + aVisDocStartPos.Move(-nRealDiffY, nRealDiffX); + else + aVisDocStartPos.Move(nRealDiffY, -nRealDiffX); + } // Das Move um den allignten Wert ergibt nicht unbedingt ein // alligntes Rechteck... // Aligned value of the move does not necessarily result in aligned @@ -2117,8 +2159,16 @@ void ImpEditView::dragOver(const css::datatransfer::dnd::DropTargetDragEvent& rD } else { - aEditCursor.Left()--; - aEditCursor.Right()++; + if( IsTopToBottom() ) + { + aEditCursor.Left()--; + aEditCursor.Right()++; + } + else + { + aEditCursor.Left()++; + aEditCursor.Right()--; + } } aEditCursor = GetWindow()->PixelToLogic( aEditCursor ); } diff --git a/editeng/source/editeng/impedit.hxx b/editeng/source/editeng/impedit.hxx index 291a95ad572a..0958617c3bba 100644 --- a/editeng/source/editeng/impedit.hxx +++ b/editeng/source/editeng/impedit.hxx @@ -295,6 +295,7 @@ public: const Rectangle& GetOutputArea() const { return aOutArea; } bool IsVertical() const; + bool IsTopToBottom() const; bool PostKeyEvent( const KeyEvent& rKeyEvent, vcl::Window* pFrameWin ); @@ -720,8 +721,9 @@ public: const Size& GetPaperSize() const { return aPaperSize; } void SetPaperSize( const Size& rSz ) { aPaperSize = rSz; } - void SetVertical( bool bVertical ); + void SetVertical( bool bVertical, bool bTopToBottom = true); bool IsVertical() const { return GetEditDoc().IsVertical(); } + bool IsTopToBottom() const { return GetEditDoc().IsTopToBottom(); } bool IsPageOverflow( ) const; diff --git a/editeng/source/editeng/impedit3.cxx b/editeng/source/editeng/impedit3.cxx index cf66a4daaafd..0da41d7af407 100644 --- a/editeng/source/editeng/impedit3.cxx +++ b/editeng/source/editeng/impedit3.cxx @@ -2580,11 +2580,11 @@ void ImpEditEngine::SetTextRanger( TextRanger* pRanger ) } } -void ImpEditEngine::SetVertical( bool bVertical ) +void ImpEditEngine::SetVertical( bool bVertical, bool bTopToBottom) { - if ( IsVertical() != bVertical ) + if ( IsVertical() != bVertical || IsTopToBottom() != (bVertical && bTopToBottom)) { - GetEditDoc().SetVertical( bVertical ); + GetEditDoc().SetVertical( bVertical, bTopToBottom); bool bUseCharAttribs = bool(aStatus.GetControlWord() & EEControlBits::USECHARATTRIBS); GetEditDoc().CreateDefFont( bUseCharAttribs ); if ( IsFormatted() ) @@ -2963,7 +2963,8 @@ void ImpEditEngine::Paint( OutputDevice* pOutDev, Rectangle aClipRect, Point aSt sal_Int32 nIndex = 0; if ( pPortion->IsVisible() && ( ( !IsVertical() && ( ( aStartPos.Y() + nParaHeight ) > aClipRect.Top() ) ) || - ( IsVertical() && ( ( aStartPos.X() - nParaHeight ) < aClipRect.Right() ) ) ) ) + ( IsVertical() && IsTopToBottom() && ( ( aStartPos.X() - nParaHeight ) < aClipRect.Right() ) ) || + ( IsVertical() && !IsTopToBottom() && ( ( aStartPos.X() + nParaHeight ) > aClipRect.Left() ) ) ) ) { @@ -2977,7 +2978,12 @@ void ImpEditEngine::Paint( OutputDevice* pOutDev, Rectangle aClipRect, Point aSt if ( !IsVertical() ) aStartPos.Y() += pPortion->GetFirstLineOffset(); else - aStartPos.X() -= pPortion->GetFirstLineOffset(); + { + if( IsTopToBottom() ) + aStartPos.X() -= pPortion->GetFirstLineOffset(); + else + aStartPos.X() += pPortion->GetFirstLineOffset(); + } Point aParaStart( aStartPos ); @@ -3002,15 +3008,27 @@ void ImpEditEngine::Paint( OutputDevice* pOutDev, Rectangle aClipRect, Point aSt } else { - aTmpPos.Y() += pLine->GetStartPosX(); - aTmpPos.X() -= pLine->GetMaxAscent(); - aStartPos.X() -= pLine->GetHeight(); - if (nLine != nLastLine) - aStartPos.X() -= nVertLineSpacing; + if ( IsTopToBottom() ) + { + aTmpPos.Y() += pLine->GetStartPosX(); + aTmpPos.X() -= pLine->GetMaxAscent(); + aStartPos.X() -= pLine->GetHeight(); + if (nLine != nLastLine) + aStartPos.X() -= nVertLineSpacing; + } + else + { + aTmpPos.Y() -= pLine->GetStartPosX(); + aTmpPos.X() += pLine->GetMaxAscent(); + aStartPos.X() += pLine->GetHeight(); + if (nLine != nLastLine) + aStartPos.X() += nVertLineSpacing; + } } if ( ( !IsVertical() && ( aStartPos.Y() > aClipRect.Top() ) ) - || ( IsVertical() && aStartPos.X() < aClipRect.Right() ) ) + || ( IsVertical() && IsTopToBottom() && aStartPos.X() < aClipRect.Right() ) + || ( IsVertical() && !IsTopToBottom() && aStartPos.X() > aClipRect.Left() ) ) { bPaintBullet = false; @@ -3048,9 +3066,18 @@ void ImpEditEngine::Paint( OutputDevice* pOutDev, Rectangle aClipRect, Point aSt } else { - aTmpPos.Y() = aStartPos.Y() + nPortionXOffset; - if ( aTmpPos.Y() > aClipRect.Bottom() ) - break; // No further output in line necessary + if( IsTopToBottom() ) + { + aTmpPos.Y() = aStartPos.Y() + nPortionXOffset; + if ( aTmpPos.Y() > aClipRect.Bottom() ) + break; // No further output in line necessary + } + else + { + aTmpPos.Y() = aStartPos.Y() - nPortionXOffset; + if (aTmpPos.Y() < aClipRect.Top()) + break; // No further output in line necessary + } } switch ( rTextPortion.GetKind() ) @@ -3141,8 +3168,16 @@ void ImpEditEngine::Paint( OutputDevice* pOutDev, Rectangle aClipRect, Point aSt } else { - aTopLeftRectPos.Y() += nAdvanceX; - aTopLeftRectPos.X() -= nAdvanceY; + if( IsTopToBottom() ) + { + aTopLeftRectPos.Y() -= nAdvanceX; + aTopLeftRectPos.X() += nAdvanceY; + } + else + { + aTopLeftRectPos.Y() += nAdvanceX; + aTopLeftRectPos.X() -= nAdvanceY; + } } Point aBottomRightRectPos( aTopLeftRectPos ); @@ -3153,8 +3188,16 @@ void ImpEditEngine::Paint( OutputDevice* pOutDev, Rectangle aClipRect, Point aSt } else { - aBottomRightRectPos.X() -= pLine->GetHeight(); - aBottomRightRectPos.Y() += 2 * nHalfBlankWidth; + if (IsTopToBottom()) + { + aBottomRightRectPos.X() += pLine->GetHeight(); + aBottomRightRectPos.Y() -= 2 * nHalfBlankWidth; + } + else + { + aBottomRightRectPos.X() -= pLine->GetHeight(); + aBottomRightRectPos.Y() += 2 * nHalfBlankWidth; + } } pOutDev->Push( PushFlags::FILLCOLOR ); @@ -3187,7 +3230,10 @@ void ImpEditEngine::Paint( OutputDevice* pOutDev, Rectangle aClipRect, Point aSt } else { - aSlashPos.Y() = aTopLeftRectPos.Y() + nAddX; + if (IsTopToBottom()) + aSlashPos.Y() = aTopLeftRectPos.Y() + nAddX; + else + aSlashPos.Y() = aTopLeftRectPos.Y() - nAddX; } aTmpFont.QuickDrawText( pOutDev, aSlashPos, aSlash, 0, 1 ); @@ -3226,8 +3272,16 @@ void ImpEditEngine::Paint( OutputDevice* pOutDev, Rectangle aClipRect, Point aSt } else { - aTmpPos.X() -= pLine->GetMaxAscent(); - aStartPos.X() -= pLine->GetHeight(); + if (IsTopToBottom()) + { + aTmpPos.X() -= pLine->GetMaxAscent(); + aStartPos.X() -= pLine->GetHeight(); + } + else + { + aTmpPos.X() += pLine->GetMaxAscent(); + aStartPos.X() += pLine->GetHeight(); + } } } ::std::vector< sal_Int32 >::iterator curIt = itSubLines; @@ -3404,7 +3458,12 @@ void ImpEditEngine::Paint( OutputDevice* pOutDev, Rectangle aClipRect, Point aSt if ( !IsVertical() ) aOutPos.Y() -= nDiff; else - aOutPos.X() += nDiff; + { + if (IsTopToBottom()) + aOutPos.X() += nDiff; + else + aOutPos.X() -= nDiff; + } aRedLineTmpPos = aOutPos; aTmpFont.SetEscapement( 0 ); } @@ -3534,7 +3593,10 @@ void ImpEditEngine::Paint( OutputDevice* pOutDev, Rectangle aClipRect, Point aSt if( !IsVertical() ) aRedLineTmpPos.Y() -= nShift; else - aRedLineTmpPos.X() += nShift; + if (IsTopToBottom()) + aRedLineTmpPos.X() += nShift; + else + aRedLineTmpPos.X() -= nShift; } } Color aOldColor( pOutDev->GetLineColor() ); @@ -3651,13 +3713,20 @@ void ImpEditEngine::Paint( OutputDevice* pOutDev, Rectangle aClipRect, Point aSt if ( !IsVertical() ) aStartPos.Y() += nSBL; else - aStartPos.X() -= nSBL; + { + if( IsTopToBottom() ) + aStartPos.X() -= nSBL; + else + aStartPos.X() += nSBL; + } } // no more visible actions? if ( !IsVertical() && ( aStartPos.Y() >= aClipRect.Bottom() ) ) break; - else if ( IsVertical() && ( aStartPos.X() <= aClipRect.Left() ) ) + else if ( IsVertical() && IsTopToBottom() && ( aStartPos.X() <= aClipRect.Left() ) ) + break; + else if (IsVertical() && !IsTopToBottom() && (aStartPos.X() >= aClipRect.Right())) break; } @@ -3668,7 +3737,12 @@ void ImpEditEngine::Paint( OutputDevice* pOutDev, Rectangle aClipRect, Point aSt if ( !IsVertical() ) aStartPos.Y() += nUL; else - aStartPos.X() -= nUL; + { + if (IsTopToBottom()) + aStartPos.X() -= nUL; + else + aStartPos.X() += nUL; + } } // #108052# Safer way for #i108052# and #i118881#: If for the current ParaPortion @@ -3697,7 +3771,12 @@ void ImpEditEngine::Paint( OutputDevice* pOutDev, Rectangle aClipRect, Point aSt if ( !IsVertical() ) aStartPos.Y() += nParaHeight; else - aStartPos.X() -= nParaHeight; + { + if (IsTopToBottom()) + aStartPos.X() -= nParaHeight; + else + aStartPos.X() += nParaHeight; + } } if ( pPDFExtOutDevData ) @@ -3706,7 +3785,9 @@ void ImpEditEngine::Paint( OutputDevice* pOutDev, Rectangle aClipRect, Point aSt // no more visible actions? if ( !IsVertical() && ( aStartPos.Y() > aClipRect.Bottom() ) ) break; - if ( IsVertical() && ( aStartPos.X() < aClipRect.Left() ) ) + if ( IsVertical() && IsTopToBottom() && ( aStartPos.X() < aClipRect.Left() ) ) + break; + if (IsVertical() && !IsTopToBottom() && ( aStartPos.X() > aClipRect.Right() ) ) break; } if ( aStatus.DoRestoreFont() ) @@ -3735,9 +3816,18 @@ void ImpEditEngine::Paint( ImpEditView* pView, const Rectangle& rRect, OutputDev } else { - aStartPos = pView->GetOutputArea().TopRight(); - aStartPos.X() += pView->GetVisDocTop(); - aStartPos.Y() -= pView->GetVisDocLeft(); + if( IsTopToBottom() ) + { + aStartPos = pView->GetOutputArea().TopRight(); + aStartPos.X() += pView->GetVisDocTop(); + aStartPos.Y() -= pView->GetVisDocLeft(); + } + else + { + aStartPos = pView->GetOutputArea().BottomLeft(); + aStartPos.X() -= pView->GetVisDocTop(); + aStartPos.Y() += pView->GetVisDocLeft(); + } } // If Doc-width < Output Area,Width and not wrapped fields, @@ -4029,8 +4119,13 @@ long ImpEditEngine::CalcVertLineSpacing(Point& rStartPos) const return 0; if (IsVertical()) - // Shift the text to the right for the asian layout mode. - rStartPos.X() += nTotalSpace; + { + if( IsTopToBottom() ) + // Shift the text to the right for the asian layout mode. + rStartPos.X() += nTotalSpace; + else + rStartPos.X() -= nTotalSpace; + } return nTotalSpace / (nTotalLineCount-1); } diff --git a/editeng/source/editeng/impedit4.cxx b/editeng/source/editeng/impedit4.cxx index dde54ad48dc4..7cf098b3c279 100644 --- a/editeng/source/editeng/impedit4.cxx +++ b/editeng/source/editeng/impedit4.cxx @@ -1026,7 +1026,7 @@ EditTextObject* ImpEditEngine::CreateTextObject(const EditSelection& rSel) EditTextObject* ImpEditEngine::CreateTextObject( EditSelection aSel, SfxItemPool* pPool, bool bAllowBigObjects, sal_Int32 nBigObjectStart ) { EditTextObject* pTxtObj = new EditTextObject(pPool); - pTxtObj->SetVertical( IsVertical() ); + pTxtObj->SetVertical( IsVertical(), IsTopToBottom()); MapUnit eMapUnit = aEditDoc.GetItemPool().GetMetric( DEF_METRIC ); pTxtObj->mpImpl->SetMetric( (sal_uInt16) eMapUnit ); if ( pTxtObj->mpImpl->IsOwnerOfPool() ) @@ -1184,7 +1184,7 @@ void ImpEditEngine::SetText( const EditTextObject& rTextObject ) EnableUndo( false ); InsertText( rTextObject, EditSelection( aPaM, aPaM ) ); - SetVertical( rTextObject.IsVertical() ); + SetVertical( rTextObject.IsVertical(), rTextObject.IsTopToBottom()); DBG_ASSERT( !HasUndoManager() || !GetUndoManager().GetUndoActionCount(), "From where comes the Undo in SetText ?!" ); SetUpdateMode( _bUpdate ); diff --git a/editeng/source/items/svxitems.src b/editeng/source/items/svxitems.src index e173867c5cf9..c39eb0dc2306 100644 --- a/editeng/source/items/svxitems.src +++ b/editeng/source/items/svxitems.src @@ -943,6 +943,14 @@ String RID_SVXITEMS_CHARROTATE_FITLINE { Text [ en-US ] = "Fit to line"; }; +String RID_SVXITEMS_TEXTROTATE_OFF +{ + Text [ en-US ] = "Text is not rotated"; +}; +String RID_SVXITEMS_TEXTROTATE +{ + Text [ en-US ] = "Text is rotated by $(ARG1)°"; +}; String RID_SVXITEMS_CHARSCALE { Text [ en-US ] = "Characters scaled $(ARG1)%"; diff --git a/editeng/source/items/textitem.cxx b/editeng/source/items/textitem.cxx index 1e01793795cf..2bc2b9d82e02 100644 --- a/editeng/source/items/textitem.cxx +++ b/editeng/source/items/textitem.cxx @@ -2877,6 +2877,107 @@ sal_uInt16 SvxTwoLinesItem::GetVersion( sal_uInt16 nFFVer ) const } +/************************************************************************* +|* class SvxTextRotateItem +*************************************************************************/ + +SvxTextRotateItem::SvxTextRotateItem(sal_uInt16 nValue, const sal_uInt16 nW) + : SfxUInt16Item(nW, nValue) +{ +} + +SfxPoolItem* SvxTextRotateItem::Clone(SfxItemPool*) const +{ + return new SvxTextRotateItem(GetValue(), Which()); +} + +SfxPoolItem* SvxTextRotateItem::Create(SvStream& rStrm, sal_uInt16) const +{ + sal_uInt16 nVal; + rStrm.ReadUInt16(nVal); + return new SvxTextRotateItem(nVal, Which()); +} + +SvStream& SvxTextRotateItem::Store(SvStream & rStrm, sal_uInt16) const +{ + rStrm.WriteUInt16(GetValue()); + return rStrm; +} + +sal_uInt16 SvxTextRotateItem::GetVersion(sal_uInt16 nFFVer) const +{ + return SOFFICE_FILEFORMAT_50 > nFFVer ? USHRT_MAX : 0; +} + +bool SvxTextRotateItem::GetPresentation( + SfxItemPresentation /*ePres*/, + MapUnit /*eCoreMetric*/, MapUnit /*ePresMetric*/, + OUString &rText, const IntlWrapper*) const +{ + if (!GetValue()) + rText = EE_RESSTR(RID_SVXITEMS_TEXTROTATE_OFF); + else + { + rText = EE_RESSTR(RID_SVXITEMS_TEXTROTATE); + rText = rText.replaceFirst("$(ARG1)", + OUString::number(GetValue() / 10)); + } + return true; +} + +bool SvxTextRotateItem::QueryValue(css::uno::Any& rVal, + sal_uInt8 nMemberId) const +{ + nMemberId &= ~CONVERT_TWIPS; + bool bRet = true; + switch (nMemberId) + { + case MID_ROTATE: + rVal <<= (sal_Int16)GetValue(); + break; + default: + bRet = false; + break; + } + return bRet; +} + +bool SvxTextRotateItem::PutValue(const css::uno::Any& rVal, sal_uInt8 nMemberId) +{ + nMemberId &= ~CONVERT_TWIPS; + bool bRet = true; + switch (nMemberId) + { + case MID_ROTATE: + { + sal_Int16 nVal = 0; + if ((rVal >>= nVal) && (0 == nVal || 900 == nVal || 2700 == nVal)) + SetValue((sal_uInt16)nVal); + else + bRet = false; + break; + } + default: + bRet = false; + } + return bRet; +} + +bool SvxTextRotateItem::operator==(const SfxPoolItem& rItem) const +{ + assert(SfxPoolItem::operator==(rItem)); + return SfxUInt16Item::operator==(rItem); +} + +void SvxTextRotateItem::dumpAsXml(xmlTextWriterPtr pWriter) const +{ + xmlTextWriterStartElement(pWriter, BAD_CAST("SvxTextRotateItem")); + xmlTextWriterWriteAttribute(pWriter, BAD_CAST("whichId"), BAD_CAST(OString::number(Which()).getStr())); + xmlTextWriterWriteAttribute(pWriter, BAD_CAST("value"), BAD_CAST(OString::number(GetValue()).getStr())); + xmlTextWriterEndElement(pWriter); +} + + /************************************************************************* |* class SvxCharRotateItem *************************************************************************/ @@ -2884,7 +2985,7 @@ sal_uInt16 SvxTwoLinesItem::GetVersion( sal_uInt16 nFFVer ) const SvxCharRotateItem::SvxCharRotateItem( sal_uInt16 nValue, bool bFitIntoLine, const sal_uInt16 nW ) - : SfxUInt16Item( nW, nValue ), bFitToLine( bFitIntoLine ) + : SvxTextRotateItem(nValue, nW), bFitToLine( bFitIntoLine ) { } @@ -2934,12 +3035,11 @@ bool SvxCharRotateItem::GetPresentation( bool SvxCharRotateItem::QueryValue( css::uno::Any& rVal, sal_uInt8 nMemberId ) const { - nMemberId &= ~CONVERT_TWIPS; bool bRet = true; - switch( nMemberId ) + switch(nMemberId & ~CONVERT_TWIPS) { case MID_ROTATE: - rVal <<= (sal_Int16)GetValue(); + SvxTextRotateItem::QueryValue(rVal, nMemberId); break; case MID_FITTOLINE: rVal = css::uno::makeAny( IsFitToLine() ); @@ -2954,17 +3054,12 @@ bool SvxCharRotateItem::QueryValue( css::uno::Any& rVal, bool SvxCharRotateItem::PutValue( const css::uno::Any& rVal, sal_uInt8 nMemberId ) { - nMemberId &= ~CONVERT_TWIPS; bool bRet = true; - switch( nMemberId ) + switch(nMemberId & ~CONVERT_TWIPS) { case MID_ROTATE: { - sal_Int16 nVal = 0; - if((rVal >>= nVal) && (0 == nVal || 900 == nVal || 2700 == nVal)) - SetValue( (sal_uInt16)nVal ); - else - bRet = false; + bRet = SvxTextRotateItem::PutValue(rVal, nMemberId); break; } @@ -2980,7 +3075,7 @@ bool SvxCharRotateItem::PutValue( const css::uno::Any& rVal, bool SvxCharRotateItem::operator==( const SfxPoolItem& rItem ) const { assert(SfxPoolItem::operator==(rItem)); - return SfxUInt16Item::operator==( rItem ) && + return SvxTextRotateItem::operator==( rItem ) && IsFitToLine() == static_cast(rItem).IsFitToLine(); } diff --git a/editeng/source/outliner/outlin2.cxx b/editeng/source/outliner/outlin2.cxx index 3248ba34f51e..c89a89fdaffb 100644 --- a/editeng/source/outliner/outlin2.cxx +++ b/editeng/source/outliner/outlin2.cxx @@ -526,9 +526,9 @@ const EditEngine& Outliner::GetEditEngine() const return *pEditEngine; } -void Outliner::SetVertical( bool b ) +void Outliner::SetVertical( bool bVertical, bool bTopToBottom) { - pEditEngine->SetVertical( b ); + pEditEngine->SetVertical(bVertical, bTopToBottom); } bool Outliner::IsVertical() const @@ -536,6 +536,11 @@ bool Outliner::IsVertical() const return pEditEngine->IsVertical(); } +bool Outliner::IsTopToBottom() const +{ + return pEditEngine->IsTopToBottom(); +} + void Outliner::SetFixedCellHeight( bool bUseFixedCellHeight ) { pEditEngine->SetFixedCellHeight( bUseFixedCellHeight ); diff --git a/editeng/source/outliner/outliner.cxx b/editeng/source/outliner/outliner.cxx index a77e88199fa4..9943efdb0d26 100644 --- a/editeng/source/outliner/outliner.cxx +++ b/editeng/source/outliner/outliner.cxx @@ -861,7 +861,7 @@ vcl::Font Outliner::ImpCalcBulletFont( sal_Int32 nPara ) const aBulletFont.SetFontSize( Size( 0, nScaledLineHeight ) ); bool bVertical = IsVertical(); aBulletFont.SetVertical( bVertical ); - aBulletFont.SetOrientation( bVertical ? 2700 : 0 ); + aBulletFont.SetOrientation( bVertical ? (IsTopToBottom() ? 2700 : 900) : 0 ); Color aColor( COL_AUTO ); if( !pEditEngine->IsFlatMode() && !( pEditEngine->GetControlWord() & EEControlBits::NOCOLORS ) ) @@ -890,6 +890,7 @@ void Outliner::PaintBullet( sal_Int32 nPara, const Point& rStartPos, if (bDrawBullet && ImplHasNumberFormat(nPara)) { bool bVertical = IsVertical(); + bool bTopToBottom = IsTopToBottom(); bool bRightToLeftPara = pEditEngine->IsRightToLeft( nPara ); @@ -927,9 +928,17 @@ void Outliner::PaintBullet( sal_Int32 nPara, const Point& rStartPos, } else { -// aTextPos.X() = rStartPos.X() - aBulletArea.Bottom(); - aTextPos.X() = rStartPos.X() - ( bSymbol ? aBulletArea.Bottom() : aParaInfos.nFirstLineMaxAscent ); - aTextPos.Y() = rStartPos.Y() + aBulletArea.Left(); + if (bTopToBottom) + { +// aTextPos.X() = rStartPos.X() - aBulletArea.Bottom(); + aTextPos.X() = rStartPos.X() - (bSymbol ? aBulletArea.Bottom() : aParaInfos.nFirstLineMaxAscent); + aTextPos.Y() = rStartPos.Y() + aBulletArea.Left(); + } + else + { + aTextPos.X() = rStartPos.X() + (bSymbol ? aBulletArea.Bottom() : aParaInfos.nFirstLineMaxAscent); + aTextPos.Y() = rStartPos.Y() + aBulletArea.Left(); + } } if ( nOrientation ) @@ -998,8 +1007,16 @@ void Outliner::PaintBullet( sal_Int32 nPara, const Point& rStartPos, } else { - aBulletPos.X() = rStartPos.X() - aBulletArea.Bottom(); - aBulletPos.Y() = rStartPos.Y() + aBulletArea.Left(); + if (bTopToBottom) + { + aBulletPos.X() = rStartPos.X() - aBulletArea.Bottom(); + aBulletPos.Y() = rStartPos.Y() + aBulletArea.Left(); + } + else + { + aBulletPos.X() = rStartPos.X() + aBulletArea.Top(); + aBulletPos.Y() = rStartPos.Y() - aBulletArea.Right(); + } } if(bStrippingPortions) diff --git a/editeng/source/outliner/outlobj.cxx b/editeng/source/outliner/outlobj.cxx index 3eba88e27435..a993b8200c3e 100644 --- a/editeng/source/outliner/outlobj.cxx +++ b/editeng/source/outliner/outlobj.cxx @@ -131,12 +131,18 @@ bool OutlinerParaObject::IsVertical() const return mpImpl->mpEditTextObject->IsVertical(); } -void OutlinerParaObject::SetVertical(bool bNew) +bool OutlinerParaObject::IsTopToBottom() const +{ + return mpImpl->mpEditTextObject->IsTopToBottom(); +} + +void OutlinerParaObject::SetVertical(bool bNew, bool bTopToBottom) { const ::o3tl::cow_wrapper< OutlinerParaObjData >* pImpl = &mpImpl; - if ( ( *pImpl )->mpEditTextObject->IsVertical() != bNew ) + if ( ( *pImpl )->mpEditTextObject->IsVertical() != bNew || + (*pImpl)->mpEditTextObject->IsTopToBottom() != (bNew && bTopToBottom)) { - mpImpl->mpEditTextObject->SetVertical(bNew); + mpImpl->mpEditTextObject->SetVertical(bNew, bTopToBottom); } } -- cgit