sw/inc/crsrsh.hxx | 3 sw/inc/swrect.hxx | 3 sw/qa/extras/layout/data/btlr-cell.odt |binary sw/qa/extras/layout/layout.cxx | 105 +++++++++++++++ sw/qa/extras/ooxmlexport/ooxmlexport8.cxx | 12 - sw/source/core/crsr/crsrsh.cxx | 3 sw/source/core/docnode/node.cxx | 4 sw/source/core/layout/newfrm.cxx | 4 sw/source/core/layout/ssfrm.cxx | 9 - sw/source/core/layout/trvlfrm.cxx | 15 +- sw/source/core/text/inftxt.cxx | 2 sw/source/core/text/txtfrm.cxx | 45 +++++- sw/source/filter/ww8/docxattributeoutput.cxx | 25 --- sw/source/uibase/docvw/edtwin.cxx | 28 +++- sw/source/uibase/inc/edtwin.hxx | 5 writerfilter/source/dmapper/DomainMapperTableManager.cxx | 15 -- 16 files changed, 203 insertions(+), 75 deletions(-)
New commits: commit e66492a7ee1e178c9ba1e30392cd49048743c581 Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Thu Mar 21 21:05:44 2019 +0100 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Wed Jul 3 10:54:33 2019 +0200 tdf#123943 sw btlr writing mode render: fix text portion background The text frame is swapped in this case, so handle BTLR similar to the normal vert (TBRL) case and the background will be positioned correctly behind the text portion. Change-Id: I2399131ef74ea8849577a467ad9bb02d980d8609 Reviewed-on: https://gerrit.libreoffice.org/69539 Tested-by: Jenkins Reviewed-by: Miklos Vajna <vmik...@collabora.com> (cherry picked from commit 4c5d0e4822dcd0c6c9397a45e3afb66d53ebaafc) diff --git a/sw/qa/extras/layout/data/btlr-cell.odt b/sw/qa/extras/layout/data/btlr-cell.odt index 17a9c19eef25..a4439218b057 100644 Binary files a/sw/qa/extras/layout/data/btlr-cell.odt and b/sw/qa/extras/layout/data/btlr-cell.odt differ diff --git a/sw/qa/extras/layout/layout.cxx b/sw/qa/extras/layout/layout.cxx index 273f13a91e4c..39984fb26031 100644 --- a/sw/qa/extras/layout/layout.cxx +++ b/sw/qa/extras/layout/layout.cxx @@ -2767,6 +2767,11 @@ void SwLayoutWriter::testBtlrCell() assertXPath(pXmlDoc, "//textarray[1]", "x", "1915"); assertXPath(pXmlDoc, "//textarray[1]", "y", "2707"); + // Without the accompanying fix in place, this test would have failed with 'Expected: 1979; + // Actual : 2129', i.e. the gray background of the "AAA2." text was too close to the right edge + // of the text portion. Now it's exactly behind the text portion. + assertXPath(pXmlDoc, "//rect[@top='2159']", "left", "1979"); + // Without the accompanying fix in place, this test would have failed with 'Expected: 269; // Actual : 0', i.e. the AAA2 frame was not visible due to 0 width. pXmlDoc = parseLayoutDump(); diff --git a/sw/source/core/text/inftxt.cxx b/sw/source/core/text/inftxt.cxx index 6714588fed8f..f2c4a3f2bcf4 100644 --- a/sw/source/core/text/inftxt.cxx +++ b/sw/source/core/text/inftxt.cxx @@ -749,7 +749,7 @@ void SwTextPaintInfo::CalcRect( const SwLinePortion& rPor, else { aPoint.setX( X() ); - if ( GetTextFrame()->IsVertLR() ) + if (GetTextFrame()->IsVertLR() && !GetTextFrame()->IsVertLRBT()) aPoint.setY( Y() - rPor.Height() + rPor.GetAscent() ); else aPoint.setY( Y() - rPor.GetAscent() ); commit 8c448e3713e6f6633fa96d94194634aa23f6da1c Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Wed Mar 13 21:35:42 2019 +0100 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Wed Jul 3 10:42:45 2019 +0200 sw btlr writing mode shell: fix cursor selection All changes are about not assuming logical top is a lower y value than logical bottom, by going via the SwRectFnSet abstraction, which already does the right thing. Change-Id: I94a9881b018ad14b02e97425f60af01aa3fd9269 Reviewed-on: https://gerrit.libreoffice.org/69226 Tested-by: Jenkins Reviewed-by: Miklos Vajna <vmik...@collabora.com> (cherry picked from commit 2f83055cdbd915d5036a7b4374b4ad10e6efc65f) diff --git a/sw/inc/swrect.hxx b/sw/inc/swrect.hxx index c4b1889ae4ae..a09b38e81a8c 100644 --- a/sw/inc/swrect.hxx +++ b/sw/inc/swrect.hxx @@ -23,6 +23,7 @@ #include <sal/log.hxx> #include <tools/gen.hxx> +#include "swdllapi.h" class SvStream; @@ -30,7 +31,7 @@ class SvStream; /// This is half-open so m_Point.X() + m_Size.getWidth() is *not* included. /// Note the tools Rectangle is (usually? sometimes?) closed so there's a /// SVRect() to subtract 1 for the conversion. -class SAL_WARN_UNUSED SwRect +class SAL_WARN_UNUSED SW_DLLPUBLIC SwRect { Point m_Point; Size m_Size; diff --git a/sw/qa/extras/layout/layout.cxx b/sw/qa/extras/layout/layout.cxx index 1b43ad464444..273f13a91e4c 100644 --- a/sw/qa/extras/layout/layout.cxx +++ b/sw/qa/extras/layout/layout.cxx @@ -2844,6 +2844,30 @@ void SwLayoutWriter::testBtlrCell() // Without the accompanying fix in place, this test would have failed: character position was 5, // i.e. cursor was at the end of the paragraph. CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), aPosition.nContent.GetIndex()); + + // Test that the selection rectangles are inside the cell frame if we select all the cell + // content. + SwTwips nCellLeft + = getXPath(pXmlDoc, "/root/page/body/tab/row/cell[1]/infos/bounds", "left").toInt32(); + SwTwips nCellWidth + = getXPath(pXmlDoc, "/root/page/body/tab/row/cell[1]/infos/bounds", "width").toInt32(); + SwTwips nCellTop + = getXPath(pXmlDoc, "/root/page/body/tab/row/cell[1]/infos/bounds", "top").toInt32(); + SwTwips nCellHeight + = getXPath(pXmlDoc, "/root/page/body/tab/row/cell[1]/infos/bounds", "height").toInt32(); + SwRect aCellRect(Point(nCellLeft, nCellTop), Size(nCellWidth, nCellHeight)); + pWrtShell->SelAll(); + SwShellCursor* pShellCursor = pWrtShell->getShellCursor(/*bBlock=*/false); + CPPUNIT_ASSERT(!pShellCursor->empty()); + // Without the accompanying fix in place, this test would have failed with: + // selection rectangle 269x2573@(1970,2172) is not inside cell rectangle 3207x1134@(1593,1701) + // i.e. the selection went past the bottom border of the cell frame. + for (const auto& rRect : *pShellCursor) + { + std::stringstream ss; + ss << "selection rectangle " << rRect << " is not inside cell rectangle " << aCellRect; + CPPUNIT_ASSERT_MESSAGE(ss.str(), aCellRect.IsInside(rRect)); + } #endif } diff --git a/sw/source/core/layout/ssfrm.cxx b/sw/source/core/layout/ssfrm.cxx index 46cf019acbc4..e1c8ec770646 100644 --- a/sw/source/core/layout/ssfrm.cxx +++ b/sw/source/core/layout/ssfrm.cxx @@ -680,14 +680,15 @@ const SwRect SwFrame::UnionFrame( bool bBorder ) const long nWidth = (getFrameArea().*fnRect->fnGetWidth)(); long nPrtLeft = (getFramePrintArea().*fnRect->fnGetLeft)(); long nPrtWidth = (getFramePrintArea().*fnRect->fnGetWidth)(); - if( nPrtLeft + nPrtWidth > nWidth ) + SwRectFnSet aRectFnSet(this); + if (aRectFnSet.XInc(nPrtLeft, nPrtWidth) > nWidth) nWidth = nPrtLeft + nPrtWidth; if( nPrtLeft < 0 ) { nLeft += nPrtLeft; nWidth -= nPrtLeft; } - SwTwips nRight = nLeft + nWidth; + SwTwips nRight = aRectFnSet.XInc(nLeft, nWidth); long nAdd = 0; if( bBorder ) { @@ -715,9 +716,9 @@ const SwRect SwFrame::UnionFrame( bool bBorder ) const if( nTmp > nAdd ) nAdd = nTmp; } - nWidth = nRight + nAdd - nLeft; + nWidth = aRectFnSet.XDiff(aRectFnSet.XInc(nRight, nAdd), nLeft); SwRect aRet( getFrameArea() ); - (aRet.*fnRect->fnSetPosX)( nLeft ); + (aRet.*fnRect->fnSetLeft)(nLeft); (aRet.*fnRect->fnSetWidth)( nWidth ); return aRet; } diff --git a/sw/source/core/layout/trvlfrm.cxx b/sw/source/core/layout/trvlfrm.cxx index c511253b6bb1..f564f040552e 100644 --- a/sw/source/core/layout/trvlfrm.cxx +++ b/sw/source/core/layout/trvlfrm.cxx @@ -2139,6 +2139,7 @@ void SwRootFrame::CalcFrameRects(SwShellCursor &rCursor) SwRectFnSet aRectFnSet(pStartFrame); const bool bR2L = pStartFrame->IsRightToLeft(); const bool bEndR2L = pEndFrame->IsRightToLeft(); + const bool bB2T = pStartFrame->IsVertLRBT(); // If there's no doubleline portion involved or start and end are both // in the same doubleline portion, all works fine, but otherwise @@ -2371,7 +2372,7 @@ void SwRootFrame::CalcFrameRects(SwShellCursor &rCursor) { Point aTmpSt( aStRect.Pos() ); Point aTmpEnd( aEndRect.Right(), aEndRect.Bottom() ); - if( bSameRotatedOrBidi || bR2L ) + if (bSameRotatedOrBidi || bR2L || bB2T) { if( aTmpSt.Y() > aTmpEnd.Y() ) { commit 1f5830deb273e3d8e5c554e5f04a07b7c8cfa199 Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Thu Mar 7 21:39:14 2019 +0100 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Wed Jul 3 10:42:19 2019 +0200 sw btlr writing mode shell: left/right cursor travelling, fix vert pos By implementing BTLR support in SwTextFrame::SwitchVerticalToHorizontal() (Point version). Cursor traveling now looks good: all of up/down/left/right direction have the correct paragraph and character position for all the lrtb, tbrl and btlr cases. As a side effect this also fixes mouse click, where clicking above the paragraph positioned the cursor at the bottom of the paragraph. Explicitly add a test for the mouse case as well, given that I initially planned to fix the keyboard part directly in SwCursor::UpDown(), where the keyboard test would pass, but not the mouse one. Change-Id: Iabeded3f03a64416cfcaf58e0438c4a1a793e662 Reviewed-on: https://gerrit.libreoffice.org/68886 Tested-by: Jenkins Reviewed-by: Miklos Vajna <vmik...@collabora.com> (cherry picked from commit 404bfc6f78549d16de193794960a9c9ab7604511) diff --git a/sw/qa/extras/layout/layout.cxx b/sw/qa/extras/layout/layout.cxx index 9ffc60de0b10..1b43ad464444 100644 --- a/sw/qa/extras/layout/layout.cxx +++ b/sw/qa/extras/layout/layout.cxx @@ -2792,6 +2792,9 @@ void SwLayoutWriter::testBtlrCell() CPPUNIT_ASSERT_GREATER(nFirstParaMiddle, rCharRect.Top()); CPPUNIT_ASSERT_LESS(nFirstParaBottom, rCharRect.Top()); + // Save initial cursor position. + SwPosition aCellStart = *pWrtShell->GetCursor()->Start(); + // Test that pressing "up" at the start of the cell goes to the next character position. sal_uLong nNodeIndex = pWrtShell->GetCursor()->Start()->nNode.GetIndex(); sal_Int32 nIndex = pWrtShell->GetCursor()->Start()->nContent.GetIndex(); @@ -2804,12 +2807,43 @@ void SwLayoutWriter::testBtlrCell() CPPUNIT_ASSERT_EQUAL(nIndex + 1, pWrtShell->GetCursor()->Start()->nContent.GetIndex()); // Test that pressing "right" goes to the next paragraph (logical "down"). + sal_Int32 nContentIndex = pWrtShell->GetCursor()->Start()->nContent.GetIndex(); aKeyEvent = KeyEvent(0, KEY_RIGHT); rEditWin.KeyInput(aKeyEvent); Scheduler::ProcessEventsToIdle(); // Without the accompanying fix in place, this test would have failed: the cursor went to the // paragraph after the table. CPPUNIT_ASSERT_EQUAL(nNodeIndex + 1, pWrtShell->GetCursor()->Start()->nNode.GetIndex()); + + // Test that we have the correct character index after traveling to the next paragraph. + // Without the accompanying fix in place, this test would have failed: char position was 5, i.e. + // the cursor jumped to the end of the paragraph for no reason. + CPPUNIT_ASSERT_EQUAL(nContentIndex, pWrtShell->GetCursor()->Start()->nContent.GetIndex()); + + // Test that clicking "below" the second paragraph positions the cursor at the start of the + // second paragraph. + SwRootFrame* pLayout = pDoc->getIDocumentLayoutAccess().GetCurrentLayout(); + SwPosition aPosition(aCellStart); + SwTwips nSecondParaLeft + = getXPath(pXmlDoc, "/root/page/body/tab/row/cell[1]/txt[2]/infos/bounds", "left") + .toInt32(); + SwTwips nSecondParaWidth + = getXPath(pXmlDoc, "/root/page/body/tab/row/cell[1]/txt[2]/infos/bounds", "width") + .toInt32(); + SwTwips nSecondParaTop + = getXPath(pXmlDoc, "/root/page/body/tab/row/cell[1]/txt[2]/infos/bounds", "top").toInt32(); + SwTwips nSecondParaHeight + = getXPath(pXmlDoc, "/root/page/body/tab/row/cell[1]/txt[2]/infos/bounds", "height") + .toInt32(); + Point aPoint; + aPoint.setX(nSecondParaLeft + nSecondParaWidth / 2); + aPoint.setY(nSecondParaTop + nSecondParaHeight - 100); + SwCursorMoveState aState(MV_NONE); + pLayout->GetCursorOfst(&aPosition, aPoint, &aState); + CPPUNIT_ASSERT_EQUAL(aCellStart.nNode.GetIndex() + 1, aPosition.nNode.GetIndex()); + // Without the accompanying fix in place, this test would have failed: character position was 5, + // i.e. cursor was at the end of the paragraph. + CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), aPosition.nContent.GetIndex()); #endif } diff --git a/sw/source/core/text/txtfrm.cxx b/sw/source/core/text/txtfrm.cxx index 430a9804877a..847d49a0bc1c 100644 --- a/sw/source/core/text/txtfrm.cxx +++ b/sw/source/core/text/txtfrm.cxx @@ -617,16 +617,29 @@ void SwTextFrame::SwitchVerticalToHorizontal( Point& rPoint ) const // calc offset inside frame if ( IsVertLR() ) + // X offset is Y - left. nOfstX = rPoint.X() - getFrameArea().Left(); else { + // X offset is right - X. if ( mbIsSwapped ) nOfstX = getFrameArea().Left() + getFrameArea().Height() - rPoint.X(); else nOfstX = getFrameArea().Left() + getFrameArea().Width() - rPoint.X(); } - const long nOfstY = rPoint.Y() - getFrameArea().Top(); + long nOfstY; + if (IsVertLRBT()) + { + // Y offset is bottom - Y. + if (mbIsSwapped) + nOfstY = getFrameArea().Top() + getFrameArea().Width() - rPoint.Y(); + else + nOfstY = getFrameArea().Top() + getFrameArea().Height() - rPoint.Y(); + } + else + // Y offset is Y - top. + nOfstY = rPoint.Y() - getFrameArea().Top(); // calc rotated coords rPoint.setX( getFrameArea().Left() + nOfstY ); commit a05baff73b8bbce136cf012cbdf7c7fd9dc9e715 Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Wed Feb 27 21:31:06 2019 +0100 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Wed Jul 3 10:41:02 2019 +0200 sw btlr writing mode shell: left/right cursor travelling, fix dest para Fix aVerticalLeftToRightBottomToTop: - fnXDiff takes "logically larger, logically smaller" arguments, so it's first - second for top to bottom text (existing directions) but it's second - first for btlr - fnXInc was effectively unused before, but it probably meant to provide logical left + width, so set that to physical left - width for btlr And then port 3 places in lcl_UpDown() to use aRectFnSet, so we get correct behavior for both ttb and btt directions. With this, pressing the left/right arrow jumps to the previous / next paragraph correctly. Change-Id: I1323e95e2ce0ab2d66a3ea6e02bd50df2cebf232 Reviewed-on: https://gerrit.libreoffice.org/68462 Tested-by: Jenkins Reviewed-by: Miklos Vajna <vmik...@collabora.com> (cherry picked from commit 8ae5a98852c2f3d87d6efff598f0c7d54df835d3) diff --git a/sw/qa/extras/layout/layout.cxx b/sw/qa/extras/layout/layout.cxx index 21fd97a8dfa1..9ffc60de0b10 100644 --- a/sw/qa/extras/layout/layout.cxx +++ b/sw/qa/extras/layout/layout.cxx @@ -2793,6 +2793,7 @@ void SwLayoutWriter::testBtlrCell() CPPUNIT_ASSERT_LESS(nFirstParaBottom, rCharRect.Top()); // Test that pressing "up" at the start of the cell goes to the next character position. + sal_uLong nNodeIndex = pWrtShell->GetCursor()->Start()->nNode.GetIndex(); sal_Int32 nIndex = pWrtShell->GetCursor()->Start()->nContent.GetIndex(); KeyEvent aKeyEvent(0, KEY_UP); SwEditWin& rEditWin = pShell->GetView()->GetEditWin(); @@ -2801,6 +2802,14 @@ void SwLayoutWriter::testBtlrCell() // Without the accompanying fix in place, this test would have failed: "up" was interpreted as // logical "left", which does nothing if you're at the start of the text anyway. CPPUNIT_ASSERT_EQUAL(nIndex + 1, pWrtShell->GetCursor()->Start()->nContent.GetIndex()); + + // Test that pressing "right" goes to the next paragraph (logical "down"). + aKeyEvent = KeyEvent(0, KEY_RIGHT); + rEditWin.KeyInput(aKeyEvent); + Scheduler::ProcessEventsToIdle(); + // Without the accompanying fix in place, this test would have failed: the cursor went to the + // paragraph after the table. + CPPUNIT_ASSERT_EQUAL(nNodeIndex + 1, pWrtShell->GetCursor()->Start()->nNode.GetIndex()); #endif } diff --git a/sw/source/core/layout/newfrm.cxx b/sw/source/core/layout/newfrm.cxx index 94e016434e47..bfaf62657091 100644 --- a/sw/source/core/layout/newfrm.cxx +++ b/sw/source/core/layout/newfrm.cxx @@ -275,9 +275,9 @@ static SwRectFnCollection aVerticalLeftToRightBottomToTop = { /*.fnSetPos =*/&SwRect::SetLowerLeftCorner, /*.fnMakePos =*/&SwFrame::MakeRightPos, - /*.fnXDiff =*/&FirstMinusSecond, + /*.fnXDiff =*/&SecondMinusFirst, /*.fnYDiff =*/&FirstMinusSecond, - /*.fnXInc =*/&SwIncrement, + /*.fnXInc =*/&SwDecrement, /*.fnYInc =*/&SwIncrement, /*.fnSetLeftAndWidth =*/&SwRect::SetBottomAndHeight, diff --git a/sw/source/core/layout/trvlfrm.cxx b/sw/source/core/layout/trvlfrm.cxx index 584b74c5f98e..c511253b6bb1 100644 --- a/sw/source/core/layout/trvlfrm.cxx +++ b/sw/source/core/layout/trvlfrm.cxx @@ -757,8 +757,8 @@ static bool lcl_UpDown( SwPaM *pPam, const SwContentFrame *pStart, while ( pCell && !pCell->IsCellFrame() ) pCell = pCell->GetUpper(); OSL_ENSURE( pCell, "could not find the cell" ); - nX = aRectFnSet.GetLeft(pCell->getFrameArea()) + - aRectFnSet.GetWidth(pCell->getFrameArea()) / 2; + nX = aRectFnSet.XInc(aRectFnSet.GetLeft(pCell->getFrameArea()), + aRectFnSet.GetWidth(pCell->getFrameArea()) / 2); //The flow leads from one table to the next. The X-value needs to be //corrected based on the middle of the starting cell by the amount @@ -778,14 +778,14 @@ static bool lcl_UpDown( SwPaM *pPam, const SwContentFrame *pStart, const long nPrtLeft = bRTL ? aRectFnSet.GetPrtRight(*pTable) : aRectFnSet.GetPrtLeft(*pTable); - if ( bRTL != (nX < nPrtLeft) ) + if (bRTL != (aRectFnSet.XDiff(nPrtLeft, nX) > 0)) nX = nPrtLeft; else { const long nPrtRight = bRTL ? aRectFnSet.GetPrtLeft(*pTable) : aRectFnSet.GetPrtRight(*pTable); - if ( bRTL != (nX > nPrtRight) ) + if (bRTL != (aRectFnSet.XDiff(nX, nPrtRight) > 0)) nX = nPrtRight; } } @@ -884,7 +884,7 @@ static bool lcl_UpDown( SwPaM *pPam, const SwContentFrame *pStart, if ( aRectFnSet.IsVert() ) { if ( nTmpTop ) - --nTmpTop; + nTmpTop = aRectFnSet.XInc(nTmpTop, -1); aInsideCell = Point( nTmpTop, nX ); } @@ -896,7 +896,7 @@ static bool lcl_UpDown( SwPaM *pPam, const SwContentFrame *pStart, if ( aRectFnSet.IsVert() ) { if ( nTmpTop ) - --nTmpTop; + nTmpTop = aRectFnSet.XInc(nTmpTop, -1); aInsideCnt = Point( nTmpTop, nX ); } commit 2b224c441dba93934a9f4f81aa6f8faf378b5bbd Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Thu Feb 21 21:22:15 2019 +0100 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Wed Jul 3 10:34:27 2019 +0200 sw btlr writing mode shell: fix up/down cursor travelling By teaching SwEditWin::KeyInput() about 2 vertical modes: the existing tbrl one and the new btlr one. Up now correctly goes to the next character and down to the previous one. Change-Id: I71faebe62e5fa3892b37e8bea6c15d1fb84df5d1 Reviewed-on: https://gerrit.libreoffice.org/68183 Reviewed-by: Miklos Vajna <vmik...@collabora.com> Tested-by: Jenkins (cherry picked from commit 31f896bb6ef922cf4250c6b971fb9d24a60592b5) diff --git a/sw/inc/crsrsh.hxx b/sw/inc/crsrsh.hxx index c76be980179d..b258d6d4af14 100644 --- a/sw/inc/crsrsh.hxx +++ b/sw/inc/crsrsh.hxx @@ -258,8 +258,6 @@ private: SAL_DLLPRIVATE bool LRMargin( bool, bool bAPI = false ); SAL_DLLPRIVATE bool IsAtLRMargin( bool, bool bAPI = false ) const; - SAL_DLLPRIVATE SvxFrameDirection GetTextDirection( const Point* pPt = nullptr ) const; - SAL_DLLPRIVATE bool isInHiddenTextFrame(SwShellCursor* pShellCursor); SAL_DLLPRIVATE bool GoStartWordImpl(); @@ -811,6 +809,7 @@ public: const SwRangeRedline* SelPrevRedline(); const SwRangeRedline* GotoRedline( SwRedlineTable::size_type nArrPos, bool bSelect ); + SAL_DLLPRIVATE SvxFrameDirection GetTextDirection( const Point* pPt = nullptr ) const; // is cursor or the point in/over a vertical formatted text? bool IsInVerticalText( const Point* pPt = nullptr ) const; // is cursor or the point in/over a right to left formatted text? diff --git a/sw/qa/extras/layout/layout.cxx b/sw/qa/extras/layout/layout.cxx index f59d867b0c38..21fd97a8dfa1 100644 --- a/sw/qa/extras/layout/layout.cxx +++ b/sw/qa/extras/layout/layout.cxx @@ -15,10 +15,13 @@ #include <officecfg/Office/Common.hxx> #include <comphelper/scopeguard.hxx> #include <unotools/syslocaleoptions.hxx> +#include <vcl/scheduler.hxx> #include <fmtanchr.hxx> #include <fmtfsize.hxx> #include <fmtcntnt.hxx> #include <wrtsh.hxx> +#include <edtwin.hxx> +#include <view.hxx> static char const DATA_DIRECTORY[] = "/sw/qa/extras/layout/data/"; @@ -2788,6 +2791,16 @@ void SwLayoutWriter::testBtlrCell() // range was 2273 -> 2835, the good vertical position is 2730, the bad one was 1830. CPPUNIT_ASSERT_GREATER(nFirstParaMiddle, rCharRect.Top()); CPPUNIT_ASSERT_LESS(nFirstParaBottom, rCharRect.Top()); + + // Test that pressing "up" at the start of the cell goes to the next character position. + sal_Int32 nIndex = pWrtShell->GetCursor()->Start()->nContent.GetIndex(); + KeyEvent aKeyEvent(0, KEY_UP); + SwEditWin& rEditWin = pShell->GetView()->GetEditWin(); + rEditWin.KeyInput(aKeyEvent); + Scheduler::ProcessEventsToIdle(); + // Without the accompanying fix in place, this test would have failed: "up" was interpreted as + // logical "left", which does nothing if you're at the start of the text anyway. + CPPUNIT_ASSERT_EQUAL(nIndex + 1, pWrtShell->GetCursor()->Start()->nContent.GetIndex()); #endif } diff --git a/sw/source/core/crsr/crsrsh.cxx b/sw/source/core/crsr/crsrsh.cxx index 696eb41c73c8..c655f9e85a34 100644 --- a/sw/source/core/crsr/crsrsh.cxx +++ b/sw/source/core/crsr/crsrsh.cxx @@ -3276,7 +3276,8 @@ SvxFrameDirection SwCursorShell::GetTextDirection( const Point* pPt ) const bool SwCursorShell::IsInVerticalText( const Point* pPt ) const { const SvxFrameDirection nDir = GetTextDirection( pPt ); - return SvxFrameDirection::Vertical_RL_TB == nDir || SvxFrameDirection::Vertical_LR_TB == nDir; + return SvxFrameDirection::Vertical_RL_TB == nDir || SvxFrameDirection::Vertical_LR_TB == nDir + || nDir == SvxFrameDirection::Vertical_LR_BT; } bool SwCursorShell::IsInRightToLeftText() const diff --git a/sw/source/core/docnode/node.cxx b/sw/source/core/docnode/node.cxx index 19cafd55a313..b0027fdd288e 100644 --- a/sw/source/core/docnode/node.cxx +++ b/sw/source/core/docnode/node.cxx @@ -1993,7 +1993,9 @@ SvxFrameDirection SwContentNode::GetTextDirection( const SwPosition& rPos, { if ( pFrame->IsVertical() ) { - if ( pFrame->IsRightToLeft() ) + if (pFrame->IsVertLRBT()) + nRet = SvxFrameDirection::Vertical_LR_BT; + else if (pFrame->IsRightToLeft()) nRet = SvxFrameDirection::Vertical_LR_TB; else nRet = SvxFrameDirection::Vertical_RL_TB; diff --git a/sw/source/uibase/docvw/edtwin.cxx b/sw/source/uibase/docvw/edtwin.cxx index cb6b59b8736d..f34d310c9242 100644 --- a/sw/source/uibase/docvw/edtwin.cxx +++ b/sw/source/uibase/docvw/edtwin.cxx @@ -1453,12 +1453,28 @@ void SwEditWin::KeyInput(const KeyEvent &rKEvt) if( ( bVertText && ( !bTableCursor || bVertTable ) ) || ( bTableCursor && bVertTable ) ) { - // Attempt to integrate cursor travelling for mongolian layout does not work. - // Thus, back to previous mapping of cursor keys to direction keys. - if( KEY_UP == nKey ) nKey = KEY_LEFT; - else if( KEY_DOWN == nKey ) nKey = KEY_RIGHT; - else if( KEY_LEFT == nKey ) nKey = KEY_DOWN; - else /* KEY_RIGHT == nKey */ nKey = KEY_UP; + SvxFrameDirection eDirection = rSh.GetTextDirection(); + if (eDirection == SvxFrameDirection::Vertical_LR_BT) + { + // Map from physical to logical, so rotate clockwise. + if (KEY_UP == nKey) + nKey = KEY_RIGHT; + else if (KEY_DOWN == nKey) + nKey = KEY_LEFT; + else if (KEY_LEFT == nKey) + nKey = KEY_UP; + else /* KEY_RIGHT == nKey */ + nKey = KEY_DOWN; + } + else + { + // Attempt to integrate cursor travelling for mongolian layout does not work. + // Thus, back to previous mapping of cursor keys to direction keys. + if( KEY_UP == nKey ) nKey = KEY_LEFT; + else if( KEY_DOWN == nKey ) nKey = KEY_RIGHT; + else if( KEY_LEFT == nKey ) nKey = KEY_DOWN; + else /* KEY_RIGHT == nKey */ nKey = KEY_UP; + } } if ( rSh.IsInRightToLeftText() ) diff --git a/sw/source/uibase/inc/edtwin.hxx b/sw/source/uibase/inc/edtwin.hxx index 0f63aa229884..abb7f4cd68a4 100644 --- a/sw/source/uibase/inc/edtwin.hxx +++ b/sw/source/uibase/inc/edtwin.hxx @@ -56,12 +56,13 @@ enum class SdrHitKind; To translate the pixel positions from the buffer OutputDevice to the real pixel positions, use the PixelToLogic methods of this class. */ -class SwEditWin final : public vcl::Window, +class SW_DLLPUBLIC SwEditWin final : public vcl::Window, public DropTargetHelper, public DragSourceHelper { static QuickHelpData* m_pQuickHlpData; - static long m_nDDStartPosX, m_nDDStartPosY; + static long m_nDDStartPosX; + static long m_nDDStartPosY; Color m_aWaterCanTextColor; // text color; for the watering can Color m_aWaterCanTextBackColor; // text background; for the watering can commit 16c6c90b5be29052589df3cc537865795bec04ec Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Fri Feb 15 16:52:20 2019 +0100 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Wed Jul 3 10:34:00 2019 +0200 sw btlr writing mode shell: fix cursor position By implementing the SwRect variant of SwTextFrame::SwitchHorizontalToVertical() for the IsVertLRBT() == true case. The blinking cursor position after doc load is now correct. Change-Id: I4862a6de286d3c0a34235fa0be8be2746b1a4151 Reviewed-on: https://gerrit.libreoffice.org/67880 Reviewed-by: Miklos Vajna <vmik...@collabora.com> Tested-by: Jenkins (cherry picked from commit 61bb90aac5038b5ff051668f7ae86eb61658e4f3) diff --git a/sw/qa/extras/layout/layout.cxx b/sw/qa/extras/layout/layout.cxx index c70b0d13d9da..f59d867b0c38 100644 --- a/sw/qa/extras/layout/layout.cxx +++ b/sw/qa/extras/layout/layout.cxx @@ -2768,6 +2768,26 @@ void SwLayoutWriter::testBtlrCell() // Actual : 0', i.e. the AAA2 frame was not visible due to 0 width. pXmlDoc = parseLayoutDump(); assertXPath(pXmlDoc, "/root/page/body/tab/row/cell[1]/txt[2]/infos/bounds", "width", "269"); + + // Test the position of the cursor after doc load. + // We expect that it's inside the first text frame in the first cell. + // More precisely, this is a bottom to top vertical frame, so we expect it's at the start, which + // means it's at the lower half of the text frame rectangle (vertically). + SwWrtShell* pWrtShell = pShell->GetWrtShell(); + CPPUNIT_ASSERT(pWrtShell); + + const SwRect& rCharRect = pWrtShell->GetCharRect(); + SwTwips nFirstParaTop + = getXPath(pXmlDoc, "/root/page/body/tab/row/cell[1]/txt[1]/infos/bounds", "top").toInt32(); + SwTwips nFirstParaHeight + = getXPath(pXmlDoc, "/root/page/body/tab/row/cell[1]/txt[1]/infos/bounds", "height") + .toInt32(); + SwTwips nFirstParaMiddle = nFirstParaTop + nFirstParaHeight / 2; + SwTwips nFirstParaBottom = nFirstParaTop + nFirstParaHeight; + // Without the accompanying fix in place, this test would have failed: the lower half (vertical) + // range was 2273 -> 2835, the good vertical position is 2730, the bad one was 1830. + CPPUNIT_ASSERT_GREATER(nFirstParaMiddle, rCharRect.Top()); + CPPUNIT_ASSERT_LESS(nFirstParaBottom, rCharRect.Top()); #endif } diff --git a/sw/source/core/text/txtfrm.cxx b/sw/source/core/text/txtfrm.cxx index f02eed653ba5..430a9804877a 100644 --- a/sw/source/core/text/txtfrm.cxx +++ b/sw/source/core/text/txtfrm.cxx @@ -478,8 +478,18 @@ void SwTextFrame::SwitchHorizontalToVertical( SwRect& rRect ) const long nOfstX, nOfstY; if ( IsVertLR() ) { - nOfstX = rRect.Left() - getFrameArea().Left(); - nOfstY = rRect.Top() - getFrameArea().Top(); + if (IsVertLRBT()) + { + // X and Y offsets here mean the position of the point that will be the top left corner + // after the switch. + nOfstX = rRect.Left() + rRect.Width() - getFrameArea().Left(); + nOfstY = rRect.Top() - getFrameArea().Top(); + } + else + { + nOfstX = rRect.Left() - getFrameArea().Left(); + nOfstY = rRect.Top() - getFrameArea().Top(); + } } else { @@ -491,7 +501,12 @@ void SwTextFrame::SwitchHorizontalToVertical( SwRect& rRect ) const const long nHeight = rRect.Height(); if ( IsVertLR() ) - rRect.Left(getFrameArea().Left() + nOfstY); + { + if (IsVertLRBT()) + rRect.Left(getFrameArea().Left() + nOfstY); + else + rRect.Left(getFrameArea().Left() + nOfstY); + } else { if ( mbIsSwapped ) @@ -501,7 +516,14 @@ void SwTextFrame::SwitchHorizontalToVertical( SwRect& rRect ) const rRect.Left( getFrameArea().Left() + getFrameArea().Width() - nOfstY ); } - rRect.Top( getFrameArea().Top() + nOfstX ); + if (IsVertLRBT()) + { + SAL_WARN_IF(!mbIsSwapped, "sw.core", + "SwTextFrame::SwitchHorizontalToVertical, IsVertLRBT, not swapped"); + rRect.Top(getFrameArea().Top() + getFrameArea().Width() - nOfstX); + } + else + rRect.Top(getFrameArea().Top() + nOfstX); rRect.Width( nHeight ); rRect.Height( nWidth ); } commit 9e47f03e1241f35972c01e9cad6ec6accb4a6bf2 Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Fri Feb 15 14:06:15 2019 +0100 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Wed Jul 3 10:33:15 2019 +0200 sw btlr writing mode: implement DOCX filter Replace the old trick with character-level rotation with the usage of the new writing direction. This means that finally table cells with btlr text direction and multiple paragraphs show all content, not only the first paragraph, as before (seen as data loss by users). (cherry picked from commit 8fdbda18b593e7014e44a0fd590bbf98d83258b7) Conflicts: writerfilter/source/dmapper/DomainMapperTableManager.cxx Change-Id: I094f36fa6ba0701579e487e8e0212707987b1b2f diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport8.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport8.cxx index feb99c340d85..b0bd7bf349c5 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport8.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport8.cxx @@ -775,9 +775,8 @@ DECLARE_OOXMLEXPORT_TEST(testTbLrHeight, "tblr-height.docx") uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, uno::UNO_QUERY); uno::Reference<container::XIndexAccess> xTables(xTextTablesSupplier->getTextTables(), uno::UNO_QUERY); uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY); - uno::Reference<table::XTableRows> xTableRows(xTable->getRows(), uno::UNO_QUERY); - // btLr text direction was imported as MIN, it should be FIX to avoid incorrectly large height in case of too much content. - CPPUNIT_ASSERT_EQUAL(text::SizeType::FIX, getProperty<sal_Int16>(xTableRows->getByIndex(0), "SizeType")); + uno::Reference<table::XCell> xCell = xTable->getCellByName("B1"); + CPPUNIT_ASSERT_EQUAL(text::WritingMode2::BT_LR, getProperty<sal_Int16>(xCell, "WritingMode")); } DECLARE_OOXMLEXPORT_TEST(testBnc865381, "bnc865381.docx") @@ -785,11 +784,8 @@ DECLARE_OOXMLEXPORT_TEST(testBnc865381, "bnc865381.docx") uno::Reference<text::XTextTablesSupplier> xTablesSupplier(mxComponent, uno::UNO_QUERY); uno::Reference<container::XIndexAccess> xTables(xTablesSupplier->getTextTables(), uno::UNO_QUERY); uno::Reference<text::XTextTable> xTextTable(xTables->getByIndex(0), uno::UNO_QUERY); - uno::Reference<table::XTableRows> xTableRows(xTextTable->getRows(), uno::UNO_QUERY); - // Second row has a vertically merged cell, make sure size type is not FIX in that case (otherwise B2 is not readable). - CPPUNIT_ASSERT(text::SizeType::FIX != getProperty<sal_Int16>(xTableRows->getByIndex(1), "SizeType")); - // Explicit size of 41 mm100 was set, so the vertical text in A2 was not readable. - CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(xTableRows->getByIndex(1), "Height")); + uno::Reference<table::XCell> xCell = xTextTable->getCellByName("A2"); + CPPUNIT_ASSERT_EQUAL(text::WritingMode2::BT_LR, getProperty<sal_Int16>(xCell, "WritingMode")); } DECLARE_OOXMLEXPORT_TEST(testFdo53985, "fdo53985.docx") diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx index 8fcc14b6d8b9..b20a2a37949b 100644 --- a/sw/source/filter/ww8/docxattributeoutput.cxx +++ b/sw/source/filter/ww8/docxattributeoutput.cxx @@ -4320,28 +4320,11 @@ void DocxAttributeOutput::TableVerticalCell( ww8::WW8TableNodeInfoInner::Pointer m_pSerializer->singleElementNS( XML_w, XML_textDirection, FSNS( XML_w, XML_val ), "tbRl", FSEND ); - else if ( SvxFrameDirection::Horizontal_LR_TB == m_rExport.TrueFrameDirection( *pFrameFormat ) ) + else if ( SvxFrameDirection::Vertical_LR_BT == m_rExport.TrueFrameDirection( *pFrameFormat ) ) { - // Undo the text direction mangling done by the btLr handler in writerfilter::dmapper::DomainMapperTableManager::sprm() - const SwStartNode* pSttNd = pTabBox->GetSttNd(); - if (pSttNd) - { - SwPaM aPam(*pSttNd, 0); - ++aPam.GetPoint()->nNode; - if (aPam.GetPoint()->nNode.GetNode().IsTextNode()) - { - const SwTextNode& rTextNode = static_cast<const SwTextNode&>(aPam.GetPoint()->nNode.GetNode()); - if( const SwAttrSet* pAttrSet = rTextNode.GetpSwAttrSet()) - { - const SvxCharRotateItem& rCharRotate = pAttrSet->GetCharRotate(); - if (rCharRotate.GetValue() == 900) - { - m_pSerializer->singleElementNS( XML_w, XML_textDirection, FSNS( XML_w, XML_val ), "btLr", FSEND ); - m_bBtLr = true; - } - } - } - } + m_pSerializer->singleElementNS( XML_w, XML_textDirection, + FSNS( XML_w, XML_val ), "btLr", + FSEND ); } const SwWriteTableRows& rRows = m_xTableWrt->GetRows( ); diff --git a/writerfilter/source/dmapper/DomainMapperTableManager.cxx b/writerfilter/source/dmapper/DomainMapperTableManager.cxx index b698fabe0c44..f7538768360f 100644 --- a/writerfilter/source/dmapper/DomainMapperTableManager.cxx +++ b/writerfilter/source/dmapper/DomainMapperTableManager.cxx @@ -298,20 +298,7 @@ bool DomainMapperTableManager::sprm(Sprm & rSprm) SAL_INFO( "writerfilter", "Have inserted textDirection " << nIntValue ); break; case NS_ooxml::LN_Value_ST_TextDirection_btLr: - { - // We have to fake this text direction - pPropMap->Insert( PROP_FRM_DIRECTION, uno::makeAny( text::WritingMode2::LR_TB )); - pPropMap->Insert( PROP_CHAR_ROTATION, uno::makeAny( sal_Int16( 900 ) )); - SAL_INFO( "writerfilter", "Have inserted textDirection " << nIntValue ); - - // We're faking a text direction, so don't allow multiple lines. - if (!getCellProps() || !getCellProps()->isSet(PROP_VERTICAL_MERGE)) - { - // Though in case there will be a vertical merge, don't do this, it hides text that is supposed to be visible. - m_bRowSizeTypeInserted = true; - } - m_bHasBtlrCell = true; - } + pPropMap->Insert( PROP_FRM_DIRECTION, uno::makeAny( text::WritingMode2::BT_LR )); break; case NS_ooxml::LN_Value_ST_TextDirection_lrTbV: pPropMap->Insert( PROP_FRM_DIRECTION, uno::makeAny( text::WritingMode2::LR_TB )); _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits