diff options
-rw-r--r-- | editeng/source/items/svxfont.cxx | 74 | ||||
-rw-r--r-- | include/editeng/svxfont.hxx | 7 | ||||
-rw-r--r-- | sc/inc/fillinfo.hxx | 4 | ||||
-rw-r--r-- | sc/qa/unit/data/xlsx/tdf119292.xlsx | bin | 0 -> 10764 bytes | |||
-rw-r--r-- | sc/qa/unit/subsequent_filters-test.cxx | 41 | ||||
-rw-r--r-- | sc/source/ui/inc/output.hxx | 7 | ||||
-rw-r--r-- | sc/source/ui/view/output.cxx | 44 | ||||
-rw-r--r-- | sc/source/ui/view/output2.cxx | 64 |
8 files changed, 171 insertions, 70 deletions
diff --git a/editeng/source/items/svxfont.cxx b/editeng/source/items/svxfont.cxx index f5d0e2d79a26..61039b316ac6 100644 --- a/editeng/source/items/svxfont.cxx +++ b/editeng/source/items/svxfont.cxx @@ -86,32 +86,62 @@ void SvxFont::SetNonAutoEscapement(short nNewEsc, const OutputDevice* pOutDev) nEsc = -MAX_ESC_POS; } -void SvxFont::DrawArrow( OutputDevice &rOut, const tools::Rectangle& rRect, - const Size& rSize, const Color& rCol, bool bLeft ) +tools::Polygon SvxFont::DrawArrow( OutputDevice &rOut, const tools::Rectangle& rRect, + const Size& rSize, const Color& rCol, bool bLeftOrTop, bool bVertical ) { - tools::Long nLeft = ( rRect.Left() + rRect.Right() - rSize.Width() )/ 2; - tools::Long nRight = nLeft + rSize.Width(); - tools::Long nMid = ( rRect.Top() + rRect.Bottom() ) / 2; - tools::Long nTop = nMid - rSize.Height() / 2; - tools::Long nBottom = nTop + rSize.Height(); - if( nLeft < rRect.Left() ) + tools::Polygon aPoly; + Point aTmp; + Point aNxt; + if (bVertical) { - nLeft = rRect.Left(); - nRight = rRect.Right(); + tools::Long nLeft = ((rRect.Left() + rRect.Right()) / 2) - (rSize.Height() / 2); + tools::Long nRight = ((rRect.Left() + rRect.Right()) / 2) + (rSize.Height() / 2); + tools::Long nMid = (rRect.Left() + rRect.Right()) / 2; + tools::Long nTop = ((rRect.Top() + rRect.Bottom()) / 2) - (rSize.Height() / 2); + tools::Long nBottom = nTop + rSize.Height(); + if (nTop < rRect.Top()) + { + if (bLeftOrTop) + { + nTop = rRect.Top(); + nBottom = rRect.Bottom(); + } + else + { + nTop = rRect.Bottom(); + nBottom = rRect.Bottom() - (rSize.Height() / 2); + } + } + aTmp.setX(nRight); + aTmp.setY(nBottom); + aNxt.setX(nMid); + aNxt.setY(nTop); + aPoly.Insert(0, aTmp); + aPoly.Insert(0, aNxt); + aTmp.setX(nLeft); + aPoly.Insert(0, aTmp); } - if( nTop < rRect.Top() ) + else { - nTop = rRect.Top(); - nBottom = rRect.Bottom(); + tools::Long nLeft = (rRect.Left() + rRect.Right() - rSize.Width()) / 2; + tools::Long nRight = nLeft + rSize.Width(); + tools::Long nMid = (rRect.Top() + rRect.Bottom()) / 2; + tools::Long nTop = nMid - rSize.Height() / 2; + tools::Long nBottom = nTop + rSize.Height(); + if (nLeft < rRect.Left()) + { + nLeft = rRect.Left(); + nRight = rRect.Right(); + } + aTmp.setX(bLeftOrTop ? nLeft : nRight); + aTmp.setY(nMid); + aNxt.setX(bLeftOrTop ? nRight : nLeft); + aNxt.setY(nTop); + aPoly.Insert(0, aTmp); + aPoly.Insert(0, aNxt); + aNxt.setY(nBottom); + aPoly.Insert(0, aNxt); } - tools::Polygon aPoly; - Point aTmp( bLeft ? nLeft : nRight, nMid ); - Point aNxt( bLeft ? nRight : nLeft, nTop ); - aPoly.Insert( 0, aTmp ); - aPoly.Insert( 0, aNxt ); - aNxt.setY( nBottom ); - aPoly.Insert( 0, aNxt ); - aPoly.Insert( 0, aTmp ); Color aOldLineColor = rOut.GetLineColor(); Color aOldFillColor = rOut.GetFillColor(); rOut.SetFillColor( rCol ); @@ -120,9 +150,9 @@ void SvxFont::DrawArrow( OutputDevice &rOut, const tools::Rectangle& rRect, rOut.DrawLine( aTmp, aNxt ); rOut.SetLineColor( aOldLineColor ); rOut.SetFillColor( aOldFillColor ); + return aPoly; } - OUString SvxFont::CalcCaseMap(const OUString &rTxt) const { if (!IsCaseMap() || rTxt.isEmpty()) diff --git a/include/editeng/svxfont.hxx b/include/editeng/svxfont.hxx index c8e8c6670b12..b385ada1592d 100644 --- a/include/editeng/svxfont.hxx +++ b/include/editeng/svxfont.hxx @@ -23,6 +23,7 @@ #include <tools/long.hxx> #include <vcl/font.hxx> #include <editeng/editengdllapi.h> +#include <tools/poly.hxx> // Percentage of height of lower case small capital letters compared to upper case letters // See i#1526# for full explanation @@ -103,8 +104,10 @@ public: const Point &rPos, const OUString &rTxt, const sal_Int32 nIdx = 0, const sal_Int32 nLen = SAL_MAX_INT32 ) const; - static void DrawArrow( OutputDevice &rOut, const tools::Rectangle& rRect, - const Size& rSize, const Color& rCol, bool bLeft ); + static tools::Polygon DrawArrow( OutputDevice &rOut, const tools::Rectangle& rRect, + const Size& rSize, const Color& rCol, bool bLeftOrTop, + bool bVertical ); + SvxFont& operator=( const SvxFont& rFont ); SvxFont& operator=( const Font& rFont ); }; diff --git a/sc/inc/fillinfo.hxx b/sc/inc/fillinfo.hxx index e18e3f545536..c4f995c21c1d 100644 --- a/sc/inc/fillinfo.hxx +++ b/sc/inc/fillinfo.hxx @@ -42,10 +42,10 @@ enum class ScRotateDir : sal_uInt8 { }; enum class ScClipMark : sal_uInt8 { - NONE = 0x00, Left = 0x01, Right = 0x02 + NONE = 0x00, Left = 0x01, Right = 0x02, Bottom = 0x03, Top = 0x04 }; namespace o3tl { - template<> struct typed_flags<ScClipMark> : is_typed_flags<ScClipMark, 0x03> {}; + template<> struct typed_flags<ScClipMark> : is_typed_flags<ScClipMark, 0x07> {}; } const sal_uInt8 SC_CLIPMARK_SIZE = 64; diff --git a/sc/qa/unit/data/xlsx/tdf119292.xlsx b/sc/qa/unit/data/xlsx/tdf119292.xlsx Binary files differnew file mode 100644 index 000000000000..cf3d3dc08dbb --- /dev/null +++ b/sc/qa/unit/data/xlsx/tdf119292.xlsx diff --git a/sc/qa/unit/subsequent_filters-test.cxx b/sc/qa/unit/subsequent_filters-test.cxx index 0807f29a3587..3d886c7b10fb 100644 --- a/sc/qa/unit/subsequent_filters-test.cxx +++ b/sc/qa/unit/subsequent_filters-test.cxx @@ -109,6 +109,7 @@ public: //ods, xls, xlsx filter tests void testCondFormatOperatorsSameRangeXLSX(); + void testTdf119292(); void testCondFormatFormulaIsXLSX(); void testCondFormatBeginsAndEndsWithXLSX(); void testExtCondFormatXLSX(); @@ -316,6 +317,7 @@ public: CPPUNIT_TEST_SUITE(ScFiltersTest); CPPUNIT_TEST(testCondFormatOperatorsSameRangeXLSX); + CPPUNIT_TEST(testTdf119292); CPPUNIT_TEST(testCondFormatFormulaIsXLSX); CPPUNIT_TEST(testCondFormatBeginsAndEndsWithXLSX); CPPUNIT_TEST(testExtCondFormatXLSX); @@ -582,21 +584,54 @@ void ScFiltersTest::testCondFormatOperatorsSameRangeXLSX() CPPUNIT_ASSERT_EQUAL(ScFormatEntry::Type::ExtCondition, pEntry->GetType()); const ScCondFormatEntry* pCondition = static_cast<const ScCondFormatEntry*>(pEntry); - CPPUNIT_ASSERT_EQUAL( ScConditionMode::ContainsText, pCondition->GetOperation()); + CPPUNIT_ASSERT_EQUAL(ScConditionMode::ContainsText, pCondition->GetOperation()); pEntry = pFormat->GetEntry(1); CPPUNIT_ASSERT(pEntry); CPPUNIT_ASSERT_EQUAL(ScFormatEntry::Type::ExtCondition, pEntry->GetType()); pCondition = static_cast<const ScCondFormatEntry*>(pEntry); - CPPUNIT_ASSERT_EQUAL( ScConditionMode::BeginsWith, pCondition->GetOperation()); + CPPUNIT_ASSERT_EQUAL(ScConditionMode::BeginsWith, pCondition->GetOperation()); pEntry = pFormat->GetEntry(2); CPPUNIT_ASSERT(pEntry); CPPUNIT_ASSERT_EQUAL(ScFormatEntry::Type::ExtCondition, pEntry->GetType()); pCondition = static_cast<const ScCondFormatEntry*>(pEntry); - CPPUNIT_ASSERT_EQUAL( ScConditionMode::EndsWith, pCondition->GetOperation()); + CPPUNIT_ASSERT_EQUAL(ScConditionMode::EndsWith, pCondition->GetOperation()); + + xDocSh->DoClose(); +} + +void ScFiltersTest::testTdf119292() +{ + ScDocShellRef xDocSh = loadDoc(u"tdf119292.", FORMAT_XLSX); + CPPUNIT_ASSERT_MESSAGE("Failed to load tdf119292.xlsx", xDocSh.is()); + + ScDocument& rDoc = xDocSh->GetDocument(); + auto* pDev = rDoc.GetRefDevice(); + Size aMarkSize(4, 6); + Color aArrowFillCol(COL_LIGHTRED); + + // check the points of the polygon if the text is rotated 90 degrees + tools::Rectangle aMarkRect1(0, 0, 45, 3); + tools::Polygon aPoly90degrees = SvxFont::DrawArrow(*pDev, aMarkRect1, aMarkSize, aArrowFillCol, true, true); + Point aPoly90Pos1 = aPoly90degrees.GetPoint(0); + Point aPoly90Pos2 = aPoly90degrees.GetPoint(1); + Point aPoly90Pos3 = aPoly90degrees.GetPoint(2); + CPPUNIT_ASSERT_EQUAL(Point(19,3),aPoly90Pos1); + CPPUNIT_ASSERT_EQUAL(Point(22,0),aPoly90Pos2); + CPPUNIT_ASSERT_EQUAL(Point(25,3),aPoly90Pos3); + + // check the points of the polygon if the text is rotated 270 degrees + tools::Rectangle aMarkRect2(89, 62, 134, 57); + tools::Polygon aPoly270degrees = SvxFont::DrawArrow(*pDev, aMarkRect2, aMarkSize, aArrowFillCol, false, true); + Point aPoly270Pos1 = aPoly270degrees.GetPoint(0); + Point aPoly270Pos2 = aPoly270degrees.GetPoint(1); + Point aPoly270Pos3 = aPoly270degrees.GetPoint(2); + CPPUNIT_ASSERT_EQUAL(Point(108,54),aPoly270Pos1); + CPPUNIT_ASSERT_EQUAL(Point(111,57),aPoly270Pos2); + CPPUNIT_ASSERT_EQUAL(Point(114,54),aPoly270Pos3); xDocSh->DoClose(); } diff --git a/sc/source/ui/inc/output.hxx b/sc/source/ui/inc/output.hxx index e45fe29e14ac..b3079259f8b0 100644 --- a/sc/source/ui/inc/output.hxx +++ b/sc/source/ui/inc/output.hxx @@ -231,6 +231,7 @@ private: bool bSnapPixel; bool bAnyClipped; // internal + bool bVertical; bool bTabProtected; bool bLayoutRTL; @@ -277,11 +278,11 @@ private: std::unique_ptr<ScFieldEditEngine> CreateOutputEditEngine(); - void ShowClipMarks( DrawEditParam& rParam, tools::Long nEngineHeight, const Size& aCellSize, - bool bMerged, OutputAreaParam& aAreaParam ); + void ShowClipMarks( DrawEditParam& rParam, tools::Long nEngineWidth, const Size& aCellSize, + bool bMerged, OutputAreaParam& aAreaParam, bool bTop ); ClearableClipRegionPtr Clip(DrawEditParam& rParam, const Size& aCellSize, OutputAreaParam& aAreaParam, - tools::Long nEngineHeight, bool bWrapFields); + tools::Long nEngineWidth, bool bWrapFields, bool bTop); bool AdjustAreaParamClipRect(OutputAreaParam& rAreaParam); tools::Long SetEngineTextAndGetWidth( DrawEditParam& rParam, const OUString& rSetString, diff --git a/sc/source/ui/view/output.cxx b/sc/source/ui/view/output.cxx index b73b2fd0980b..fc1750f53e14 100644 --- a/sc/source/ui/view/output.cxx +++ b/sc/source/ui/view/output.cxx @@ -173,6 +173,7 @@ ScOutputData::ScOutputData( OutputDevice* pNewDev, ScOutputType eNewType, bMarkClipped( false ), // sal_False for printer/metafile etc. bSnapPixel( false ), bAnyClipped( false ), + bVertical(false), mpTargetPaintWindow(nullptr), // #i74769# use SdrPaintWindow direct mpSpellCheckCxt(nullptr) { @@ -2552,19 +2553,42 @@ void ScOutputData::DrawClipMarks() tools::Long nMarkPixel = static_cast<tools::Long>( SC_CLIPMARK_SIZE * mnPPTX ); Size aMarkSize( nMarkPixel, (nMarkPixel-1)*2 ); - if ( pInfo->nClipMark & ( bLayoutRTL ? ScClipMark::Right : ScClipMark::Left ) ) + if (bVertical) { - // visually left - tools::Rectangle aMarkRect = aCellRect; - aMarkRect.SetRight( aCellRect.Left()+nMarkPixel-1 ); - SvxFont::DrawArrow( *mpDev, aMarkRect, aMarkSize, aArrowFillCol, true ); + if (pInfo->nClipMark & (bLayoutRTL ? ScClipMark::Bottom : ScClipMark::Top)) + { + // visually top + tools::Rectangle aMarkRect = aCellRect; + aMarkRect.SetBottom(aCellRect.Top() + nMarkPixel - 1); + SvxFont::DrawArrow(*mpDev, aMarkRect, aMarkSize, aArrowFillCol, true, true); + } + if (pInfo->nClipMark & (bLayoutRTL ? ScClipMark::Top : ScClipMark::Bottom)) + { + // visually bottom + tools::Rectangle aMarkRect = aCellRect; + aMarkRect.SetTop(aCellRect.Bottom() + nMarkPixel + 1); + SvxFont::DrawArrow(*mpDev, aMarkRect, aMarkSize, aArrowFillCol, false, + true); + } } - if ( pInfo->nClipMark & ( bLayoutRTL ? ScClipMark::Left : ScClipMark::Right ) ) + else { - // visually right - tools::Rectangle aMarkRect = aCellRect; - aMarkRect.SetLeft( aCellRect.Right()-nMarkPixel+1 ); - SvxFont::DrawArrow( *mpDev, aMarkRect, aMarkSize, aArrowFillCol, false ); + if (pInfo->nClipMark & (bLayoutRTL ? ScClipMark::Right : ScClipMark::Left)) + { + // visually left + tools::Rectangle aMarkRect = aCellRect; + aMarkRect.SetRight(aCellRect.Left() + nMarkPixel - 1); + SvxFont::DrawArrow(*mpDev, aMarkRect, aMarkSize, aArrowFillCol, true, + false); + } + if (pInfo->nClipMark & (bLayoutRTL ? ScClipMark::Left : ScClipMark::Right)) + { + // visually right + tools::Rectangle aMarkRect = aCellRect; + aMarkRect.SetLeft(aCellRect.Right() - nMarkPixel + 1); + SvxFont::DrawArrow(*mpDev, aMarkRect, aMarkSize, aArrowFillCol, false, + false); + } } } nPosX += pRowInfo[0].pCellInfo[nX+1].nWidth * nLayoutSign; diff --git a/sc/source/ui/view/output2.cxx b/sc/source/ui/view/output2.cxx index 4d5003bdc02e..e2726517a874 100644 --- a/sc/source/ui/view/output2.cxx +++ b/sc/source/ui/view/output2.cxx @@ -3186,48 +3186,56 @@ void ScOutputData::DrawEditStandard(DrawEditParam& rParam) rParam.adjustForHyperlinkInPDF(aURLStart, mpDev); } -void ScOutputData::ShowClipMarks( DrawEditParam& rParam, tools::Long nEngineHeight, const Size& aCellSize, - bool bMerged, OutputAreaParam& aAreaParam) +void ScOutputData::ShowClipMarks( DrawEditParam& rParam, tools::Long nEngineWidth, const Size& aCellSize, + bool bMerged, OutputAreaParam& aAreaParam, bool bTop) { - // Show clip marks if height is at least 5pt too small and + // Show clip marks if width is at least 5pt too small and // there are several lines of text. // Not for asian vertical text, because that would interfere // with the default right position of the text. // Only with automatic line breaks, to avoid having to find // the cells with the horizontal end of the text again. - if ( !(nEngineHeight - aCellSize.Height() > 100 && - rParam.mbBreak && bMarkClipped && - ( rParam.mpEngine->GetParagraphCount() > 1 || rParam.mpEngine->GetLineCount(0) > 1 )) ) - return; - - CellInfo* pClipMarkCell = nullptr; - if ( bMerged ) + if (nEngineWidth - aCellSize.Width() > 100 && rParam.mbBreak && bMarkClipped + && (rParam.mpEngine->GetParagraphCount() > 1 || rParam.mpEngine->GetLineCount(0) > 1)) { - // anywhere in the merged area... - SCCOL nClipX = ( rParam.mnX < nX1 ) ? nX1 : rParam.mnX; - pClipMarkCell = &pRowInfo[(rParam.mnArrY != 0) ? rParam.mnArrY : 1].pCellInfo[nClipX+1]; - } - else - pClipMarkCell = &rParam.mpThisRowInfo->pCellInfo[rParam.mnX+1]; - - pClipMarkCell->nClipMark |= ScClipMark::Right; //! also allow left? - bAnyClipped = true; + CellInfo* pClipMarkCell = nullptr; + if (bMerged) + { + // anywhere in the merged area... + SCCOL nClipX = (rParam.mnX < nX1) ? nX1 : rParam.mnX; + pClipMarkCell = &pRowInfo[(rParam.mnArrY != 0) ? rParam.mnArrY : 1].pCellInfo[nClipX + 1]; + } + else + pClipMarkCell = &rParam.mpThisRowInfo->pCellInfo[rParam.mnX + 1]; - const tools::Long nMarkPixel = static_cast<tools::Long>( SC_CLIPMARK_SIZE * mnPPTX ); - if ( aAreaParam.maClipRect.Right() - nMarkPixel > aAreaParam.maClipRect.Left() ) - aAreaParam.maClipRect.AdjustRight( -nMarkPixel ); + bAnyClipped = true; + bVertical = true; + const tools::Long nMarkPixel = static_cast<tools::Long>(SC_CLIPMARK_SIZE * mnPPTX); + if (bTop) + { + pClipMarkCell->nClipMark |= ScClipMark::Top; + if (aAreaParam.maClipRect.Top() - nMarkPixel < aAreaParam.maClipRect.Bottom()) + aAreaParam.maClipRect.AdjustTop(+nMarkPixel); + } + else + { + pClipMarkCell->nClipMark |= ScClipMark::Bottom; + if (aAreaParam.maClipRect.Top() - nMarkPixel < aAreaParam.maClipRect.Bottom()) + aAreaParam.maClipRect.AdjustBottom(-nMarkPixel); + } + } } ClearableClipRegionPtr ScOutputData::Clip( DrawEditParam& rParam, const Size& aCellSize, - OutputAreaParam& aAreaParam, tools::Long nEngineHeight, - bool bWrapFields) + OutputAreaParam& aAreaParam, tools::Long nEngineWidth, + bool bWrapFields, bool bTop) { // Also take fields in a cell with automatic breaks into account: clip to cell width bool bClip = AdjustAreaParamClipRect(aAreaParam) || aAreaParam.mbLeftClip || aAreaParam.mbRightClip || bWrapFields; bool bSimClip = false; const Size& aRefOne = mpRefDevice->PixelToLogic(Size(1,1)); - if ( nEngineHeight >= aCellSize.Height() + aRefOne.Height() ) + if ( nEngineWidth >= aCellSize.Width() + aRefOne.Width() ) { const ScMergeAttr* pMerge = &rParam.mpPattern->GetItem(ATTR_MERGE); const bool bMerged = pMerge->GetColMerge() > 1 || pMerge->GetRowMerge() > 1; @@ -3243,7 +3251,7 @@ ClearableClipRegionPtr ScOutputData::Clip( DrawEditParam& rParam, const Size& aC else bSimClip = true; - ShowClipMarks( rParam, nEngineHeight, aCellSize, bMerged, aAreaParam); + ShowClipMarks( rParam, nEngineWidth, aCellSize, bMerged, aAreaParam, bTop); } // Clip marks are already handled in GetOutputArea @@ -3425,7 +3433,7 @@ void ScOutputData::DrawEditBottomTop(DrawEditParam& rParam) Point aURLStart; { - const auto pClipRegion = Clip( rParam, aCellSize, aAreaParam, nEngineHeight, bWrapFields ); + const auto pClipRegion = Clip( rParam, aCellSize, aAreaParam, nEngineWidth, bWrapFields, true ); Point aLogicStart(nStartX, nStartY); rParam.calcStartPosForVertical(aLogicStart, aCellSize.Width(), nEngineWidth, nTopM, mpRefDevice); @@ -3671,7 +3679,7 @@ void ScOutputData::DrawEditTopBottom(DrawEditParam& rParam) Point aURLStart; { - const auto pClipRegion = Clip( rParam, aCellSize, aAreaParam, nEngineHeight, bWrapFields ); + const auto pClipRegion = Clip( rParam, aCellSize, aAreaParam, nEngineWidth, bWrapFields, false ); Point aLogicStart(nStartX, nStartY); rParam.calcStartPosForVertical(aLogicStart, aCellSize.Width(), nEngineWidth, nTopM, mpRefDevice); |