editeng/source/items/frmitems.cxx | 17 ++ include/editeng/frmdir.hxx | 5 include/editeng/frmdiritem.hxx | 1 include/xmloff/xmltoken.hxx | 1 offapi/com/sun/star/text/WritingMode2.idl | 7 + schema/libreoffice/OpenDocument-schema-v1.3+libreoffice.rng | 11 + sw/qa/extras/odfexport/data/btlr-cell.odt |binary sw/qa/extras/odfexport/odfexport.cxx | 20 ++ sw/source/core/inc/frame.hxx | 15 +- sw/source/core/inc/frmtool.hxx | 7 - sw/source/core/inc/swfont.hxx | 29 ++-- sw/source/core/layout/calcmove.cxx | 2 sw/source/core/layout/colfrm.cxx | 2 sw/source/core/layout/findfrm.cxx | 1 sw/source/core/layout/newfrm.cxx | 61 ++++++++ sw/source/core/layout/paintfrm.cxx | 26 ++- sw/source/core/layout/ssfrm.cxx | 4 sw/source/core/layout/wsfrm.cxx | 14 +- sw/source/core/text/inftxt.cxx | 23 ++- sw/source/core/text/itratr.cxx | 9 - sw/source/core/text/itratr.hxx | 3 sw/source/core/text/redlnitr.cxx | 16 +- sw/source/core/text/txtfrm.cxx | 15 ++ sw/source/core/txtnode/fntcache.cxx | 25 ++- sw/source/core/txtnode/swfont.cxx | 83 ++++++++---- sw/source/core/unocore/unotbl.cxx | 8 - sw/source/filter/xml/xmlexpit.cxx | 44 +++++- sw/source/filter/xml/xmlimpit.cxx | 31 +++- sw/source/filter/xml/xmlitemm.cxx | 1 xmloff/source/core/xmltoken.cxx | 1 xmloff/source/token/tokens.txt | 1 31 files changed, 374 insertions(+), 109 deletions(-)
New commits: commit 7dce046c8816eb449d6ecf5a40c51519fe037361 Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Wed Feb 13 14:01:57 2019 +0100 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Mon Jul 1 16:58:45 2019 +0200 sw btlr writing mode: implement ODF filter An easy way would be to just extend aXML_WritingDirection_Enum, but then we would write the new attribute value to a non-extension namespace. So special case the new attribute value during both import and export (and only for table cells as a start). Reviewed-on: https://gerrit.libreoffice.org/67770 Reviewed-by: Miklos Vajna <vmik...@collabora.com> Tested-by: Jenkins (cherry picked from commit 8af98ac8bf0ac8795999ecbf061d3c094f7c3be4) Conflicts: sw/source/filter/xml/xmlimpit.cxx Change-Id: I431bf99693c4a3452e91f241bd2f0fcfc72c68fd diff --git a/include/xmloff/xmltoken.hxx b/include/xmloff/xmltoken.hxx index 815d84c599f9..bebbcb7f08ac 100644 --- a/include/xmloff/xmltoken.hxx +++ b/include/xmloff/xmltoken.hxx @@ -2183,6 +2183,7 @@ namespace xmloff { namespace token { XML_RL_TB, XML_TB_LR, + XML_BT_LR, XML_LR, XML_RL, XML_TB, diff --git a/schema/libreoffice/OpenDocument-schema-v1.3+libreoffice.rng b/schema/libreoffice/OpenDocument-schema-v1.3+libreoffice.rng index d59314e99771..956ccc2f02e4 100644 --- a/schema/libreoffice/OpenDocument-schema-v1.3+libreoffice.rng +++ b/schema/libreoffice/OpenDocument-schema-v1.3+libreoffice.rng @@ -2323,6 +2323,17 @@ xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1. </rng:optional> </rng:define> + <!-- TODO no proposal --> + <rng:define name="common-writing-mode-attlist" combine="interleave"> + <rng:optional> + <rng:attribute name="loext:writing-mode"> + <rng:choice> + <rng:value>bt-lr</rng:value> + </rng:choice> + </rng:attribute> + </rng:optional> + </rng:define> + <!-- just a test-case for user-defined attributes, move along, nothing to see here... --> <rng:define name="style-table-cell-properties-attlist" combine="interleave"> <rng:optional> diff --git a/sw/qa/extras/odfexport/data/btlr-cell.odt b/sw/qa/extras/odfexport/data/btlr-cell.odt new file mode 100644 index 000000000000..c010fa9f51b6 Binary files /dev/null and b/sw/qa/extras/odfexport/data/btlr-cell.odt differ diff --git a/sw/qa/extras/odfexport/odfexport.cxx b/sw/qa/extras/odfexport/odfexport.cxx index 7031430efede..a47028c91b73 100644 --- a/sw/qa/extras/odfexport/odfexport.cxx +++ b/sw/qa/extras/odfexport/odfexport.cxx @@ -32,6 +32,7 @@ #include <com/sun/star/document/XEmbeddedObjectSupplier.hpp> #include <com/sun/star/text/XTextEmbeddedObjectsSupplier.hpp> #include <com/sun/star/text/XTextField.hpp> +#include <com/sun/star/text/WritingMode2.hpp> #include <comphelper/storagehelper.hxx> #include <comphelper/fileformat.h> #include <comphelper/propertysequence.hxx> @@ -1391,6 +1392,25 @@ DECLARE_ODFEXPORT_TEST(testWhitespace, "whitespace.odt") CPPUNIT_ASSERT(!xPortions->hasMoreElements()); } +DECLARE_ODFEXPORT_TEST(testBtlrCell, "btlr-cell.odt") +{ + // Without the accompanying fix in place, this test would have failed, as + // the btlr text direction in the A1 cell was lost on ODF import and + // export. + uno::Reference<text::XTextTablesSupplier> xSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference<container::XNameAccess> xTables = xSupplier->getTextTables(); + uno::Reference<text::XTextTable> xTable(xTables->getByName("Table1"), uno::UNO_QUERY); + uno::Reference<beans::XPropertySet> xA1(xTable->getCellByName("A1"), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(text::WritingMode2::BT_LR, getProperty<sal_Int16>(xA1, "WritingMode")); + + uno::Reference<beans::XPropertySet> xB1(xTable->getCellByName("B1"), uno::UNO_QUERY); + auto nActual = getProperty<sal_Int16>(xB1, "WritingMode"); + CPPUNIT_ASSERT(nActual == text::WritingMode2::LR_TB || nActual == text::WritingMode2::CONTEXT); + + uno::Reference<beans::XPropertySet> xC1(xTable->getCellByName("C1"), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(text::WritingMode2::TB_RL, getProperty<sal_Int16>(xC1, "WritingMode")); +} + DECLARE_ODFEXPORT_TEST(testFdo86963, "fdo86963.odt") { // Export of this document failed with beans::UnknownPropertyException. diff --git a/sw/source/filter/xml/xmlexpit.cxx b/sw/source/filter/xml/xmlexpit.cxx index b04d8f085e13..1c0a3a9d609b 100644 --- a/sw/source/filter/xml/xmlexpit.cxx +++ b/sw/source/filter/xml/xmlexpit.cxx @@ -46,6 +46,7 @@ #include <editeng/formatbreakitem.hxx> #include <editeng/keepitem.hxx> #include <editeng/brushitem.hxx> +#include <editeng/frmdiritem.hxx> #include <fmtpdsc.hxx> #include <fmtornt.hxx> #include <fmtfsize.hxx> @@ -202,16 +203,41 @@ void SvXMLExportItemMapper::exportXML( const SvXMLExport& rExport, } else if( 0 == (rEntry.nMemberId & MID_SW_FLAG_ELEMENT_ITEM_EXPORT) ) { - OUString aValue; - if( QueryXMLValue(rItem, aValue, - static_cast< sal_uInt16 >( - rEntry.nMemberId & MID_SW_FLAG_MASK ), - rUnitConverter ) ) + bool bDone = false; + switch (rItem.Which()) { - const OUString sName( - rNamespaceMap.GetQNameByKey( rEntry.nNameSpace, - GetXMLToken(rEntry.eLocalName))); - rAttrList.AddAttribute( sName, aValue ); + case RES_FRAMEDIR: + { + // Write bt-lr to the extension namespace, handle other values + // below. + auto pDirection = static_cast<const SvxFrameDirectionItem*>(&rItem); + if (rEntry.nNameSpace == XML_NAMESPACE_LO_EXT + && pDirection->GetValue() == SvxFrameDirection::Vertical_LR_BT) + { + const OUString sName(rNamespaceMap.GetQNameByKey( + XML_NAMESPACE_LO_EXT, GetXMLToken(XML_WRITING_MODE))); + rAttrList.AddAttribute(sName, GetXMLToken(XML_BT_LR)); + } + if (rEntry.nNameSpace == XML_NAMESPACE_LO_EXT + || pDirection->GetValue() == SvxFrameDirection::Vertical_LR_BT) + bDone = true; + break; + } + } + + if (!bDone) + { + OUString aValue; + if( QueryXMLValue(rItem, aValue, + static_cast< sal_uInt16 >( + rEntry.nMemberId & MID_SW_FLAG_MASK ), + rUnitConverter ) ) + { + const OUString sName( + rNamespaceMap.GetQNameByKey( rEntry.nNameSpace, + GetXMLToken(rEntry.eLocalName))); + rAttrList.AddAttribute( sName, aValue ); + } } } } diff --git a/sw/source/filter/xml/xmlimpit.cxx b/sw/source/filter/xml/xmlimpit.cxx index 184a6e6194f1..9eb42a3b785a 100644 --- a/sw/source/filter/xml/xmlimpit.cxx +++ b/sw/source/filter/xml/xmlimpit.cxx @@ -42,6 +42,7 @@ #include <editeng/formatbreakitem.hxx> #include <editeng/keepitem.hxx> #include <editeng/brushitem.hxx> +#include <editeng/frmdir.hxx> #include <fmtpdsc.hxx> #include <fmtornt.hxx> #include <fmtfsize.hxx> @@ -53,6 +54,7 @@ #include "xmlithlp.hxx" #include <com/sun/star/uno/Any.hxx> #include <osl/diagnose.h> +#include <sal/log.hxx> using ::editeng::SvxBorderLine; using namespace ::com::sun::star; @@ -906,18 +908,29 @@ bool SvXMLImportItemMapper::PutXMLValue( case RES_FRAMEDIR: { - const XMLPropertyHandler* pWritingModeHandler = - XMLPropertyHandlerFactory::CreatePropertyHandler( - XML_TYPE_TEXT_WRITING_MODE_WITH_DEFAULT ); - if( pWritingModeHandler != nullptr ) + if (IsXMLToken(rValue, XML_BT_LR)) { + // Read bt-lr from the extension namespace, handle other values + // below. Any aAny; - bOk = pWritingModeHandler->importXML( rValue, aAny, - rUnitConverter ); - if( bOk ) - bOk = rItem.PutValue( aAny, 0 ); + aAny <<= static_cast<sal_uInt16>(SvxFrameDirection::Vertical_LR_BT); + bOk = rItem.PutValue(aAny, 0); + } + else + { + const XMLPropertyHandler* pWritingModeHandler = + XMLPropertyHandlerFactory::CreatePropertyHandler( + XML_TYPE_TEXT_WRITING_MODE_WITH_DEFAULT ); + if( pWritingModeHandler != nullptr ) + { + Any aAny; + bOk = pWritingModeHandler->importXML( rValue, aAny, + rUnitConverter ); + if( bOk ) + bOk = rItem.PutValue( aAny, 0 ); - delete pWritingModeHandler; + delete pWritingModeHandler; + } } } break; diff --git a/sw/source/filter/xml/xmlitemm.cxx b/sw/source/filter/xml/xmlitemm.cxx index 417e0a5d96c1..0757bdd57604 100644 --- a/sw/source/filter/xml/xmlitemm.cxx +++ b/sw/source/filter/xml/xmlitemm.cxx @@ -282,6 +282,7 @@ SvXMLItemMapEntry const aXMLTableCellItemMap[] = // RES_FRAMEDIR MAP_ENTRY( STYLE, WRITING_MODE, RES_FRAMEDIR, 0 ), + MAP_ENTRY( LO_EXT, WRITING_MODE, RES_FRAMEDIR, 0 ), M_END }; diff --git a/xmloff/source/core/xmltoken.cxx b/xmloff/source/core/xmltoken.cxx index 8a40bdc11fc9..b83298799104 100644 --- a/xmloff/source/core/xmltoken.cxx +++ b/xmloff/source/core/xmltoken.cxx @@ -2186,6 +2186,7 @@ namespace xmloff { namespace token { TOKEN( "rl-tb", XML_RL_TB ), TOKEN( "tb-lr", XML_TB_LR ), + TOKEN( "bt-lr", XML_BT_LR ), TOKEN( "lr", XML_LR ), TOKEN( "rl", XML_RL ), TOKEN( "tb", XML_TB ), diff --git a/xmloff/source/token/tokens.txt b/xmloff/source/token/tokens.txt index c57d2b646ddc..d6d832ea5343 100644 --- a/xmloff/source/token/tokens.txt +++ b/xmloff/source/token/tokens.txt @@ -2088,6 +2088,7 @@ stock-gain-marker stock-range-line rl-tb tb-lr +bt-lr lr rl tb commit abbff658a428aee5105bcb0143c4819eb309e9b8 Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Tue Feb 12 17:50:59 2019 +0100 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Mon Jul 1 16:56:11 2019 +0200 sw btlr writing mode layout: implement unmapping of this direction Fix various cases which trigger this warning: warn:legacy.osl:10975:10975:sw/source/core/txtnode/swfont.cxx:427: Unsupported direction Which means that we tried to work with a VCL direction of 900, without passing around the btlr flag accordingly. Change-Id: I96374fc949f60e8324c5a84de48b710b6461bafb Reviewed-on: https://gerrit.libreoffice.org/67746 Tested-by: Jenkins Reviewed-by: Miklos Vajna <vmik...@collabora.com> (cherry picked from commit cb9f393a5293c0f39d76b703154f8392c45f8047) diff --git a/sw/source/core/inc/frmtool.hxx b/sw/source/core/inc/frmtool.hxx index 3496b6d5eb59..a031d11ea136 100644 --- a/sw/source/core/inc/frmtool.hxx +++ b/sw/source/core/inc/frmtool.hxx @@ -108,12 +108,13 @@ void SwAlignGrfRect( SwRect *pGrfRect, const OutputDevice &rOut ); * @param[in] rFont font object of actual text, which specify the border * @param[in] rPaintArea rectangle area in which line portion takes place * @param[in] bVerticalLayout corresponding text frame verticality + * @param[in] bVerticalLayoutLRBT corresponding text frame verticality (LRBT subset) * @param[in] bJoinWithPrev leave border with which actual border joins to the previous portion * @param[in] bJoinWithNext leave border with which actual border joins to the next portion **/ -void PaintCharacterBorder( - const SwFont& rFont, const SwRect& rPaintArea, const bool bVerticalLayout, - const bool bJoinWithPrev, const bool bJoinWithNext ); +void PaintCharacterBorder(const SwFont& rFont, const SwRect& rPaintArea, const bool bVerticalLayout, + const bool bVerticalLayoutLRBT, const bool bJoinWithPrev, + const bool bJoinWithNext); // get Fly, if no List is given use the current shell // Implementation in feshview.cxx diff --git a/sw/source/core/inc/swfont.hxx b/sw/source/core/inc/swfont.hxx index cc299a1d3fba..2e1369450c89 100644 --- a/sw/source/core/inc/swfont.hxx +++ b/sw/source/core/inc/swfont.hxx @@ -46,7 +46,7 @@ const sal_Unicode CH_TAB = '\t'; // \t const sal_Unicode CH_PAR = 0xB6; // paragraph const sal_Unicode CH_BULLET = 0xB7; // centered dot -sal_uInt16 UnMapDirection( sal_uInt16 nDir, const bool bVertFormat ); +sal_uInt16 UnMapDirection( sal_uInt16 nDir, const bool bVertFormat, const bool bVertFormatLRBT ); class SwSubFont : public SvxFont { @@ -282,7 +282,8 @@ public: FontWeight GetWeight() const { return m_aSub[m_nActual].GetWeight(); } FontEmphasisMark GetEmphasisMark() const { return m_aSub[m_nActual].GetEmphasisMark(); } - sal_uInt16 GetOrientation( const bool bVertLayout = false ) const; + sal_uInt16 GetOrientation(const bool bVertLayout = false, + const bool bVertFormatLRBT = false) const; const OUString& GetName( const SwFontScript nWhich ) const { return m_aSub[nWhich].GetFamilyName(); } @@ -339,10 +340,14 @@ public: const boost::optional<editeng::SvxBorderLine>& GetLeftBorder() const { return m_aLeftBorder; } // Get absolute border correspond to the layout verticality and orientation. - const boost::optional<editeng::SvxBorderLine>& GetAbsTopBorder( const bool bVertLayout ) const; - const boost::optional<editeng::SvxBorderLine>& GetAbsBottomBorder( const bool bVertLayout ) const; - const boost::optional<editeng::SvxBorderLine>& GetAbsRightBorder( const bool bVertLayout ) const; - const boost::optional<editeng::SvxBorderLine>& GetAbsLeftBorder( const bool bVertLayout ) const; + const boost::optional<editeng::SvxBorderLine>& + GetAbsTopBorder(const bool bVertLayout, const bool bVertLayoutLRBT) const; + const boost::optional<editeng::SvxBorderLine>& + GetAbsBottomBorder(const bool bVertLayout, const bool bVertLayoutLRBT) const; + const boost::optional<editeng::SvxBorderLine>& + GetAbsRightBorder(const bool bVertLayout, const bool bVertLayoutLRBT) const; + const boost::optional<editeng::SvxBorderLine>& + GetAbsLeftBorder(const bool bVertLayout, const bool bVertLayoutLRBT) const; void SetTopBorderDist( const sal_uInt16 nTopDist ); void SetBottomBorderDist( const sal_uInt16 nBottomDist ); @@ -376,9 +381,12 @@ public: * * @param[in] bVertLayout true, if the container layout is vertical * false, otherwise + * @param[in] bVertLayoutLRBT true if the container layout is vertical + * (bottom to top, left to right), false otherwise * @return absolute location **/ - SvxShadowLocation GetAbsShadowLocation( const bool bVertLayout ) const; + SvxShadowLocation GetAbsShadowLocation(const bool bVertLayout, + const bool bVertLayoutLRBT) const; /** * Calculate the shadow space on the specified side dependent from @@ -388,12 +396,14 @@ public: * @param[in] nShadow specify the side * @param[in] bVertLayout true, if the container layout is vertical * false, otherwise + * @param[in] bVertLayoutLRBT true if the container layout is vertical + * (bottom to top, left to right), false otherwise * @param[in] bSkipLeft relative left shadow space is skipped * @param[in] bSkipRight relative right shadow space is skipped * @return the shadow space **/ sal_uInt16 CalcShadowSpace( - const SvxShadowItemSide nShadow, const bool bVertLayout, + const SvxShadowItemSide nShadow, const bool bVertLayout, const bool bVertLayoutLRBT, const bool bSkipLeft, const bool bSkipRight ) const; void dumpAsXml( xmlTextWriterPtr writer ) const; diff --git a/sw/source/core/layout/paintfrm.cxx b/sw/source/core/layout/paintfrm.cxx index 1ec4e721b3ea..afbd85ffcea1 100644 --- a/sw/source/core/layout/paintfrm.cxx +++ b/sw/source/core/layout/paintfrm.cxx @@ -4696,6 +4696,7 @@ void PaintCharacterBorder( const SwFont& rFont, const SwRect& rPaintArea, const bool bVerticalLayout, + const bool bVerticalLayoutLRBT, const bool bJoinWithPrev, const bool bJoinWithNext ) { @@ -4707,7 +4708,7 @@ void PaintCharacterBorder( bool bLeft = true; bool bRight = true; - switch( rFont.GetOrientation(bVerticalLayout) ) + switch (rFont.GetOrientation(bVerticalLayout, bVerticalLayoutLRBT)) { case 0 : bLeft = !bJoinWithPrev; @@ -4731,7 +4732,7 @@ void PaintCharacterBorder( { const SvxShadowItem aShadow( 0, &rFont.GetShadowColor(), rFont.GetShadowWidth(), - rFont.GetAbsShadowLocation(bVerticalLayout)); + rFont.GetAbsShadowLocation(bVerticalLayout, bVerticalLayoutLRBT)); if( aShadow.GetLocation() != SvxShadowLocation::NONE ) { @@ -4744,10 +4745,19 @@ void PaintCharacterBorder( basegfx::utils::createScaleTranslateB2DHomMatrix( aAlignedRect.Width(), aAlignedRect.Height(), aAlignedRect.Left(), aAlignedRect.Top())); - const svx::frame::Style aStyleTop(bTop ? rFont.GetAbsTopBorder(bVerticalLayout).get_ptr() : nullptr, 1.0); - const svx::frame::Style aStyleRight(bRight ? rFont.GetAbsRightBorder(bVerticalLayout).get_ptr() : nullptr, 1.0); - const svx::frame::Style aStyleBottom(bBottom ? rFont.GetAbsBottomBorder(bVerticalLayout).get_ptr() : nullptr, 1.0); - const svx::frame::Style aStyleLeft(bLeft ? rFont.GetAbsLeftBorder(bVerticalLayout).get_ptr() : nullptr, 1.0); + const svx::frame::Style aStyleTop( + bTop ? rFont.GetAbsTopBorder(bVerticalLayout, bVerticalLayoutLRBT).get_ptr() : nullptr, + 1.0); + const svx::frame::Style aStyleRight( + bRight ? rFont.GetAbsRightBorder(bVerticalLayout, bVerticalLayoutLRBT).get_ptr() : nullptr, + 1.0); + const svx::frame::Style aStyleBottom( + bBottom ? rFont.GetAbsBottomBorder(bVerticalLayout, bVerticalLayoutLRBT).get_ptr() + : nullptr, + 1.0); + const svx::frame::Style aStyleLeft( + bLeft ? rFont.GetAbsLeftBorder(bVerticalLayout, bVerticalLayoutLRBT).get_ptr() : nullptr, + 1.0); drawinglayer::primitive2d::Primitive2DContainer aBorderLineTarget; aBorderLineTarget.append( diff --git a/sw/source/core/text/inftxt.cxx b/sw/source/core/text/inftxt.cxx index 29ef2035bee7..6714588fed8f 100644 --- a/sw/source/core/text/inftxt.cxx +++ b/sw/source/core/text/inftxt.cxx @@ -778,10 +778,19 @@ void SwTextPaintInfo::CalcRect( const SwLinePortion& rPor, const bool bJoinWithNext = static_cast<const SwTextPortion&>(rPor).GetJoinBorderWithNext(); const bool bIsVert = GetTextFrame()->IsVertical(); - aRect.Top(aRect.Top() + GetFont()->CalcShadowSpace(SvxShadowItemSide::TOP, bIsVert, bJoinWithPrev, bJoinWithNext )); - aRect.Bottom(aRect.Bottom() - GetFont()->CalcShadowSpace(SvxShadowItemSide::BOTTOM, bIsVert, bJoinWithPrev, bJoinWithNext )); - aRect.Left(aRect.Left() + GetFont()->CalcShadowSpace(SvxShadowItemSide::LEFT, bIsVert, bJoinWithPrev, bJoinWithNext )); - aRect.Right(aRect.Right() - GetFont()->CalcShadowSpace(SvxShadowItemSide::RIGHT, bIsVert, bJoinWithPrev, bJoinWithNext )); + const bool bIsVertLRBT = GetTextFrame()->IsVertLRBT(); + aRect.Top(aRect.Top() + + GetFont()->CalcShadowSpace(SvxShadowItemSide::TOP, bIsVert, bIsVertLRBT, + bJoinWithPrev, bJoinWithNext)); + aRect.Bottom(aRect.Bottom() + - GetFont()->CalcShadowSpace(SvxShadowItemSide::BOTTOM, bIsVert, bIsVertLRBT, + bJoinWithPrev, bJoinWithNext)); + aRect.Left(aRect.Left() + + GetFont()->CalcShadowSpace(SvxShadowItemSide::LEFT, bIsVert, bIsVertLRBT, + bJoinWithPrev, bJoinWithNext)); + aRect.Right(aRect.Right() + - GetFont()->CalcShadowSpace(SvxShadowItemSide::RIGHT, bIsVert, bIsVertLRBT, + bJoinWithPrev, bJoinWithNext)); } if ( pRect ) @@ -1263,9 +1272,9 @@ void SwTextPaintInfo::DrawBorder( const SwLinePortion &rPor ) const CalcRect( rPor, &aDrawArea ); if ( aDrawArea.HasArea() ) { - PaintCharacterBorder( - *m_pFnt, aDrawArea, GetTextFrame()->IsVertical(), - rPor.GetJoinBorderWithPrev(), rPor.GetJoinBorderWithNext()); + PaintCharacterBorder(*m_pFnt, aDrawArea, GetTextFrame()->IsVertical(), + GetTextFrame()->IsVertLRBT(), rPor.GetJoinBorderWithPrev(), + rPor.GetJoinBorderWithNext()); } } diff --git a/sw/source/core/txtnode/fntcache.cxx b/sw/source/core/txtnode/fntcache.cxx index 175821ab90ef..9a9ebafcbdaa 100644 --- a/sw/source/core/txtnode/fntcache.cxx +++ b/sw/source/core/txtnode/fntcache.cxx @@ -253,18 +253,20 @@ struct CalcLinePosData vcl::Font& rFont; TextFrameIndex const nCnt; const bool bSwitchH2V; + const bool bSwitchH2VLRBT; const bool bSwitchL2R; long const nHalfSpace; long* const pKernArray; const bool bBidiPor; CalcLinePosData( SwDrawTextInfo& _rInf, vcl::Font& _rFont, - TextFrameIndex const _nCnt, const bool _bSwitchH2V, const bool _bSwitchL2R, + TextFrameIndex const _nCnt, const bool _bSwitchH2V, const bool _bSwitchH2VLRBT, const bool _bSwitchL2R, long _nHalfSpace, long* _pKernArray, const bool _bBidiPor) : rInf( _rInf ), rFont( _rFont ), nCnt( _nCnt ), bSwitchH2V( _bSwitchH2V ), + bSwitchH2VLRBT( _bSwitchH2VLRBT ), bSwitchL2R( _bSwitchL2R ), nHalfSpace( _nHalfSpace ), pKernArray( _pKernArray ), @@ -295,8 +297,9 @@ static void lcl_calcLinePos( const CalcLinePosData &rData, sal_Int32 nKernStart = nStart ? rData.pKernArray[sal_Int32(nStart) - 1] : 0; sal_Int32 nKernEnd = rData.pKernArray[sal_Int32(nEnd) - 1]; - const sal_uInt16 nDir = rData.bBidiPor ? 1800 : - UnMapDirection( rData.rFont.GetOrientation(), rData.bSwitchH2V ); + const sal_uInt16 nDir = rData.bBidiPor ? 1800 + : UnMapDirection(rData.rFont.GetOrientation(), + rData.bSwitchH2V, rData.bSwitchH2VLRBT); switch ( nDir ) { @@ -933,6 +936,7 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf ) // line of the ExtendedAttributeSets will appear in the font color first const bool bSwitchH2V = rInf.GetFrame() && rInf.GetFrame()->IsVertical(); + const bool bSwitchH2VLRBT = rInf.GetFrame() && rInf.GetFrame()->IsVertLRBT(); const bool bSwitchL2R = rInf.GetFrame() && rInf.GetFrame()->IsRightToLeft() && ! rInf.IsIgnoreFrameRTL(); const ComplexTextLayoutFlags nMode = rInf.GetOut().GetLayoutMode(); @@ -1721,11 +1725,10 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf ) Point aEnd; long nKernVal = pKernArray[sal_Int32(rInf.GetLen()) - 1]; - const sal_uInt16 nDir = bBidiPor ? - 1800 : - UnMapDirection( - GetFont().GetOrientation(), - bSwitchH2V ); + const sal_uInt16 nDir = bBidiPor + ? 1800 + : UnMapDirection(GetFont().GetOrientation(), + bSwitchH2V, bSwitchH2VLRBT); switch ( nDir ) { @@ -1775,9 +1778,9 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf ) // anything to do? if (rInf.GetWrong() || rInf.GetGrammarCheck() || rInf.GetSmartTags()) { - CalcLinePosData aCalcLinePosData(rInf, GetFont(), - nCnt, bSwitchH2V, bSwitchL2R, - nHalfSpace, pKernArray.get(), bBidiPor); + CalcLinePosData aCalcLinePosData(rInf, GetFont(), nCnt, bSwitchH2V, + bSwitchH2VLRBT, bSwitchL2R, nHalfSpace, + pKernArray.get(), bBidiPor); SwForbidden aForbidden; // draw line for smart tag data diff --git a/sw/source/core/txtnode/swfont.cxx b/sw/source/core/txtnode/swfont.cxx index a7797412e484..d00a96817a28 100644 --- a/sw/source/core/txtnode/swfont.cxx +++ b/sw/source/core/txtnode/swfont.cxx @@ -126,9 +126,9 @@ void SwFont::SetLeftBorder( const editeng::SvxBorderLine* pLeftBorder ) } const boost::optional<editeng::SvxBorderLine>& -SwFont::GetAbsTopBorder( const bool bVertLayout ) const +SwFont::GetAbsTopBorder(const bool bVertLayout, const bool bVertLayoutLRBT) const { - switch( GetOrientation( bVertLayout ) ) + switch (GetOrientation(bVertLayout, bVertLayoutLRBT)) { case 0 : return m_aTopBorder; @@ -150,9 +150,9 @@ SwFont::GetAbsTopBorder( const bool bVertLayout ) const } const boost::optional<editeng::SvxBorderLine>& -SwFont::GetAbsBottomBorder( const bool bVertLayout ) const +SwFont::GetAbsBottomBorder(const bool bVertLayout, const bool bVertLayoutLRBT) const { - switch( GetOrientation( bVertLayout ) ) + switch (GetOrientation(bVertLayout, bVertLayoutLRBT)) { case 0 : return m_aBottomBorder; @@ -174,9 +174,9 @@ SwFont::GetAbsBottomBorder( const bool bVertLayout ) const } const boost::optional<editeng::SvxBorderLine>& -SwFont::GetAbsLeftBorder( const bool bVertLayout ) const +SwFont::GetAbsLeftBorder(const bool bVertLayout, const bool bVertLayoutLRBT) const { - switch( GetOrientation( bVertLayout ) ) + switch (GetOrientation(bVertLayout, bVertLayoutLRBT)) { case 0 : return m_aLeftBorder; @@ -198,9 +198,9 @@ SwFont::GetAbsLeftBorder( const bool bVertLayout ) const } const boost::optional<editeng::SvxBorderLine>& -SwFont::GetAbsRightBorder( const bool bVertLayout ) const +SwFont::GetAbsRightBorder(const bool bVertLayout, const bool bVertLayoutLRBT) const { - switch( GetOrientation( bVertLayout ) ) + switch (GetOrientation(bVertLayout, bVertLayoutLRBT)) { case 0 : return m_aRightBorder; @@ -221,10 +221,11 @@ SwFont::GetAbsRightBorder( const bool bVertLayout ) const } } -SvxShadowLocation SwFont::GetAbsShadowLocation( const bool bVertLayout ) const +SvxShadowLocation SwFont::GetAbsShadowLocation(const bool bVertLayout, + const bool bVertLayoutLRBT) const { SvxShadowLocation aLocation = SvxShadowLocation::NONE; - switch( GetOrientation( bVertLayout ) ) + switch (GetOrientation(bVertLayout, bVertLayoutLRBT)) { case 0: aLocation = m_aShadowLocation; @@ -303,13 +304,13 @@ SvxShadowLocation SwFont::GetAbsShadowLocation( const bool bVertLayout ) const return aLocation; } -sal_uInt16 SwFont::CalcShadowSpace( - const SvxShadowItemSide nShadow, const bool bVertLayout, - const bool bSkipLeft, const bool bSkipRight ) const +sal_uInt16 SwFont::CalcShadowSpace(const SvxShadowItemSide nShadow, const bool bVertLayout, + const bool bVertLayoutLRBT, const bool bSkipLeft, + const bool bSkipRight) const { sal_uInt16 nSpace = 0; - const sal_uInt16 nOrient = GetOrientation( bVertLayout ); - const SvxShadowLocation aLoc = GetAbsShadowLocation( bVertLayout ); + const sal_uInt16 nOrient = GetOrientation(bVertLayout, bVertLayoutLRBT); + const SvxShadowLocation aLoc = GetAbsShadowLocation(bVertLayout, bVertLayoutLRBT); switch( nShadow ) { case SvxShadowItemSide::TOP: @@ -394,8 +395,22 @@ static sal_uInt16 MapDirection(sal_uInt16 nDir, const bool bVertFormat, const bo // maps the absolute direction set at the font to its logical counterpart // in the rotated environment -sal_uInt16 UnMapDirection( sal_uInt16 nDir, const bool bVertFormat ) +sal_uInt16 UnMapDirection(sal_uInt16 nDir, const bool bVertFormat, const bool bVertFormatLRBT) { + if (bVertFormatLRBT) + { + switch (nDir) + { + case 900: + nDir = 0; + break; + default: + SAL_WARN("sw.core", "unsupported direction for VertLRBT"); + break; + } + return nDir; + } + if ( bVertFormat ) { switch ( nDir ) @@ -419,9 +434,9 @@ sal_uInt16 UnMapDirection( sal_uInt16 nDir, const bool bVertFormat ) return nDir; } -sal_uInt16 SwFont::GetOrientation( const bool bVertFormat ) const +sal_uInt16 SwFont::GetOrientation(const bool bVertFormat, const bool bVertFormatLRBT) const { - return UnMapDirection( m_aSub[m_nActual].GetOrientation(), bVertFormat ); + return UnMapDirection(m_aSub[m_nActual].GetOrientation(), bVertFormat, bVertFormatLRBT); } void SwFont::SetVertical(sal_uInt16 nDir, const bool bVertFormat, const bool bVertLayoutLRBT) @@ -1383,8 +1398,14 @@ void SwSubFont::CalcEsc( SwDrawTextInfo const & rInf, Point& rPos ) { long nOfst; - const sal_uInt16 nDir = UnMapDirection( - GetOrientation(), rInf.GetFrame() && rInf.GetFrame()->IsVertical() ); + bool bVert = false; + bool bVertLRBT = false; + if (rInf.GetFrame()) + { + bVert = rInf.GetFrame()->IsVertical(); + bVertLRBT = rInf.GetFrame()->IsVertLRBT(); + } + const sal_uInt16 nDir = UnMapDirection(GetOrientation(), bVert, bVertLRBT); switch ( GetEscapement() ) { @@ -1454,9 +1475,14 @@ void SwDrawTextInfo::Shift( sal_uInt16 nDir ) const bool bBidiPor = ( GetFrame() && GetFrame()->IsRightToLeft() ) != ( ComplexTextLayoutFlags::Default != ( ComplexTextLayoutFlags::BiDiRtl & GetpOut()->GetLayoutMode() ) ); - nDir = bBidiPor ? - 1800 : - UnMapDirection( nDir, GetFrame() && GetFrame()->IsVertical() ); + bool bVert = false; + bool bVertLRBT = false; + if (GetFrame()) + { + bVert = GetFrame()->IsVertical(); + bVertLRBT = GetFrame()->IsVertLRBT(); + } + nDir = bBidiPor ? 1800 : UnMapDirection(nDir, bVert, bVertLRBT); switch ( nDir ) { commit 0ef51db33170f90062868622f1a0cc5d8b6ebad1 Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Tue Feb 12 16:38:47 2019 +0100 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Mon Jul 1 16:56:03 2019 +0200 sw btlr writing mode: implement initial layout The bulk of this commit is reasonably straightforward, the interesting parts are: - SwFrame::CheckDir() is where the layout reads the doc model, i.e. sets the new SwFrame::mbVertLRBT. - We had 3 text directions previously: horizontal, vertical (implicitly RL) and vertical LR (implicitly TB). This adds a 4th text direction for the LRBT case. - SwTextFrame::SwitchHorizontalToVertical() is responsible for re-locating the origo of a string to be painted from the top left to the bottom left corner (in addition to the height/width swap that's done for all vertical directions). - Finally MapDirection() is the place where we map Writer's new btlr mode (with no character rotation) to VCL's 900 (90 degrees) rotated direction. No functional changes intended for existing text directions. Lots of places are still not yet adapted, but this is good enough to paint a single word in a table cell at the correct position with the correct direction. Change-Id: I465c62db6562d8a2be140c3d37473e590830139e Reviewed-on: https://gerrit.libreoffice.org/67740 Reviewed-by: Miklos Vajna <vmik...@collabora.com> Tested-by: Jenkins (cherry picked from commit e8b9572bf89f55463f2c879a401ed62efc165d95) diff --git a/sw/source/core/inc/frame.hxx b/sw/source/core/inc/frame.hxx index 0a9a1ea823c0..5f9a2cfcf886 100644 --- a/sw/source/core/inc/frame.hxx +++ b/sw/source/core/inc/frame.hxx @@ -404,6 +404,7 @@ protected: bool mbVertical : 1; bool mbVertLR : 1; + bool mbVertLRBT : 1; bool mbValidLineNum : 1; bool mbFixSize : 1; @@ -602,6 +603,7 @@ public: inline bool IsVertical() const; inline bool IsVertLR() const; + inline bool IsVertLRBT() const; void SetDerivedVert( bool bNew ){ mbDerivedVert = bNew; } void SetInvalidVert( bool bNew) { mbInvalidVert = bNew; } @@ -955,6 +957,10 @@ inline bool SwFrame::IsVertLR() const { return mbVertLR; } +inline bool SwFrame::IsVertLRBT() const +{ + return mbVertLRBT; +} inline bool SwFrame::IsRightToLeft() const { if( mbInvalidR2L ) @@ -1312,21 +1318,23 @@ struct SwRectFnCollection typedef SwRectFnCollection* SwRectFn; // This class allows to use proper methods regardless of orientation (LTR/RTL, horizontal or vertical) -extern SwRectFn fnRectHori, fnRectVert, fnRectVertL2R; +extern SwRectFn fnRectHori, fnRectVert, fnRectVertL2R, fnRectVertL2RB2T; class SwRectFnSet { public: explicit SwRectFnSet(const SwFrame *pFrame) : m_bVert(pFrame->IsVertical()) , m_bVertL2R(pFrame->IsVertLR()) + , m_bVertL2RB2T(pFrame->IsVertLRBT()) { - m_fnRect = m_bVert ? (m_bVertL2R ? fnRectVertL2R : fnRectVert) : fnRectHori; + m_fnRect = m_bVert ? (m_bVertL2R ? (m_bVertL2RB2T ? fnRectVertL2RB2T : fnRectVertL2R) : fnRectVert) : fnRectHori; } void Refresh(const SwFrame *pFrame) { m_bVert = pFrame->IsVertical(); m_bVertL2R = pFrame->IsVertLR(); - m_fnRect = m_bVert ? (m_bVertL2R ? fnRectVertL2R : fnRectVert) : fnRectHori; + m_bVertL2RB2T = pFrame->IsVertLRBT(); + m_fnRect = m_bVert ? (m_bVertL2R ? (m_bVertL2RB2T ? fnRectVertL2RB2T : fnRectVertL2R) : fnRectVert) : fnRectHori; } bool IsVert() const { return m_bVert; } @@ -1395,6 +1403,7 @@ public: private: bool m_bVert; bool m_bVertL2R; + bool m_bVertL2RB2T; SwRectFn m_fnRect; }; diff --git a/sw/source/core/inc/swfont.hxx b/sw/source/core/inc/swfont.hxx index ff0e5d8a0b9d..cc299a1d3fba 100644 --- a/sw/source/core/inc/swfont.hxx +++ b/sw/source/core/inc/swfont.hxx @@ -215,7 +215,8 @@ public: void SetOverColor( const Color &rColor ) { m_aOverColor = rColor; } inline void SetStrikeout( const FontStrikeout eStrikeout ); inline void SetOutline( const bool bOutline ); - void SetVertical( sal_uInt16 nDir, const bool bVertLayout = false ); + void SetVertical(sal_uInt16 nDir, const bool bVertLayout = false, + const bool bVertLayoutLRBT = false); inline void SetShadow( const bool bShadow ); inline void SetAutoKern( FontKerning nAutoKern ); inline void SetTransparent( const bool bTrans ); diff --git a/sw/source/core/layout/calcmove.cxx b/sw/source/core/layout/calcmove.cxx index 871f77a2f96e..b670adf668ae 100644 --- a/sw/source/core/layout/calcmove.cxx +++ b/sw/source/core/layout/calcmove.cxx @@ -928,7 +928,7 @@ void SwLayoutFrame::MakeAll(vcl::RenderContext* /*pRenderContext*/) const SwLayNotify aNotify( this ); bool bVert = IsVertical(); - SwRectFn fnRect = ( IsNeighbourFrame() == bVert )? fnRectHori : ( IsVertLR() ? fnRectVertL2R : fnRectVert ); + SwRectFn fnRect = ( IsNeighbourFrame() == bVert )? fnRectHori : ( IsVertLR() ? (IsVertLRBT() ? fnRectVertL2RB2T : fnRectVertL2R) : fnRectVert ); std::unique_ptr<SwBorderAttrAccess> pAccess; const SwBorderAttrs*pAttrs = nullptr; diff --git a/sw/source/core/layout/colfrm.cxx b/sw/source/core/layout/colfrm.cxx index efb776eaaef4..195bbc9535bd 100644 --- a/sw/source/core/layout/colfrm.cxx +++ b/sw/source/core/layout/colfrm.cxx @@ -300,7 +300,7 @@ void SwLayoutFrame::AdjustColumns( const SwFormatCol *pAttr, bool bAdjustAttribu const bool bVert = IsVertical(); - SwRectFn fnRect = bVert ? ( IsVertLR() ? fnRectVertL2R : fnRectVert ) : fnRectHori; + SwRectFn fnRect = bVert ? ( IsVertLR() ? (IsVertLRBT() ? fnRectVertL2RB2T : fnRectVertL2R) : fnRectVert ) : fnRectHori; //If we have a pointer or we have to configure an attribute, we set the //column widths in any case. Otherwise we check if a configuration is needed. diff --git a/sw/source/core/layout/findfrm.cxx b/sw/source/core/layout/findfrm.cxx index 5bdb1de12702..849457f2b3ea 100644 --- a/sw/source/core/layout/findfrm.cxx +++ b/sw/source/core/layout/findfrm.cxx @@ -1476,6 +1476,7 @@ void SwFrame::SetDirFlags( bool bVert ) { mbVertical = pAsk->IsVertical(); mbVertLR = pAsk->IsVertLR(); + mbVertLRBT = pAsk->IsVertLRBT(); if ( !pAsk->mbInvalidVert ) mbInvalidVert = false; diff --git a/sw/source/core/layout/newfrm.cxx b/sw/source/core/layout/newfrm.cxx index adc2909c38a5..0971c2d95a8e 100644 --- a/sw/source/core/layout/newfrm.cxx +++ b/sw/source/core/layout/newfrm.cxx @@ -224,9 +224,70 @@ static SwRectFnCollection aVerticalLeftToRight = { /*.fnSetTopAndHeight =*/&SwRect::SetLeftAndWidth }; +/** + * This is the same as horizontal, but rotated counter-clockwise by 90 degrees. + * This means logical top is physical right, bottom is left, left is top, + * finally right is bottom. + */ +static SwRectFnCollection aVerticalLeftToRightBottomToTop = { + /*.fnGetTop =*/&SwRect::Right_, + /*.fnGetBottom =*/&SwRect::Left_, + /*.fnGetLeft =*/&SwRect::Top_, + /*.fnGetRight =*/&SwRect::Bottom_, + /*.fnGetWidth =*/&SwRect::Height_, + /*.fnGetHeight =*/&SwRect::Width_, + /*.fnGetPos =*/&SwRect::TopRight, + /*.fnGetSize =*/&SwRect::SwappedSize, + + /*.fnSetTop =*/&SwRect::Right_, + /*.fnSetBottom =*/&SwRect::Left_, + /*.fnSetLeft =*/&SwRect::Top_, + /*.fnSetRight =*/&SwRect::Bottom_, + /*.fnSetWidth =*/&SwRect::Height_, + /*.fnSetHeight =*/&SwRect::Width_, + + /*.fnSubTop =*/&SwRect::AddRight, + /*.fnAddBottom =*/&SwRect::SubLeft, + /*.fnSubLeft =*/&SwRect::SubTop, + /*.fnAddRight =*/&SwRect::AddBottom, + /*.fnAddWidth =*/&SwRect::AddHeight, + /*.fnAddHeight =*/&SwRect::AddWidth, + + /*.fnSetPosX =*/&SwRect::SetPosY, + /*.fnSetPosY =*/&SwRect::SetPosX, + + /*.fnGetTopMargin =*/&SwFrame::GetRightMargin, + /*.fnGetBottomMargin =*/&SwFrame::GetLeftMargin, + /*.fnGetLeftMargin =*/&SwFrame::GetTopMargin, + /*.fnGetRightMargin =*/&SwFrame::GetBottomMargin, + /*.fnSetXMargins =*/&SwFrame::SetTopBottomMargins, + /*.fnSetYMargins =*/&SwFrame::SetLeftRightMargins, + /*.fnGetPrtTop =*/&SwFrame::GetPrtRight, + /*.fnGetPrtBottom =*/&SwFrame::GetPrtLeft, + /*.fnGetPrtLeft =*/&SwFrame::GetPrtTop, + /*.fnGetPrtRight =*/&SwFrame::GetPrtBottom, + /*.fnTopDist =*/&SwRect::GetRightDistance, + /*.fnBottomDist =*/&SwRect::GetLeftDistance, + /*.fnLeftDist =*/&SwRect::GetTopDistance, + /*.fnRightDist =*/&SwRect::GetBottomDistance, + /*.fnSetLimit =*/&SwFrame::SetMinLeft, + /*.fnOverStep =*/&SwRect::OverStepLeft, + + /*.fnSetPos =*/&SwRect::SetUpperRightCorner, + /*.fnMakePos =*/&SwFrame::MakeLeftPos, + /*.fnXDiff =*/&FirstMinusSecond, + /*.fnYDiff =*/&FirstMinusSecond, + /*.fnXInc =*/&SwIncrement, + /*.fnYInc =*/&SwIncrement, + + /*.fnSetLeftAndWidth =*/&SwRect::SetTopAndHeight, + /*.fnSetTopAndHeight =*/&SwRect::SetRightAndWidth +}; + SwRectFn fnRectHori = &aHorizontal; SwRectFn fnRectVert = &aVertical; SwRectFn fnRectVertL2R = &aVerticalLeftToRight; +SwRectFn fnRectVertL2RB2T = &aVerticalLeftToRightBottomToTop; // #i65250# sal_uInt32 SwFrameAreaDefinition::mnLastFrameId=0; diff --git a/sw/source/core/layout/paintfrm.cxx b/sw/source/core/layout/paintfrm.cxx index f116678d0b59..1ec4e721b3ea 100644 --- a/sw/source/core/layout/paintfrm.cxx +++ b/sw/source/core/layout/paintfrm.cxx @@ -1256,7 +1256,7 @@ static void lcl_CalcBorderRect( SwRect &rRect, const SwFrame *pFrame, rRect = pFrame->getFramePrintArea(); rRect.Pos() += pFrame->getFrameArea().Pos(); - SwRectFn fnRect = pFrame->IsVertical() ? ( pFrame->IsVertLR() ? fnRectVertL2R : fnRectVert ) : fnRectHori; + SwRectFn fnRect = pFrame->IsVertical() ? ( pFrame->IsVertLR() ? (pFrame->IsVertLRBT() ? fnRectVertL2RB2T : fnRectVertL2R) : fnRectVert ) : fnRectHori; const SvxBoxItem &rBox = rAttrs.GetBox(); const bool bTop = 0 != (pFrame->*fnRect->fnGetTopMargin)(); @@ -5220,7 +5220,7 @@ void SwLayoutFrame::PaintColLines( const SwRect &rRect, const SwFormatCol &rForm if ( !pCol || !pCol->IsColumnFrame() ) return; - SwRectFn fnRect = pCol->IsVertical() ? ( pCol->IsVertLR() ? fnRectVertL2R : fnRectVert ) : fnRectHori; + SwRectFn fnRect = pCol->IsVertical() ? ( pCol->IsVertLR() ? (pCol->IsVertLRBT() ? fnRectVertL2RB2T : fnRectVertL2R) : fnRectVert ) : fnRectHori; SwRect aLineRect = getFramePrintArea(); aLineRect += getFrameArea().Pos(); diff --git a/sw/source/core/layout/ssfrm.cxx b/sw/source/core/layout/ssfrm.cxx index f309693befc2..46cf019acbc4 100644 --- a/sw/source/core/layout/ssfrm.cxx +++ b/sw/source/core/layout/ssfrm.cxx @@ -584,7 +584,7 @@ const SwRect SwFrame::GetPaintArea() const // Cell frames may not leave their upper: SwRect aRect = IsRowFrame() ? GetUpper()->getFrameArea() : getFrameArea(); const bool bVert = IsVertical(); - SwRectFn fnRect = bVert ? ( IsVertLR() ? fnRectVertL2R : fnRectVert ) : fnRectHori; + SwRectFn fnRect = bVert ? ( IsVertLR() ? (IsVertLRBT() ? fnRectVertL2RB2T : fnRectVertL2R) : fnRectVert ) : fnRectHori; long nRight = (aRect.*fnRect->fnGetRight)(); long nLeft = (aRect.*fnRect->fnGetLeft)(); const SwFrame* pTmp = this; @@ -675,7 +675,7 @@ const SwRect SwFrame::GetPaintArea() const const SwRect SwFrame::UnionFrame( bool bBorder ) const { bool bVert = IsVertical(); - SwRectFn fnRect = bVert ? ( IsVertLR() ? fnRectVertL2R : fnRectVert ) : fnRectHori; + SwRectFn fnRect = bVert ? ( IsVertLR() ? (IsVertLRBT() ? fnRectVertL2RB2T : fnRectVertL2R) : fnRectVert ) : fnRectHori; long nLeft = (getFrameArea().*fnRect->fnGetLeft)(); long nWidth = (getFrameArea().*fnRect->fnGetWidth)(); long nPrtLeft = (getFramePrintArea().*fnRect->fnGetLeft)(); diff --git a/sw/source/core/layout/wsfrm.cxx b/sw/source/core/layout/wsfrm.cxx index a5a589bae4a0..c2d1bf5d62ae 100644 --- a/sw/source/core/layout/wsfrm.cxx +++ b/sw/source/core/layout/wsfrm.cxx @@ -300,6 +300,7 @@ SwFrame::SwFrame( SwModify *pMod, SwFrame* pSib ) mbDerivedVert(false), mbVertical(false), mbVertLR(false), + mbVertLRBT(false), mbValidLineNum(false), mbFixSize(false), mbCompletePaint(true), @@ -357,6 +358,11 @@ void SwFrame::CheckDir( SvxFrameDirection nDir, bool bVert, bool bOnlyBiDi, bool mbVertLR = false; else if(SvxFrameDirection::Vertical_LR_TB==nDir) mbVertLR = true; + else if (nDir == SvxFrameDirection::Vertical_LR_BT) + { + mbVertLR = true; + mbVertLRBT = true; + } } } else @@ -712,7 +718,7 @@ Size SwFrame::ChgSize( const Size& aNewSize ) if ( GetUpper() ) { bool bNeighb = IsNeighbourFrame(); - SwRectFn fnRect = IsVertical() == bNeighb ? fnRectHori : ( IsVertLR() ? fnRectVertL2R : fnRectVert ); + SwRectFn fnRect = IsVertical() == bNeighb ? fnRectHori : ( IsVertLR() ? (IsVertLRBT() ? fnRectVertL2RB2T : fnRectVertL2R) : fnRectVert ); SwRect aNew( Point(0,0), aNewSize ); { @@ -1319,9 +1325,9 @@ void SwLayoutFrame::Paste( SwFrame* pParent, SwFrame* pSibling) if ( IsHeaderFrame() || IsFooterFrame() ) fnRect = fnRectHori; else if ( IsCellFrame() || IsColumnFrame() ) - fnRect = GetUpper()->IsVertical() ? fnRectHori : ( GetUpper()->IsVertLR() ? fnRectVertL2R : fnRectVert ); + fnRect = GetUpper()->IsVertical() ? fnRectHori : ( GetUpper()->IsVertLR() ? (GetUpper()->IsVertLRBT() ? fnRectVertL2RB2T : fnRectVertL2R) : fnRectVert ); else - fnRect = GetUpper()->IsVertical() ? ( GetUpper()->IsVertLR() ? fnRectVertL2R : fnRectVert ) : fnRectHori; + fnRect = GetUpper()->IsVertical() ? ( GetUpper()->IsVertLR() ? (GetUpper()->IsVertLRBT() ? fnRectVertL2RB2T : fnRectVertL2R) : fnRectVert ) : fnRectHori; if( (getFrameArea().*fnRect->fnGetWidth)() != (pParent->getFramePrintArea().*fnRect->fnGetWidth)()) InvalidateSize_(); @@ -3364,7 +3370,7 @@ void SwLayoutFrame::Format( vcl::RenderContext* /*pRenderContext*/, const SwBord const sal_uInt16 nLower = bHideWhitespace ? 0 : pAttrs->CalcBottom(); const bool bVert = IsVertical() && !IsPageFrame(); - SwRectFn fnRect = bVert ? ( IsVertLR() ? fnRectVertL2R : fnRectVert ) : fnRectHori; + SwRectFn fnRect = bVert ? ( IsVertLR() ? (IsVertLRBT() ? fnRectVertL2RB2T : fnRectVertL2R) : fnRectVert ) : fnRectHori; if ( !isFramePrintAreaValid() ) { setFramePrintAreaValid(true); diff --git a/sw/source/core/text/itratr.cxx b/sw/source/core/text/itratr.cxx index f964a13f858f..964d42e75eda 100644 --- a/sw/source/core/text/itratr.cxx +++ b/sw/source/core/text/itratr.cxx @@ -205,7 +205,8 @@ bool SwAttrIter::SeekStartAndChgAttrIter( OutputDevice* pOut, const bool bParaFo { assert(m_pMergedPara); m_pTextNode = m_pMergedPara->pFirstNode; - InitFontAndAttrHandler(*m_pMergedPara->pParaPropsNode, *m_pTextNode, m_pMergedPara->mergedText, nullptr); + InitFontAndAttrHandler(*m_pMergedPara->pParaPropsNode, *m_pTextNode, + m_pMergedPara->mergedText, nullptr, nullptr); } // reset font to its original state @@ -339,7 +340,8 @@ bool SwAttrIter::Seek(TextFrameIndex const nNewPos) // items at all; it can only apply a previously effective item. // So do this by recreating the font from scratch. // Apply new para items: - InitFontAndAttrHandler(*m_pMergedPara->pParaPropsNode, *newPos.first, m_pMergedPara->mergedText, nullptr); + InitFontAndAttrHandler(*m_pMergedPara->pParaPropsNode, *newPos.first, + m_pMergedPara->mergedText, nullptr, nullptr); // reset to next m_pTextNode = newPos.first; m_nStartIndex = 0; @@ -361,7 +363,8 @@ bool SwAttrIter::Seek(TextFrameIndex const nNewPos) m_pTextNode = newPos.first; // sw_redlinehide: hope it's okay to use the current text node // here; the AttrHandler shouldn't care about non-char items - InitFontAndAttrHandler(*m_pMergedPara->pParaPropsNode, *m_pTextNode, m_pMergedPara->mergedText, nullptr); + InitFontAndAttrHandler(*m_pMergedPara->pParaPropsNode, *m_pTextNode, + m_pMergedPara->mergedText, nullptr, nullptr); } } if (m_pMergedPara || m_pTextNode->GetpSwpHints()) diff --git a/sw/source/core/text/itratr.hxx b/sw/source/core/text/itratr.hxx index 2dddd1265d8c..dd3a755c7bfd 100644 --- a/sw/source/core/text/itratr.hxx +++ b/sw/source/core/text/itratr.hxx @@ -67,7 +67,8 @@ private: void SetFnt( SwFont* pNew ) { m_pFont = pNew; } void InitFontAndAttrHandler( SwTextNode const& rPropsNode, SwTextNode const& rTextNode, - OUString const& rText, bool const* pbVertLayout); + OUString const& rText, bool const* pbVertLayout, + bool const* pbVertLayoutLRBT); protected: void Chg( SwTextAttr const *pHt ); diff --git a/sw/source/core/text/redlnitr.cxx b/sw/source/core/text/redlnitr.cxx index b2ef40409422..f26f3c67ab42 100644 --- a/sw/source/core/text/redlnitr.cxx +++ b/sw/source/core/text/redlnitr.cxx @@ -305,7 +305,8 @@ void SwAttrIter::InitFontAndAttrHandler( SwTextNode const& rPropsNode, SwTextNode const& rTextNode, OUString const& rText, - bool const*const pbVertLayout) + bool const*const pbVertLayout, + bool const*const pbVertLayoutLRBT) { // Build a font matching the default paragraph style: SwFontAccess aFontAccess( &rPropsNode.GetAnyFormatColl(), m_pViewShell ); @@ -326,7 +327,10 @@ void SwAttrIter::InitFontAndAttrHandler( // if it's a re-init, the vert flag never changes if (pbVertLayout ? *pbVertLayout : m_aAttrHandler.IsVertLayout()) { - m_pFont->SetVertical( m_pFont->GetOrientation(), true ); + bool bVertLayoutLRBT = false; + if (pbVertLayoutLRBT) + bVertLayoutLRBT = *pbVertLayoutLRBT; + m_pFont->SetVertical(m_pFont->GetOrientation(), true, bVertLayoutLRBT); } // Initialize the default attribute of the attribute handler @@ -383,6 +387,7 @@ void SwAttrIter::CtorInitAttrIter(SwTextNode & rTextNode, // set font to vertical if frame layout is vertical bool bVertLayout = false; + bool bVertLayoutLRBT = false; bool bRTL = false; if ( pFrame ) { @@ -390,6 +395,10 @@ void SwAttrIter::CtorInitAttrIter(SwTextNode & rTextNode, { bVertLayout = true; } + if (pFrame->IsVertLRBT()) + { + bVertLayoutLRBT = true; + } bRTL = pFrame->IsRightToLeft(); m_pMergedPara = pFrame->GetMergedPara(); } @@ -403,7 +412,8 @@ void SwAttrIter::CtorInitAttrIter(SwTextNode & rTextNode, m_pMergedPara ? *m_pMergedPara->pParaPropsNode : rTextNode, rTextNode, m_pMergedPara ? m_pMergedPara->mergedText : rTextNode.GetText(), - & bVertLayout); + & bVertLayout, + & bVertLayoutLRBT); m_nStartIndex = m_nEndIndex = m_nPosition = m_nChgCnt = 0; m_nPropFont = 0; diff --git a/sw/source/core/text/txtfrm.cxx b/sw/source/core/text/txtfrm.cxx index e7f221c705e9..f02eed653ba5 100644 --- a/sw/source/core/text/txtfrm.cxx +++ b/sw/source/core/text/txtfrm.cxx @@ -512,6 +512,21 @@ void SwTextFrame::SwitchHorizontalToVertical( SwRect& rRect ) const */ void SwTextFrame::SwitchHorizontalToVertical( Point& rPoint ) const { + if (IsVertLRBT()) + { + // The horizontal origo is the top left corner, the LRBT origo is the + // bottom left corner. Finally x and y has to be swapped. + SAL_WARN_IF(!mbIsSwapped, "sw.core", + "SwTextFrame::SwitchHorizontalToVertical, IsVertLRBT, not swapped"); + Point aPoint(rPoint); + rPoint.setX(getFrameArea().Left() + (aPoint.Y() - getFrameArea().Top())); + // This would be bottom - x delta, but bottom is top + height, finally + // width (and not height), as it's swapped. + rPoint.setY(getFrameArea().Top() + getFrameArea().Width() + - (aPoint.X() - getFrameArea().Left())); + return; + } + // calc offset inside frame const long nOfstX = rPoint.X() - getFrameArea().Left(); const long nOfstY = rPoint.Y() - getFrameArea().Top(); diff --git a/sw/source/core/txtnode/swfont.cxx b/sw/source/core/txtnode/swfont.cxx index 5e8ea0651c38..a7797412e484 100644 --- a/sw/source/core/txtnode/swfont.cxx +++ b/sw/source/core/txtnode/swfont.cxx @@ -364,14 +364,17 @@ sal_uInt16 SwFont::CalcShadowSpace( } // maps directions for vertical layout -static sal_uInt16 MapDirection( sal_uInt16 nDir, const bool bVertFormat ) +static sal_uInt16 MapDirection(sal_uInt16 nDir, const bool bVertFormat, const bool bVertFormatLRBT) { if ( bVertFormat ) { switch ( nDir ) { case 0 : - nDir = 2700; + if (bVertFormatLRBT) + nDir = 900; + else + nDir = 2700; break; case 900 : nDir = 0; @@ -421,10 +424,10 @@ sal_uInt16 SwFont::GetOrientation( const bool bVertFormat ) const return UnMapDirection( m_aSub[m_nActual].GetOrientation(), bVertFormat ); } -void SwFont::SetVertical( sal_uInt16 nDir, const bool bVertFormat ) +void SwFont::SetVertical(sal_uInt16 nDir, const bool bVertFormat, const bool bVertLayoutLRBT) { // map direction if frame has vertical layout - nDir = MapDirection( nDir, bVertFormat ); + nDir = MapDirection(nDir, bVertFormat, bVertLayoutLRBT); if( nDir != m_aSub[SwFontScript::Latin].GetOrientation() ) { commit 5cccc917a1163f924cbc9d109a777803dd270aa9 Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Tue Feb 12 14:36:43 2019 +0100 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Mon Jul 1 16:55:57 2019 +0200 sw btlr writing mode: implement UNO API The custom code in SwXCell::setPropertyValue() was added in commit 5a5597655a4bf12e4ca07c9c2b6f6221e217f080 (tentative fix for fdo#30474#, 2010-11-26), which suggests that not handling all constants from text::WritingMode2 was not intentional. Later the writerfilter side (which is the only client of this hidden property) was adapted to use text::WritingMode2, so do the same here. This implicitly adds support for the new text::WritingMode2::BT_LR as well. Change-Id: I37d8eaa844847cb19e7503b2d973069f9895e6bc Reviewed-on: https://gerrit.libreoffice.org/67730 Reviewed-by: Miklos Vajna <vmik...@collabora.com> Tested-by: Jenkins (cherry picked from commit 052b5d375307245223e694bb835d86966c370d3b) diff --git a/editeng/source/items/frmitems.cxx b/editeng/source/items/frmitems.cxx index cc2950a4b875..57c462d7d122 100644 --- a/editeng/source/items/frmitems.cxx +++ b/editeng/source/items/frmitems.cxx @@ -3867,6 +3867,9 @@ bool SvxFrameDirectionItem::PutValue( const css::uno::Any& rVal, case text::WritingMode2::TB_LR: SetValue( SvxFrameDirection::Vertical_LR_TB ); break; + case text::WritingMode2::BT_LR: + SetValue( SvxFrameDirection::Vertical_LR_BT ); + break; case text::WritingMode2::PAGE: SetValue( SvxFrameDirection::Environment ); break; @@ -3900,6 +3903,9 @@ bool SvxFrameDirectionItem::QueryValue( css::uno::Any& rVal, case SvxFrameDirection::Vertical_LR_TB: nVal = text::WritingMode2::TB_LR; break; + case SvxFrameDirection::Vertical_LR_BT: + nVal = text::WritingMode2::BT_LR; + break; case SvxFrameDirection::Environment: nVal = text::WritingMode2::PAGE; break; diff --git a/sw/source/core/unocore/unotbl.cxx b/sw/source/core/unocore/unotbl.cxx index 44b4282c99a6..986869e29e0d 100644 --- a/sw/source/core/unocore/unotbl.cxx +++ b/sw/source/core/unocore/unotbl.cxx @@ -1020,14 +1020,8 @@ void SwXCell::setPropertyValue(const OUString& rPropertyName, const uno::Any& aV if(rPropertyName == "FRMDirection") { SvxFrameDirection eDir = SvxFrameDirection::Environment; - try - { - const std::array<SvxFrameDirection, 3> vDirs = { SvxFrameDirection::Horizontal_LR_TB, SvxFrameDirection::Horizontal_RL_TB, SvxFrameDirection::Vertical_RL_TB }; - eDir = vDirs.at(aValue.get<sal_Int32>()); - } catch(std::out_of_range &) { - SAL_WARN("sw.uno", "unknown direction code, maybe it's a bitfield"); - } SvxFrameDirectionItem aItem(eDir, RES_FRAMEDIR); + aItem.PutValue(aValue, 0); pBox->GetFrameFormat()->SetFormatAttr(aItem); } else if(rPropertyName == "TableRedlineParams") commit 512dcf886d7cdc067d7c91fa2e38b54eba099732 Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Tue Feb 12 12:04:19 2019 +0100 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Mon Jul 1 16:55:51 2019 +0200 sw btlr wrting mode: implement document model btLr is not a writing mode that would be used by any natural language, the reason it makes sense to support this is that the Word UI makes it easy to rotate text 90 degrees counter-clockwise for Latin (lrtb) text, which then triggers this feature. This is common in the first column of tables to create text that looks like a row header. An import-time workaround to handle <w:textDirection w:val="btLr"/> was added in commit c2d1ab73165d5fa19037e6244b1d634c6c455efc (tentative fix for fdo#30474#, 2010-11-26), but rotating text at a text portion level has various unwanted side effects, just counting my own fixes, I had 7 workarounds on top of that workaround to hide problems where the root cause is this missing writing direction in sw core. This commit just extends the sw core doc model, everything else is to be done in follow-up commits. Change-Id: I89e02cd4b40de78699dbf14885fc128e870de3b8 Reviewed-on: https://gerrit.libreoffice.org/67717 Reviewed-by: Miklos Vajna <vmik...@collabora.com> Tested-by: Jenkins (cherry picked from commit db346dde6179e7414289681d91b153a6ed259d05) diff --git a/editeng/source/items/frmitems.cxx b/editeng/source/items/frmitems.cxx index f21950827dd7..cc2950a4b875 100644 --- a/editeng/source/items/frmitems.cxx +++ b/editeng/source/items/frmitems.cxx @@ -3917,4 +3917,15 @@ bool SvxFrameDirectionItem::QueryValue( css::uno::Any& rVal, return bRet; } +void SvxFrameDirectionItem::dumpAsXml(xmlTextWriterPtr pWriter) const +{ + xmlTextWriterStartElement(pWriter, BAD_CAST("SvxFrameDirectionItem")); + xmlTextWriterWriteAttribute(pWriter, BAD_CAST("m_nWhich"), + BAD_CAST(OString::number(Which()).getStr())); + xmlTextWriterWriteAttribute( + pWriter, BAD_CAST("m_nValue"), + BAD_CAST(OString::number(static_cast<sal_Int16>(GetValue())).getStr())); + xmlTextWriterEndElement(pWriter); +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/editeng/frmdir.hxx b/include/editeng/frmdir.hxx index b0ada2cce30a..f8801cc77020 100644 --- a/include/editeng/frmdir.hxx +++ b/include/editeng/frmdir.hxx @@ -48,7 +48,10 @@ enum class SvxFrameDirection Vertical_LR_TB = css::text::WritingMode2::TB_LR, /** Use the value from the environment, can only be used in frames. */ - Environment = css::text::WritingMode2::CONTEXT + Environment = css::text::WritingMode2::CONTEXT, + + /** Vertical, from bottom to top, from left to right. */ + Vertical_LR_BT = css::text::WritingMode2::BT_LR, }; const char* getFrmDirResId(size_t nIndex); diff --git a/include/editeng/frmdiritem.hxx b/include/editeng/frmdiritem.hxx index 929cbc5b0b3e..1ec32483077d 100644 --- a/include/editeng/frmdiritem.hxx +++ b/include/editeng/frmdiritem.hxx @@ -58,6 +58,7 @@ public: } SvxFrameDirectionItem(SvxFrameDirectionItem const &) = default; // SfxPoolItem copy function dichotomy + void dumpAsXml(struct _xmlTextWriter* pWriter) const override; }; #endif // INCLUDED_EDITENG_FRMDIRITEM_HXX diff --git a/offapi/com/sun/star/text/WritingMode2.idl b/offapi/com/sun/star/text/WritingMode2.idl index 4f1800b06a0d..1edc467e7a0f 100644 --- a/offapi/com/sun/star/text/WritingMode2.idl +++ b/offapi/com/sun/star/text/WritingMode2.idl @@ -76,6 +76,13 @@ published constants WritingMode2 /** obtain actual writing mode from the context of the object. */ const short CONTEXT = 4; + + /** text within a line is written bottom-to-top. Lines and blocks are + placed left-to-right. + + @since LibreOffice 6.3 + */ + const short BT_LR = 5; }; _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits