summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArmin Le Grand <Armin.Le.Grand@cib.de>2018-01-18 17:07:43 +0100
committerThorsten Behrens <Thorsten.Behrens@CIB.de>2018-01-30 12:57:49 +0100
commitf839ea98181a1c6970fe25a82cf798dc151ed332 (patch)
tree6b52b5bb035b55fc9ec377b675c00163708bdac3
parent9e7344ae5776117e94684713767fae1b0afbb6b9 (diff)
fix tdf#114934 borderline feature regressions
squashing some master commits, fixes the following bugs: - tdf#114934 which contains: - tdf#115169: Calc: Rotated Cells not shown rotated when using Print/PDF/PrintPreview - tdf#113751: Borders for Merged Cells are Partially Shown - tdf#114625: Calc can not print right border of merged cells from LO 6.0 - tdf#114824: Export to PDF and Printing: Borders of Merged Cells Flow to Page Footer BorderlineFix: Need to redesign Borderline paint for Calc To fix some errors, need to change svx::frame::Array conversion to Primitives, especially regarding handling of merged cells. These make problems in the currtent form where the full extended merged cell tries to be converted. This is bad for cropped stuff and also wrong for double-line stuff attaching to a merged cell. The solution is to handle cells single and merge created primitives which is more expensive but will work. This will involve special handling for X-Ed (crossed) and 'roated' Cells. Also need to be very careful since all this is used in the meantime for all visualizations of Tables in multiple apps/situations. Change-Id: If0652a3ba97a6f27dd5d782ea22b1514303f3710 BorderlineFix: Corrected missing borders in print In Print/PDF/PrintPreview border lines were missing, this happened for merged cells. It has to do with access to the involved Styles and/or 'Clip' set (to avoid creating everything). Thus a 'mixed' usage of cell and merged-cell stuff was needed. As it turns out support for this is already there, need to use it. Change-Id: Ic16085b97eef5c79a4501279432f43491bca350e BorderlineFix: Avoid BorderLines to be too prolonged For MergedCells there was an effect that the BorderLines were painted too far in PrintPreview/Print/PDF visualization, found reason and changed. Checked (hopefully) all usages, looks good. Change-Id: I0acf8dcb20548a98533f3ab317ac72c0d0f0a947 BorderlineFix: Corrected handling for 'rotated' CellBorders CellBorders can be rotated (including their Text) and need special visualization that is based on an own sheared/rotated coordinate system. Currently only possible for single cells (not merged ones) and needs to handle all borders (also bottom-right directly in the rotated cell, not in the neighboured ones to have the geometry, plus avoiding these in the non-rotated neighbour cells. Also corrected adding CellRotation data to svx::frame::Array in calc using SetCellRotations() which now gets called in the ScOutputData constructor to ensure it gets called in all places where it is used. Change-Id: I47bdfc29ba5ca76bbc07d98cb64733f867b1ee20 BorderlineFix: Fixed visual updates when scrolling For Cells with DoubleLine the connections to perpendicular DoubleLine-Styles may have to be displayed in a Cell which is 'around' the orig cell in a Cell-Border of one. To represent that and to avoid repaint errors when scrolling in, the preparation of Primitives has to take accordingly more neighbour cells into account. Tested this change with the usages in Calc, UI (Dialogs) and Calc exports Print/PrintPreview/PDF. This does not affect Tables in Writer and/or Draw/Impress. Change-Id: I3bcc68cdf7b4fc1825a87a9773892c359421024e BorderlineFix: Fix WriterPaint if scrolling CellTableBorders Similar to CalcBorders in Writer the overlap regions for FrameBorders have to be taken into account when repainting the CellBordes of WriterTables Change-Id: I488ba158e1de579bfb06b9c8353adaa2cac706c6 BorderlineFix: Corrected Draw/Impress TableStyle accesses In Draw/Impress the indices for accessing the correct neighbouring TableStyles were wrong and thus created wrong visualizations, corrected that. Change-Id: Iebc5f294adb62fa4c6358e2f8c27d29cc3163fbc BorderlineFix: Use svx::frame::Array tooling in Draw/Impress For creating the needed BorderPrimitives for TableCells for the Tables used in Draw/Impress, adapt the ViewContactOfTableObj doing this to use svx::frame::Array tooling now. This will correct the error for not taking the neighboured connects for merged cells into account and unify one more space to the same tooling. Change-Id: I2e6f732985e9b963359f156628bd29ddfec1a80c BorderlineFix: Corrected wrong indexing in Array initialization Change-Id: I4222ef1c82620a05cea9f6db1a0664196cfb3bd4 Reviewed-on: https://gerrit.libreoffice.org/48891 Reviewed-by: Thorsten Behrens <Thorsten.Behrens@CIB.de> Tested-by: Thorsten Behrens <Thorsten.Behrens@CIB.de>
-rw-r--r--include/svx/framelink.hxx12
-rw-r--r--include/svx/framelinkarray.hxx8
-rw-r--r--sc/source/ui/inc/output.hxx7
-rw-r--r--sc/source/ui/miscdlgs/autofmt.cxx4
-rw-r--r--sc/source/ui/view/gridwin4.cxx4
-rw-r--r--sc/source/ui/view/output.cxx3
-rw-r--r--svx/Library_svx.mk1
-rw-r--r--svx/Library_svxcore.mk1
-rw-r--r--svx/source/dialog/framelink.cxx12
-rw-r--r--svx/source/dialog/framelinkarray.cxx472
-rw-r--r--svx/source/dialog/frmsel.cxx4
-rw-r--r--svx/source/table/viewcontactoftableobj.cxx197
-rw-r--r--sw/source/core/layout/paintfrm.cxx22
-rw-r--r--sw/source/ui/table/tautofmt.cxx4
14 files changed, 378 insertions, 373 deletions
diff --git a/include/svx/framelink.hxx b/include/svx/framelink.hxx
index 887c512e5433..661d775db240 100644
--- a/include/svx/framelink.hxx
+++ b/include/svx/framelink.hxx
@@ -143,18 +143,9 @@ private:
/// the impl class holding the data
std::shared_ptr< implStyle > maImplStyle;
- /// pointer to Cell using this style. Not member of the
- /// impl class since multiple Cells may use the same style
- const Cell* mpUsingCell;
-
/// call to set maImplStyle on demand
void implEnsureImplStyle();
- /// need information which cell this style info comes from due to needed
- /// rotation info (which is in the cell). Rotation depends on the cell.
- friend class Cell;
- void SetUsingCell(const Cell* pCell) { mpUsingCell = pCell; }
-
public:
/** Constructs an invisible frame style. */
explicit Style();
@@ -203,9 +194,6 @@ public:
/** Mirrors this style (exchanges primary and secondary), if it is a double frame style. */
Style& MirrorSelf();
- /** return the Cell using this style (if set) */
- const Cell* GetUsingCell() const { return mpUsingCell; }
-
bool operator==( const Style& rOther) const;
bool operator<( const Style& rOther) const;
};
diff --git a/include/svx/framelinkarray.hxx b/include/svx/framelinkarray.hxx
index 2b06d29a41b2..b73531b06e47 100644
--- a/include/svx/framelinkarray.hxx
+++ b/include/svx/framelinkarray.hxx
@@ -290,9 +290,8 @@ public:
long GetHeight() const;
/** Returns the output range of the cell (nCol,nRow).
- Returns total output range of merged ranges. */
- basegfx::B2DRange GetCellRange( size_t nCol, size_t nRow ) const;
- basegfx::B2DRange GetCellRange( size_t nCellIndex ) const;
+ Returns total output range of merged ranges, if bExpandMerged is true. */
+ basegfx::B2DRange GetCellRange( size_t nCol, size_t nRow, bool bExpandMerged ) const;
// mirroring --------------------------------------------------------------
@@ -312,9 +311,6 @@ public:
/** Draws the part of the array, that is inside the clipping range. */
drawinglayer::primitive2d::Primitive2DContainer CreateB2DPrimitiveArray() const;
- // fill the Cell::maCellIndex entries to allow referencing back from Cell to Array Col/Row coordinates
- void AddCellIndices() const;
-
private:
std::unique_ptr<ArrayImpl> mxImpl;
};
diff --git a/sc/source/ui/inc/output.hxx b/sc/source/ui/inc/output.hxx
index 2237b7daa560..8165bfda86d0 100644
--- a/sc/source/ui/inc/output.hxx
+++ b/sc/source/ui/inc/output.hxx
@@ -252,6 +252,11 @@ private:
bool AdjustAreaParamClipRect(OutputAreaParam& rAreaParam);
+ // Check for and set cell rotations at OutputData to have it available
+ // in the svx tooling to render the borders. Moved to private section
+ // and the single call to end of constructor to be sure this always happens
+ void SetCellRotations();
+
public:
/**
* @param nNewScrX: X-Offset in the output device for the table
@@ -308,8 +313,6 @@ public:
// with logic MapMode set!
void DrawEdit(bool bPixelToLogic);
-
- void SetCellRotations();
void DrawRotated(bool bPixelToLogic); // logical
void DrawClear();
diff --git a/sc/source/ui/miscdlgs/autofmt.cxx b/sc/source/ui/miscdlgs/autofmt.cxx
index e5276b3f8803..399edd9b25b6 100644
--- a/sc/source/ui/miscdlgs/autofmt.cxx
+++ b/sc/source/ui/miscdlgs/autofmt.cxx
@@ -250,7 +250,7 @@ void ScAutoFmtPreview::DrawString(vcl::RenderContext& rRenderContext, size_t nCo
Size aStrSize;
sal_uInt16 nFmtIndex = GetFormatIndex( nCol, nRow );
- const basegfx::B2DRange cellRange(maArray.GetCellRange( nCol, nRow ));
+ const basegfx::B2DRange cellRange(maArray.GetCellRange( nCol, nRow, true ));
Point aPos = Point(basegfx::fround(cellRange.getMinX()), basegfx::fround(cellRange.getMinY()));
sal_uInt16 nRightX = 0;
bool bJustify = pCurData->GetIncludeJustify();
@@ -374,7 +374,7 @@ void ScAutoFmtPreview::DrawBackground(vcl::RenderContext& rRenderContext)
rRenderContext.SetLineColor();
rRenderContext.SetFillColor( pItem->GetColor() );
- const basegfx::B2DRange aCellRange(maArray.GetCellRange( nCol, nRow ));
+ const basegfx::B2DRange aCellRange(maArray.GetCellRange( nCol, nRow, true ));
rRenderContext.DrawRect(
tools::Rectangle(
basegfx::fround(aCellRange.getMinX()), basegfx::fround(aCellRange.getMinY()),
diff --git a/sc/source/ui/view/gridwin4.cxx b/sc/source/ui/view/gridwin4.cxx
index 9387c1e6d79c..92b0eee6cc96 100644
--- a/sc/source/ui/view/gridwin4.cxx
+++ b/sc/source/ui/view/gridwin4.cxx
@@ -696,10 +696,6 @@ void ScGridWindow::DrawContent(OutputDevice &rDevice, const ScTableInfo& rTableI
pContentDev->SetMapMode(aCurrentMapMode);
}
- // check for and set cell rotations at OutputData to have it available
- // in the svx tooling to render the borders
- aOutputData.SetCellRotations();
-
if ( rDoc.HasBackgroundDraw( nTab, aDrawingRectLogic ) )
{
pContentDev->SetMapMode(MapMode(MapUnit::MapPixel));
diff --git a/sc/source/ui/view/output.cxx b/sc/source/ui/view/output.cxx
index 6cfa4c2861b1..6e0fa1a77e5c 100644
--- a/sc/source/ui/view/output.cxx
+++ b/sc/source/ui/view/output.cxx
@@ -214,6 +214,9 @@ ScOutputData::ScOutputData( OutputDevice* pNewDev, ScOutputType eNewType,
bTabProtected = mpDoc->IsTabProtected( nTab );
bLayoutRTL = mpDoc->IsLayoutRTL( nTab );
+
+ // always needed, so call at the end of the constructor
+ SetCellRotations();
}
ScOutputData::~ScOutputData()
diff --git a/svx/Library_svx.mk b/svx/Library_svx.mk
index 6bdbadaf2e3b..ad1b1dc3a423 100644
--- a/svx/Library_svx.mk
+++ b/svx/Library_svx.mk
@@ -128,7 +128,6 @@ $(eval $(call gb_Library_add_exception_objects,svx,\
svx/source/dialog/fntctrl \
svx/source/dialog/fontlb \
svx/source/dialog/fontwork \
- svx/source/dialog/framelinkarray \
svx/source/dialog/frmdirlbox \
svx/source/dialog/frmsel \
svx/source/dialog/graphctl \
diff --git a/svx/Library_svxcore.mk b/svx/Library_svxcore.mk
index 5bfbf899034d..603860d7f11b 100644
--- a/svx/Library_svxcore.mk
+++ b/svx/Library_svxcore.mk
@@ -116,6 +116,7 @@ $(eval $(call gb_Library_add_exception_objects,svxcore,\
svx/source/dialog/dlgutil \
svx/source/dialog/hexcolorcontrol \
svx/source/dialog/framelink \
+ svx/source/dialog/framelinkarray \
svx/source/dialog/langbox \
svx/source/dialog/pagenumberlistbox \
svx/source/dialog/papersizelistbox \
diff --git a/svx/source/dialog/framelink.cxx b/svx/source/dialog/framelink.cxx
index e86e6f1b3e34..8c087157d287 100644
--- a/svx/source/dialog/framelink.cxx
+++ b/svx/source/dialog/framelink.cxx
@@ -51,14 +51,12 @@ void Style::implEnsureImplStyle()
}
Style::Style() :
- maImplStyle(),
- mpUsingCell(nullptr)
+ maImplStyle()
{
}
Style::Style( double nP, double nD, double nS, SvxBorderLineStyle nType, double fScale ) :
- maImplStyle(new implStyle()),
- mpUsingCell(nullptr)
+ maImplStyle(new implStyle())
{
maImplStyle->mnType = nType;
maImplStyle->mfPatternScale = fScale;
@@ -66,8 +64,7 @@ Style::Style( double nP, double nD, double nS, SvxBorderLineStyle nType, double
}
Style::Style( const Color& rColorPrim, const Color& rColorSecn, const Color& rColorGap, bool bUseGapColor, double nP, double nD, double nS, SvxBorderLineStyle nType, double fScale ) :
- maImplStyle(new implStyle()),
- mpUsingCell(nullptr)
+ maImplStyle(new implStyle())
{
maImplStyle->mnType = nType;
maImplStyle->mfPatternScale = fScale;
@@ -75,8 +72,7 @@ Style::Style( const Color& rColorPrim, const Color& rColorSecn, const Color& rCo
}
Style::Style( const editeng::SvxBorderLine* pBorder, double fScale ) :
- maImplStyle(),
- mpUsingCell(nullptr)
+ maImplStyle()
{
if(nullptr != pBorder)
{
diff --git a/svx/source/dialog/framelinkarray.cxx b/svx/source/dialog/framelinkarray.cxx
index c9273c41344f..7cd4b26027dc 100644
--- a/svx/source/dialog/framelinkarray.cxx
+++ b/svx/source/dialog/framelinkarray.cxx
@@ -21,6 +21,7 @@
#include <math.h>
#include <vector>
+#include <set>
#include <algorithm>
#include <vcl/outdev.hxx>
#include <drawinglayer/primitive2d/borderlineprimitive2d.hxx>
@@ -45,10 +46,8 @@ public:
long mnAddTop;
long mnAddBottom;
- SvxRotateMode meRotMode;
- double mfOrientation;
- basegfx::B2DHomMatrix maCoordinateSystem;
- size_t maCellIndex;
+ SvxRotateMode meRotMode;
+ double mfOrientation;
bool mbMergeOrig;
bool mbOverlapX;
@@ -57,12 +56,12 @@ public:
public:
explicit Cell();
- void SetStyleLeft(const Style& rStyle) { maLeft = rStyle; maLeft.SetUsingCell(this); }
- void SetStyleRight(const Style& rStyle) { maRight = rStyle; maRight.SetUsingCell(this); }
- void SetStyleTop(const Style& rStyle) { maTop = rStyle; maTop.SetUsingCell(this); }
- void SetStyleBottom(const Style& rStyle) { maBottom = rStyle; maBottom.SetUsingCell(this); }
- void SetStyleTLBR(const Style& rStyle) { maTLBR = rStyle; maTLBR.SetUsingCell(this); }
- void SetStyleBLTR(const Style& rStyle) { maBLTR = rStyle; maBLTR.SetUsingCell(this); }
+ void SetStyleLeft(const Style& rStyle) { maLeft = rStyle; }
+ void SetStyleRight(const Style& rStyle) { maRight = rStyle; }
+ void SetStyleTop(const Style& rStyle) { maTop = rStyle; }
+ void SetStyleBottom(const Style& rStyle) { maBottom = rStyle; }
+ void SetStyleTLBR(const Style& rStyle) { maTLBR = rStyle; }
+ void SetStyleBLTR(const Style& rStyle) { maBLTR = rStyle; }
const Style& GetStyleLeft() const { return maLeft; }
const Style& GetStyleRight() const { return maRight; }
@@ -76,74 +75,54 @@ public:
void MirrorSelfX();
- basegfx::B2DHomMatrix CreateCoordinateSystem(const Array& rArray) const;
- size_t GetCellIndex(const Array& rArray) const;
+ basegfx::B2DHomMatrix CreateCoordinateSystem(const Array& rArray, size_t nCol, size_t nRow, bool bExpandMerged) const;
};
typedef std::vector< long > LongVec;
typedef std::vector< Cell > CellVec;
-size_t Cell::GetCellIndex(const Array& rArray) const
+basegfx::B2DHomMatrix Cell::CreateCoordinateSystem(const Array& rArray, size_t nCol, size_t nRow, bool bExpandMerged) const
{
- if(static_cast<size_t>(-1) == maCellIndex)
- {
- rArray.AddCellIndices();
- }
-
- return maCellIndex;
-}
+ basegfx::B2DHomMatrix aRetval;
+ const basegfx::B2DRange aRange(rArray.GetCellRange(nCol, nRow, bExpandMerged));
-basegfx::B2DHomMatrix Cell::CreateCoordinateSystem(const Array& rArray) const
-{
- if(!maCoordinateSystem.isIdentity())
+ if(!aRange.isEmpty())
{
- return maCoordinateSystem;
- }
+ basegfx::B2DPoint aOrigin(aRange.getMinimum());
+ basegfx::B2DVector aX(aRange.getWidth(), 0.0);
+ basegfx::B2DVector aY(0.0, aRange.getHeight());
- const size_t nCellIndex(GetCellIndex(rArray));
-
- if(static_cast<size_t>(-1) != nCellIndex)
- {
- const basegfx::B2DRange aRange(rArray.GetCellRange(nCellIndex));
-
- if(!aRange.isEmpty())
+ if (IsRotated() && SvxRotateMode::SVX_ROTATE_MODE_STANDARD != meRotMode)
{
- basegfx::B2DPoint aOrigin(aRange.getMinimum());
- basegfx::B2DVector aX(aRange.getWidth(), 0.0);
- basegfx::B2DVector aY(0.0, aRange.getHeight());
+ // when rotated, adapt values. Get Skew (cos/sin == 1/tan)
+ const double fSkew(aY.getY() * (cos(mfOrientation) / sin(mfOrientation)));
- if (IsRotated() && SvxRotateMode::SVX_ROTATE_MODE_STANDARD != meRotMode)
+ switch (meRotMode)
{
- // when rotated, adapt values. Get Skew (cos/sin == 1/tan)
- const double fSkew(aY.getY() * (cos(mfOrientation) / sin(mfOrientation)));
-
- switch (meRotMode)
- {
- case SvxRotateMode::SVX_ROTATE_MODE_TOP:
- // shear Y-Axis
- aY.setX(-fSkew);
- break;
- case SvxRotateMode::SVX_ROTATE_MODE_CENTER:
- // shear origin half, Y full
- aOrigin.setX(aOrigin.getX() + (fSkew * 0.5));
- aY.setX(-fSkew);
- break;
- case SvxRotateMode::SVX_ROTATE_MODE_BOTTOM:
- // shear origin full, Y full
- aOrigin.setX(aOrigin.getX() + fSkew);
- aY.setX(-fSkew);
- break;
- default: // SvxRotateMode::SVX_ROTATE_MODE_STANDARD, already excluded above
- break;
- }
+ case SvxRotateMode::SVX_ROTATE_MODE_TOP:
+ // shear Y-Axis
+ aY.setX(-fSkew);
+ break;
+ case SvxRotateMode::SVX_ROTATE_MODE_CENTER:
+ // shear origin half, Y full
+ aOrigin.setX(aOrigin.getX() + (fSkew * 0.5));
+ aY.setX(-fSkew);
+ break;
+ case SvxRotateMode::SVX_ROTATE_MODE_BOTTOM:
+ // shear origin full, Y full
+ aOrigin.setX(aOrigin.getX() + fSkew);
+ aY.setX(-fSkew);
+ break;
+ default: // SvxRotateMode::SVX_ROTATE_MODE_STANDARD, already excluded above
+ break;
}
-
- // use column vectors as coordinate axes, homogen column for translation
- const_cast<Cell*>(this)->maCoordinateSystem = basegfx::utils::createCoordinateSystemTransform(aOrigin, aX, aY);
}
+
+ // use column vectors as coordinate axes, homogen column for translation
+ aRetval = basegfx::utils::createCoordinateSystemTransform(aOrigin, aX, aY);
}
- return maCoordinateSystem;
+ return aRetval;
}
Cell::Cell() :
@@ -153,8 +132,6 @@ Cell::Cell() :
mnAddBottom( 0 ),
meRotMode(SvxRotateMode::SVX_ROTATE_MODE_STANDARD ),
mfOrientation( 0.0 ),
- maCoordinateSystem(),
- maCellIndex(static_cast<size_t>(-1)),
mbMergeOrig( false ),
mbOverlapX( false ),
mbOverlapY( false )
@@ -168,8 +145,6 @@ void Cell::MirrorSelfX()
maLeft.MirrorSelf();
maRight.MirrorSelf();
mfOrientation = -mfOrientation;
- maCoordinateSystem.identity();
- maCellIndex = static_cast<size_t>(-1);
}
@@ -864,31 +839,46 @@ long Array::GetHeight() const
return GetRowPosition( mxImpl->mnHeight ) - GetRowPosition( 0 );
}
-basegfx::B2DRange Array::GetCellRange( size_t nCellIndex ) const
+basegfx::B2DRange Array::GetCellRange( size_t nCol, size_t nRow, bool bExpandMerged ) const
{
- return GetCellRange(nCellIndex % GetColCount(), nCellIndex / GetColCount());
-}
-
-basegfx::B2DRange Array::GetCellRange( size_t nCol, size_t nRow ) const
-{
- size_t nFirstCol = mxImpl->GetMergedFirstCol( nCol, nRow );
- size_t nFirstRow = mxImpl->GetMergedFirstRow( nCol, nRow );
- size_t nLastCol = mxImpl->GetMergedLastCol( nCol, nRow );
- size_t nLastRow = mxImpl->GetMergedLastRow( nCol, nRow );
- const Point aPoint( GetColPosition( nFirstCol ), GetRowPosition( nFirstRow ) );
- const Size aSize( GetColWidth( nFirstCol, nLastCol ) + 1, GetRowHeight( nFirstRow, nLastRow ) + 1 );
- tools::Rectangle aRect(aPoint, aSize);
+ if(bExpandMerged)
+ {
+ // get the Range of the fully expanded cell (if merged)
+ const size_t nFirstCol(mxImpl->GetMergedFirstCol( nCol, nRow ));
+ const size_t nFirstRow(mxImpl->GetMergedFirstRow( nCol, nRow ));
+ const size_t nLastCol(mxImpl->GetMergedLastCol( nCol, nRow ));
+ const size_t nLastRow(mxImpl->GetMergedLastRow( nCol, nRow ));
+ const Point aPoint( GetColPosition( nFirstCol ), GetRowPosition( nFirstRow ) );
+ const Size aSize( GetColWidth( nFirstCol, nLastCol ) + 1, GetRowHeight( nFirstRow, nLastRow ) + 1 );
+ tools::Rectangle aRect(aPoint, aSize);
+
+ // adjust rectangle for partly visible merged cells
+ const Cell& rCell = CELL( nCol, nRow );
+
+ if( rCell.IsMerged() )
+ {
+ // not *sure* what exactly this is good for,
+ // it is just a hard set extension at merged cells,
+ // probably *should* be included in the above extended
+ // GetColPosition/GetColWidth already. This might be
+ // added due to GetColPosition/GetColWidth not working
+ // correcly over PageChanges (if used), but not sure.
+ aRect.Left() -= rCell.mnAddLeft;
+ aRect.Right() += rCell.mnAddRight;
+ aRect.Top() -= rCell.mnAddTop;
+ aRect.Bottom() += rCell.mnAddBottom;
+ }
- // adjust rectangle for partly visible merged cells
- const Cell& rCell = CELL( nCol, nRow );
- if( rCell.IsMerged() )
+ return basegfx::B2DRange(aRect.Left(), aRect.Top(), aRect.Right(), aRect.Bottom());
+ }
+ else
{
- aRect.Left() -= rCell.mnAddLeft;
- aRect.Right() += rCell.mnAddRight;
- aRect.Top() -= rCell.mnAddTop;
- aRect.Bottom() += rCell.mnAddBottom;
+ const Point aPoint( GetColPosition( nCol ), GetRowPosition( nRow ) );
+ const Size aSize( GetColWidth( nCol, nCol ) + 1, GetRowHeight( nRow, nRow ) + 1 );
+ const tools::Rectangle aRect(aPoint, aSize);
+
+ return basegfx::B2DRange(aRect.Left(), aRect.Top(), aRect.Right(), aRect.Bottom());
}
- return basegfx::B2DRange(aRect.Left(), aRect.Top(), aRect.Right(), aRect.Bottom());
}
// mirroring
@@ -1023,45 +1013,6 @@ void HelperCreateVerticalEntry(
);
}
-void HelperCreateEntry(const Array& rArray, const Style& rStyle, drawinglayer::primitive2d::Primitive2DContainer& rSequence, const Color* pForceColor)
-{
- const Cell* pCell = rStyle.GetUsingCell();
-
- if(nullptr != pCell)
- {
- const size_t nCellIndex(pCell->GetCellIndex(rArray));
-
- if(static_cast<size_t>(-1) != nCellIndex)
- {
- size_t col(nCellIndex % rArray.GetColCount());
- size_t row(nCellIndex / rArray.GetColCount());
- const bool bL(&rStyle == &pCell->GetStyleLeft());
- const bool bR(&rStyle == &pCell->GetStyleRight());
- const bool bT(&rStyle == &pCell->GetStyleTop());
- const bool bB(&rStyle == &pCell->GetStyleBottom());
-
- if(bL || bR || bT || bB)
- {
- const basegfx::B2DHomMatrix aCoordinateSystem(pCell->CreateCoordinateSystem(rArray));
- const basegfx::B2DVector aX(basegfx::utils::getColumn(aCoordinateSystem, 0));
- const basegfx::B2DVector aY(basegfx::utils::getColumn(aCoordinateSystem, 1));
- const basegfx::B2DPoint aOrigin(basegfx::utils::getColumn(aCoordinateSystem, 2));
-
- if(bL || bR)
- {
- // left/right
- HelperCreateVerticalEntry(rArray, rStyle, bL ? col : col + 1, row, aOrigin, aX, aY, rSequence, bL, pForceColor);
- }
- else if(bT || bB)
- {
- // top/bottom
- HelperCreateHorizontalEntry(rArray, rStyle, col, bT ? row : row + 1, aOrigin, aX, aY, rSequence, bT, pForceColor);
- }
- }
- }
- }
-}
-
void HelperMergeInB2DPrimitiveArray(
const drawinglayer::primitive2d::Primitive2DContainer& rSource,
drawinglayer::primitive2d::Primitive2DContainer& rTarget)
@@ -1111,28 +1062,51 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange(
DBG_FRAME_CHECK_COLROW( nFirstCol, nFirstRow, "CreateB2DPrimitiveRange" );
DBG_FRAME_CHECK_COLROW( nLastCol, nLastRow, "CreateB2DPrimitiveRange" );
+ // It may be necessary to extend the loop ranges by one cell to the outside,
+ // when possible. This is needed e.g. when there is in Calc a Cell with an
+ // upper CellBorder using DoubleLine and that is right/left connected upwards
+ // to also DoubleLine. These upper DoubleLines will be extended to meet the
+ // lower of the upper CellBorder and thus have graphical parts that are
+ // displayed one cell below and right/left of the target cell - analog to
+ // other examples in all other directions.
+ // It would be possible to explicitely test this (if possible by indices at all)
+ // looping and testing the styles in the outer cells to detect this, but since
+ // for other usages (e.g. UI) usually nFirstRow==0 and nLastRow==GetRowCount()-1
+ // (and analog for Col) it is okay to just expand the range when available.
+ // Do *not* change nFirstRow/nLastRow due to these needed to the boolean tests
+ // below (!)
+ // Checked usages, this method is used in Calc EditView/Print/Export stuff and
+ // in UI (Dialog), not for Writer Tables and Draw/Impress tables. All usages
+ // seem okay with this change, so I will add it.
+ const size_t nStartRow(nFirstRow > 0 ? nFirstRow - 1 : nFirstRow);
+ const size_t nEndRow(nLastRow < GetRowCount() - 1 ? nLastRow + 1 : nLastRow);
+ const size_t nStartCol(nFirstCol > 0 ? nFirstCol - 1 : nFirstCol);
+ const size_t nEndCol(nLastCol < GetColCount() - 1 ? nLastCol + 1 : nLastCol);
+
// various primitive sequences to collect the different border types
drawinglayer::primitive2d::Primitive2DContainer aHorizontalSequence;
- std::vector< drawinglayer::primitive2d::Primitive2DContainer > aVerticalSequences(nLastCol - nFirstCol + 1);
+ std::vector< drawinglayer::primitive2d::Primitive2DContainer > aVerticalSequences(nEndCol - nStartCol + 1);
drawinglayer::primitive2d::Primitive2DContainer aCrossSequence;
- for (size_t nRow = nFirstRow; nRow <= nLastRow; ++nRow)
+ // remember for which merged cells crossed lines were already created. To
+ // do so, hold the size_t cell index in a set for fast check
+ std::set< size_t > aMergedCells;
+
+ for (size_t nRow(nStartRow); nRow <= nEndRow; ++nRow)
{
- for (size_t nCol = nFirstCol; nCol <= nLastCol; ++nCol)
+ for (size_t nCol(nStartCol); nCol <= nEndCol; ++nCol)
{
- const Cell& rCell = CELL(nCol, nRow);
- const basegfx::B2DHomMatrix aCoordinateSystem(rCell.CreateCoordinateSystem(*this));
- const basegfx::B2DVector aX(basegfx::utils::getColumn(aCoordinateSystem, 0));
- const basegfx::B2DVector aY(basegfx::utils::getColumn(aCoordinateSystem, 1));
+ // get Cell and CoordinateSystem (*only* for this Cell, do *not* expand for
+ // merged cells (!)), check if used (non-empty vectors)
+ const Cell& rCell(CELL(nCol, nRow));
+ basegfx::B2DHomMatrix aCoordinateSystem(rCell.CreateCoordinateSystem(*this, nCol, nRow, false));
+ basegfx::B2DVector aX(basegfx::utils::getColumn(aCoordinateSystem, 0));
+ basegfx::B2DVector aY(basegfx::utils::getColumn(aCoordinateSystem, 1));
if(!aX.equalZero() && !aY.equalZero())
{
- size_t _nFirstCol = mxImpl->GetMergedFirstCol(nCol, nRow);
- size_t _nFirstRow = mxImpl->GetMergedFirstRow(nCol, nRow);
- size_t _nLastCol = mxImpl->GetMergedLastCol(nCol, nRow);
- size_t _nLastRow = mxImpl->GetMergedLastRow(nCol, nRow);
- const basegfx::B2DPoint aOrigin(basegfx::utils::getColumn(aCoordinateSystem, 2));
-
+ // get needed local values
+ basegfx::B2DPoint aOrigin(basegfx::utils::getColumn(aCoordinateSystem, 2));
const bool bOverlapX(rCell.mbOverlapX);
const bool bOverlapY(rCell.mbOverlapY);
const bool bFirstCol(nCol == nFirstCol);
@@ -1140,116 +1114,170 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange(
const bool bFirstRow(nRow == nFirstRow);
const bool bLastRow(nRow == nLastRow);
- if (!bOverlapX || bFirstRow)
+ // handle rotation: If cell is rotated, handle lower/right edge inside
+ // this local geometry due to the created CoordinateSystem already representing
+ // the needed transformations.
+ const bool bRotated(rCell.IsRotated());
+
+ // Additionally avoid double-handling by supressing handling when self not roated,
+ // but above/left is rotated and thus already handled. Two directly connected
+ // rotated will paint/create both edges, they might be rotated differently.
+ const bool bSuppressAbove(!bRotated && nRow > nFirstRow && CELL(nCol, nRow - 1).IsRotated());
+ const bool bSupressLeft(!bRotated && nCol > nFirstCol && CELL(nCol - 1, nRow).IsRotated());
+
+ // create upper line for this Cell
+ if ((!bOverlapY // true for first line in merged cells or cells
+ || bFirstRow) // true for non_Calc usages of this tooling
+ && !bSuppressAbove) // true when above is not rotated, so edge is already handled (see bRotated)
{
- const Style& rTop = GetCellStyleTop(_nFirstCol, _nFirstRow);
+ // get CellStyle - method will take care to get the correct one, e.g.
+ // for merged cells (it uses ORIGCELL that works with topLeft's of these)
+ const Style& rTop(GetCellStyleTop(nCol, nRow));
if(rTop.IsUsed())
{
- HelperCreateEntry(*this, rTop, aHorizontalSequence, pForceColor);
+ HelperCreateHorizontalEntry(*this, rTop, nCol, nRow, aOrigin, aX, aY, aHorizontalSequence, true, pForceColor);
}
}
- if (bLastRow)
+ // create lower line for this Cell
+ if (bLastRow // true for non_Calc usages of this tooling
+ || bRotated) // true if cell is rotated, handle lower edge in local geometry
{
- const Style& rBottom = GetCellStyleBottom(_nFirstCol, _nFirstRow);
+ const Style& rBottom(GetCellStyleBottom(nCol, nRow));
if(rBottom.IsUsed())
{
- HelperCreateEntry(*this, rBottom, aHorizontalSequence, pForceColor);
+ HelperCreateHorizontalEntry(*this, rBottom, nCol, nRow + 1, aOrigin, aX, aY, aHorizontalSequence, false, pForceColor);
}
}
- if (!bOverlapY || bFirstCol)
+ // create left line for this Cell
+ if ((!bOverlapX // true for first column in merged cells or cells
+ || bFirstCol) // true for non_Calc usages of this tooling
+ && !bSupressLeft) // true when left is not rotated, so edge is already handled (see bRotated)
{
- const Style& rLeft(GetCellStyleLeft(_nFirstCol, _nFirstRow));
+ const Style& rLeft(GetCellStyleLeft(nCol, nRow));
if(rLeft.IsUsed())
{
- HelperCreateEntry(*this, rLeft, aVerticalSequences[nCol - nFirstCol], pForceColor);
+ HelperCreateVerticalEntry(*this, rLeft, nCol, nRow, aOrigin, aX, aY, aVerticalSequences[nCol - nStartCol], true, pForceColor);
}
}
- if (bLastCol)
+ // create right line for this Cell
+ if (bLastCol // true for non_Calc usages of this tooling
+ || bRotated) // true if cell is rotated, handle right edge in local geometry
{
- const Style& rRight(GetCellStyleRight(_nFirstCol, _nFirstRow));
+ const Style& rRight(GetCellStyleRight(nCol, nRow));
if(rRight.IsUsed())
{
- HelperCreateEntry(*this, rRight, aVerticalSequences[nCol - nFirstCol], pForceColor);
+ HelperCreateVerticalEntry(*this, rRight, nCol + 1, nRow, aOrigin, aX, aY, aVerticalSequences[nCol - nStartCol], false, pForceColor);
}
}
- if ((!bOverlapX && !bOverlapY) || (bFirstCol && bFirstRow) || (!bOverlapY && bFirstCol) || (!bOverlapX && bFirstRow))
+ // check for crossed lines, these need special treatment, especially
+ // for merged cells, see below
+ const Style& rTLBR(GetCellStyleTLBR(nCol, nRow));
+ const Style& rBLTR(GetCellStyleBLTR(nCol, nRow));
+
+ if(rTLBR.IsUsed() || rBLTR.IsUsed())
{
- const Style& rTLBR = GetCellStyleTLBR(_nFirstCol, _nFirstRow);
- if(rTLBR.IsUsed())
+ bool bContinue(true);
+
+ if(rCell.IsMerged())
{
- /// top-left and bottom-right Style Tables
- /// Fill top-left Style Table
- const Style& rTLFromRight(GetCellStyleTop(_nFirstCol, _nFirstRow));
- const Style& rTLFromBottom(GetCellStyleLeft(_nFirstCol, _nFirstRow));
- StyleVectorTable aStart;
- const basegfx::B2DVector aAxisA(aX + aY);
-
- aStart.add(rTLFromRight, aAxisA, aX, false);
- aStart.add(rTLFromBottom, aAxisA, aY, false);
- aStart.sort();
-
- /// Fill bottom-right Style Table
- const Style& rBRFromBottom(GetCellStyleRight(_nLastCol, _nLastRow));
- const Style& rBRFromLeft(GetCellStyleBottom(_nLastCol, _nLastRow));
- StyleVectorTable aEnd;
- const basegfx::B2DVector aAxisB(-aX -aY);
-
- aEnd.add(rBRFromBottom, aAxisB, -aY, true);
- aEnd.add(rBRFromLeft, aAxisB, -aX, true);
- aEnd.sort();
-
- CreateBorderPrimitives(
- aCrossSequence,
- aOrigin,
- aX + aY,
- rTLBR,
- aStart,
- aEnd,
- pForceColor
- );
+ // first check if this merged cell was already handled. To do so,
+ // calculate and use the index of the TopLeft cell
+ const size_t _nMergedFirstCol(mxImpl->GetMergedFirstCol(nCol, nRow));
+ const size_t _nMergedFirstRow(mxImpl->GetMergedFirstRow(nCol, nRow));
+ const size_t nIndexOfMergedCell(mxImpl->GetIndex(_nMergedFirstCol, _nMergedFirstRow));
+ bContinue = (aMergedCells.end() == aMergedCells.find(nIndexOfMergedCell));
+
+ if(bContinue)
+ {
+ // not found, add now to mark as handled
+ aMergedCells.insert(nIndexOfMergedCell);
+
+ // when merged, get extended coordinate system and derived values
+ // for the full range of this merged cell
+ aCoordinateSystem = rCell.CreateCoordinateSystem(*this, nCol, nRow, true);
+ aX = basegfx::utils::getColumn(aCoordinateSystem, 0);
+ aY = basegfx::utils::getColumn(aCoordinateSystem, 1);
+ aOrigin = basegfx::utils::getColumn(aCoordinateSystem, 2);
+ }
}
- const Style& rBLTR = GetCellStyleBLTR(_nFirstCol, _nFirstRow);
- if(rBLTR.IsUsed())
+ if(bContinue)
{
- /// bottom-left and top-right Style Tables
- /// Fill bottom-left Style Table
- const Style& rBLFromTop(GetCellStyleLeft(_nFirstCol, _nLastRow));
- const Style& rBLFromBottom(GetCellStyleBottom(_nFirstCol, _nLastRow));
- StyleVectorTable aStart;
- const basegfx::B2DVector aAxisA(aX - aY);
-
- aStart.add(rBLFromTop, aAxisA, -aY, true);
- aStart.add(rBLFromBottom, aAxisA, aX, false);
- aStart.sort();
-
- /// Fill top-right Style Table
- const Style& rTRFromLeft(GetCellStyleTop(_nLastCol, _nFirstRow));
- const Style& rTRFromBottom(GetCellStyleRight(_nLastCol, _nFirstRow));
- StyleVectorTable aEnd;
- const basegfx::B2DVector aAxisB(aY - aX);
-
- aEnd.add(rTRFromLeft, aAxisB, -aX, true);
- aEnd.add(rTRFromBottom, aAxisB, aY, false);
- aEnd.sort();
-
- CreateBorderPrimitives(
- aCrossSequence,
- aOrigin + aY,
- aX - aY,
- rBLTR,
- aStart,
- aEnd,
- pForceColor
- );
+ if(rTLBR.IsUsed())
+ {
+ /// top-left and bottom-right Style Tables
+ /// Fill top-left Style Table
+ const Style& rTLFromRight(GetCellStyleTop(nCol, nRow));
+ const Style& rTLFromBottom(GetCellStyleLeft(nCol, nRow));
+ StyleVectorTable aStart;
+ const basegfx::B2DVector aAxisA(aX + aY);
+
+ aStart.add(rTLFromRight, aAxisA, aX, false);
+ aStart.add(rTLFromBottom, aAxisA, aY, false);
+ aStart.sort();
+
+ /// Fill bottom-right Style Table
+ const Style& rBRFromBottom(GetCellStyleRight(nCol, nRow));
+ const Style& rBRFromLeft(GetCellStyleBottom(nCol, nRow));
+ StyleVectorTable aEnd;
+ const basegfx::B2DVector aAxisB(-aX -aY);
+
+ aEnd.add(rBRFromBottom, aAxisB, -aY, true);
+ aEnd.add(rBRFromLeft, aAxisB, -aX, true);
+ aEnd.sort();
+
+ CreateBorderPrimitives(
+ aCrossSequence,
+ aOrigin,
+ aX + aY,
+ rTLBR,
+ aStart,
+ aEnd,
+ pForceColor
+ );
+ }
+
+ if(rBLTR.IsUsed())
+ {
+ /// bottom-left and top-right Style Tables
+ /// Fill bottom-left Style Table
+ const Style& rBLFromTop(GetCellStyleLeft(nCol, nRow));
+ const Style& rBLFromBottom(GetCellStyleBottom(nCol, nRow));
+ StyleVectorTable aStart;
+ const basegfx::B2DVector aAxisA(aX - aY);
+
+ aStart.add(rBLFromTop, aAxisA, -aY, true);
+ aStart.add(rBLFromBottom, aAxisA, aX, false);
+ aStart.sort();
+
+ /// Fill top-right Style Table
+ const Style& rTRFromLeft(GetCellStyleTop(nCol, nRow));
+ const Style& rTRFromBottom(GetCellStyleRight(nCol, nRow));
+ StyleVectorTable aEnd;
+ const basegfx::B2DVector aAxisB(aY - aX);
+
+ aEnd.add(rTRFromLeft, aAxisB, -aX, true);
+ aEnd.add(rTRFromBottom, aAxisB, aY, false);
+ aEnd.sort();
+
+ CreateBorderPrimitives(
+ aCrossSequence,
+ aOrigin + aY,
+ aX - aY,
+ rBLTR,
+ aStart,
+ aEnd,
+ pForceColor
+ );
+ }
}
}
}
@@ -1259,6 +1287,7 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange(
// to stay compatible, create order as it was formally. Also try to
// merge primitives as far as possible
HelperMergeInB2DPrimitiveArray(aHorizontalSequence, aCrossSequence);
+
for(const auto& aVert : aVerticalSequences)
{
HelperMergeInB2DPrimitiveArray(aVert, aCrossSequence);
@@ -1279,19 +1308,9 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveArray()
return aPrimitives;
}
-void Array::AddCellIndices() const
-{
- for (size_t a(0); a < mxImpl->maCells.size(); a++)
- {
- const_cast<Array*>(this)->mxImpl->maCells[a].maCellIndex = a;
- }
-}
-
#undef ORIGCELL
#undef CELLACC
#undef CELL
-
-
#undef DBG_FRAME_CHECK_ROW_1
#undef DBG_FRAME_CHECK_COL_1
#undef DBG_FRAME_CHECK_COLROW
@@ -1299,7 +1318,6 @@ void Array::AddCellIndices() const
#undef DBG_FRAME_CHECK_COL
#undef DBG_FRAME_CHECK
-
}
}
diff --git a/svx/source/dialog/frmsel.cxx b/svx/source/dialog/frmsel.cxx
index e3a6b6a9f8ba..fd858605e32c 100644
--- a/svx/source/dialog/frmsel.cxx
+++ b/svx/source/dialog/frmsel.cxx
@@ -410,7 +410,7 @@ void FrameSelectorImpl::InitBorderGeometry()
{
for( nRow = 0, nRows = maArray.GetRowCount(); nRow < nRows; ++nRow )
{
- const basegfx::B2DRange aCellRange(maArray.GetCellRange( nCol, nRow ));
+ const basegfx::B2DRange aCellRange(maArray.GetCellRange( nCol, nRow, true ));
const tools::Rectangle aRect(
basegfx::fround(aCellRange.getMinX()), basegfx::fround(aCellRange.getMinY()),
basegfx::fround(aCellRange.getMaxX()), basegfx::fround(aCellRange.getMaxY()));
@@ -469,7 +469,7 @@ void FrameSelectorImpl::InitBorderGeometry()
for( nRow = 0, nRows = maArray.GetRowCount(); nRow < nRows; ++nRow )
{
// the usable area between horizonal/vertical frame borders of current quadrant
- const basegfx::B2DRange aCellRange(maArray.GetCellRange( nCol, nRow ));
+ const basegfx::B2DRange aCellRange(maArray.GetCellRange( nCol, nRow, true ));
const tools::Rectangle aRect(
basegfx::fround(aCellRange.getMinX()) + nClV + 1, basegfx::fround(aCellRange.getMinY()) + nClH + 1,
basegfx::fround(aCellRange.getMaxX()) - nClV + 1, basegfx::fround(aCellRange.getMaxY()) - nClH + 1);
diff --git a/svx/source/table/viewcontactoftableobj.cxx b/svx/source/table/viewcontactoftableobj.cxx
index 2f818e5ee7f2..b37950323fe3 100644
--- a/svx/source/table/viewcontactoftableobj.cxx
+++ b/svx/source/table/viewcontactoftableobj.cxx
@@ -36,8 +36,10 @@
#include <drawinglayer/attribute/sdrlineattribute.hxx>
#include <drawinglayer/attribute/sdrshadowattribute.hxx>
#include <drawinglayer/primitive2d/sdrdecompositiontools2d.hxx>
+#include <drawinglayer/primitive2d/transformprimitive2d.hxx>
#include <basegfx/matrix/b2dhommatrixtools.hxx>
#include <svx/framelink.hxx>
+#include <svx/framelinkarray.hxx>
#include <cell.hxx>
#include "tablelayouter.hxx"
@@ -196,42 +198,6 @@ namespace sdr
return svx::frame::Style();
}
- void createForVector(bool bHor, drawinglayer::primitive2d::Primitive2DContainer& rContainer, const basegfx::B2DPoint& rOrigin, const basegfx::B2DVector& rX,
- const svx::frame::Style& rLine,
- const svx::frame::Style& rLeftA, const svx::frame::Style& rLeftB, const svx::frame::Style& rLeftC,
- const svx::frame::Style& rRightA, const svx::frame::Style& rRightB, const svx::frame::Style& rRightC)
- {
- /// top-left and bottom-right Style Tables
- const basegfx::B2DVector aY(basegfx::getNormalizedPerpendicular(rX));
-
- /// Fill top-left Style Table
- svx::frame::StyleVectorTable aStart;
-
- aStart.add(rLeftA, rX, -aY, bHor); // bHor ? true : false));
- aStart.add(rLeftB, rX, -rX, true); // bHor ? true : true));
- aStart.add(rLeftC, rX, aY, !bHor); // bHor ? false : true));
- aStart.sort();
-
- /// Fill bottom-right Style Table
- svx::frame::StyleVectorTable aEnd;
- const basegfx::B2DVector aAxis(-rX);
-
- aEnd.add(rRightA, aAxis, -aY, bHor); // bHor ? true : false));
- aEnd.add(rRightB, aAxis, rX, false); // bHor ? false : false));
- aEnd.add(rRightC, aAxis, aY, !bHor); // bHor ? false : true));
- aEnd.sort();
-
- CreateBorderPrimitives(
- rContainer,
- rOrigin,
- rX,
- rLine,
- aStart,
- aEnd,
- nullptr
- );
- }
-
drawinglayer::primitive2d::Primitive2DContainer ViewContactOfTableObj::createViewIndependentPrimitive2DSequence() const
{
const sdr::table::SdrTableObj& rTableObj = static_cast<const sdr::table::SdrTableObj&>(GetSdrObject());
@@ -249,7 +215,7 @@ namespace sdr
if(nAllCount)
{
- const sdr::table::TableLayouter& rTableLayouter = rTableObj.getTableLayouter();
+ const sdr::table::TableLayouter& rTableLayouter(rTableObj.getTableLayouter());
const bool bIsRTL(css::text::WritingMode_RL_TB == rTableObj.GetWritingMode());
sdr::table::CellPos aCellPos;
sdr::table::CellRef xCurrentCell;
@@ -258,19 +224,59 @@ namespace sdr
// create range using the model data directly. This is in SdrTextObj::aRect which i will access using
// GetGeoRect() to not trigger any calculations. It's the unrotated geometry.
const tools::Rectangle& rObjectRectangle(rTableObj.GetGeoRect());
- const basegfx::B2DRange aObjectRange(rObjectRectangle.Left(), rObjectRectangle.Top(), rObjectRectangle.Right(), rObjectRectangle.Bottom());
+ const basegfx::B2DRange aObjectRange(
+ rObjectRectangle.Left(), rObjectRectangle.Top(),
+ rObjectRectangle.Right(), rObjectRectangle.Bottom());
+
+ // To create the CellBorderPrimitives, use the tolling from svx::frame::Array
+ // which is capable of creating the needed visualization. Fill it during the
+ // anyways needed run over the table.
+ svx::frame::Array aArray;
- // for each cell we need potentially a cell primitive and a border primitive
- // (e.g. single cell). Prepare sequences and input counters
- drawinglayer::primitive2d::Primitive2DContainer aBorderSequence;
+ // initialize CellBorderArray for primitive creation
+ aArray.Initialize(nColCount, nRowCount);
// create single primitives per cell
for(aCellPos.mnRow = 0; aCellPos.mnRow < nRowCount; aCellPos.mnRow++)
{
+ // add RowHeight to CellBorderArray for primitive creation
+ aArray.SetRowHeight(aCellPos.mnRow, rTableLayouter.getRowHeight(aCellPos.mnRow));
+
for(aCellPos.mnCol = 0; aCellPos.mnCol < nColCount; aCellPos.mnCol++)
{
+ // add ColWidth to CellBorderArray for primitive creation, only
+ // needs to be done in the 1st run
+ if(0 == aCellPos.mnRow)
+ {
+ aArray.SetColWidth(aCellPos.mnCol, rTableLayouter.getColumnWidth(aCellPos.mnCol));
+ }
+
+ // access the cell
xCurrentCell.set(dynamic_cast< sdr::table::Cell* >(xTable->getCellByPosition(aCellPos.mnCol, aCellPos.mnRow).get()));
+ if(xCurrentCell.is())
+ {
+ // copy styles for current cell to CellBorderArray for primitive creation
+ aArray.SetCellStyleLeft(aCellPos.mnCol, aCellPos.mnRow, impGetLineStyle(rTableLayouter, aCellPos.mnCol, aCellPos.mnRow, false, nColCount, nRowCount, bIsRTL));
+ aArray.SetCellStyleRight(aCellPos.mnCol, aCellPos.mnRow, impGetLineStyle(rTableLayouter, aCellPos.mnCol + 1, aCellPos.mnRow, false, nColCount, nRowCount, bIsRTL));
+ aArray.SetCellStyleTop(aCellPos.mnCol, aCellPos.mnRow, impGetLineStyle(rTableLayouter, aCellPos.mnCol, aCellPos.mnRow, true, nColCount, nRowCount, bIsRTL));
+ aArray.SetCellStyleBottom(aCellPos.mnCol, aCellPos.mnRow, impGetLineStyle(rTableLayouter, aCellPos.mnCol, aCellPos.mnRow + 1, true, nColCount, nRowCount, bIsRTL));
+
+ // ignore merged cells (all except the top-left of a merged cell)
+ if(!xCurrentCell->isMerged())
+ {
+ // check if we are the top-left of a merged cell
+ const sal_Int32 nXSpan(xCurrentCell->getColumnSpan());
+ const sal_Int32 nYSpan(xCurrentCell->getRowSpan());
+
+ if(nXSpan > 1 || nYSpan > 1)
+ {
+ // if merged, set so at CellBorderArray for primitive creation
+ aArray.SetMergedRange(aCellPos.mnCol, aCellPos.mnRow, aCellPos.mnCol + nXSpan - 1, aCellPos.mnRow + nYSpan - 1);
+ }
+ }
+ }
+
if(xCurrentCell.is() && !xCurrentCell->isMerged())
{
if(rTableLayouter.getCellArea(xCurrentCell, aCellPos, aCellArea))
@@ -318,77 +324,54 @@ namespace sdr
aCellMatrix, aAttribute));
aRetval.append(xCellReference);
}
-
- // handle cell borders
- const sal_Int32 nX(bIsRTL ? nColCount - aCellPos.mnCol : aCellPos.mnCol);
- const sal_Int32 nY(aCellPos.mnRow);
-
- // get access values for X,Y at the cell's end
- const sal_Int32 nXSpan(xCurrentCell->getColumnSpan());
- const sal_Int32 nYSpan(xCurrentCell->getRowSpan());
- const sal_Int32 nXRight(bIsRTL ? nX - nXSpan : nX + nXSpan);
- const sal_Int32 nYBottom(nY + nYSpan);
-
- // get basic lines
- const svx::frame::Style aLeftLine(impGetLineStyle(rTableLayouter, nX, nY, false, nColCount, nRowCount, bIsRTL));
- //To resolve the bug fdo#59117
- //In RTL table as BottomLine & TopLine are drawn from Left Side to Right, nX should be nX-1
- const svx::frame::Style aBottomLine(impGetLineStyle(rTableLayouter, bIsRTL?nX-1:nX, nYBottom, true, nColCount, nRowCount, bIsRTL));
- const svx::frame::Style aRightLine(impGetLineStyle(rTableLayouter, nXRight, nY, false, nColCount, nRowCount, bIsRTL));
- const svx::frame::Style aTopLine(impGetLineStyle(rTableLayouter, bIsRTL?nX-1:nX, nY, true, nColCount, nRowCount, bIsRTL));
-
- if(aLeftLine.IsUsed() || aBottomLine.IsUsed() || aRightLine.IsUsed() || aTopLine.IsUsed())
- {
- // get the neighbor cells' borders
- const svx::frame::Style aLeftFromTLine(impGetLineStyle(rTableLayouter, nX, nY - 1, false, nColCount, nRowCount, bIsRTL));
- const svx::frame::Style aLeftFromBLine(impGetLineStyle(rTableLayouter, nX, nYBottom + 1, false, nColCount, nRowCount, bIsRTL));
- const svx::frame::Style aRightFromTLine(impGetLineStyle(rTableLayouter, nXRight, nY - 1, false, nColCount, nRowCount, bIsRTL));
- const svx::frame::Style aRightFromBLine(impGetLineStyle(rTableLayouter, nXRight, nYBottom + 1, false, nColCount, nRowCount, bIsRTL));
- const svx::frame::Style aTopFromLLine(impGetLineStyle(rTableLayouter, nX - 1, nY, true, nColCount, nRowCount, bIsRTL));
- const svx::frame::Style aTopFromRLine(impGetLineStyle(rTableLayouter, nXRight + 1, nY, true, nColCount, nRowCount, bIsRTL));
- const svx::frame::Style aBottomFromLLine(impGetLineStyle(rTableLayouter, nX - 1, nYBottom, true, nColCount, nRowCount, bIsRTL));
- const svx::frame::Style aBottomFromRLine(impGetLineStyle(rTableLayouter, nXRight + 1, nYBottom, true, nColCount, nRowCount, bIsRTL));
-
- // get cell coordinate system
- const basegfx::B2DPoint aOrigin(aCellMatrix * basegfx::B2DPoint(0.0, 0.0));
- const basegfx::B2DVector aX(aCellMatrix * basegfx::B2DVector(1.0, 0.0));
- const basegfx::B2DVector aY(aCellMatrix * basegfx::B2DVector(0.0, 1.0));
-
- if(aLeftLine.IsUsed())
- {
- createForVector(false, aBorderSequence, aOrigin, aY, aLeftLine,
- aTopLine, aLeftFromTLine, aTopFromLLine,
- aBottomLine, aLeftFromBLine, aBottomFromLLine);
- }
-
- if(aBottomLine.IsUsed())
- {
- createForVector(true, aBorderSequence, aOrigin + aY, aX, aBottomLine,
- aLeftLine, aBottomFromLLine, aLeftFromBLine,
- aRightLine, aBottomFromRLine, aRightFromBLine);
- }
-
- if(aRightLine.IsUsed())
- {
- createForVector(false, aBorderSequence, aOrigin + aX, aY, aRightLine,
- aTopFromRLine, aRightFromTLine, aTopLine,
- aBottomFromRLine, aRightFromBLine, aBottomLine);
- }
-
- if(aTopLine.IsUsed())
- {
- createForVector(true, aBorderSequence, aOrigin, aX, aTopLine,
- aLeftFromTLine, aTopFromLLine, aLeftLine,
- aRightFromTLine, aTopFromRLine, aRightLine);
- }
- }
}
}
}
}
- // append Border info to target. We want fillings and text first
- aRetval.append(aBorderSequence);
+ // now create all CellBorderPrimitives
+ const drawinglayer::primitive2d::Primitive2DContainer aCellBorderPrimitives(aArray.CreateB2DPrimitiveArray());
+
+ if(!aCellBorderPrimitives.empty())
+ {
+ // this is already scaled (due to Table in non-uniform coordinates), so
+ // first transform removing scale
+ basegfx::B2DHomMatrix aTransform(
+ basegfx::utils::createScaleB2DHomMatrix(
+ 1.0 / aObjectRange.getWidth(),
+ 1.0 / aObjectRange.getHeight()));
+
+ // If RTL, mirror the whole unified table in X and move right.
+ // This is much easier than taking this into account for the whole
+ // index calcualtions
+ if(bIsRTL)
+ {
+ aTransform.scale(-1.0, 1.0);
+ aTransform.translate(1.0, 0.0);
+ }
+
+ // create object matrix
+ const GeoStat& rGeoStat(rTableObj.GetGeoStat());
+ const double fShearX(rGeoStat.nShearAngle ? tan((36000 - rGeoStat.nShearAngle) * F_PI18000) : 0.0);
+ const double fRotate(rGeoStat.nRotationAngle ? (36000 - rGeoStat.nRotationAngle) * F_PI18000 : 0.0);
+ const basegfx::B2DHomMatrix aObjectMatrix(basegfx::utils::createScaleShearXRotateTranslateB2DHomMatrix(
+ aObjectRange.getWidth(), aObjectRange.getHeight(), fShearX, fRotate,
+ aObjectRange.getMinX(), aObjectRange.getMinY()));
+
+ // add object matrix to transform. By doing so theoretically
+ // CellBorders could be also rotated/sheared for the first time ever.
+ // To completely make that work, the primitives already created in
+ // aRetval would also have to be based on ObjectMatrix, not only on
+ // ObjectRange as it currently is.
+ aTransform *= aObjectMatrix;
+
+ // create a transform primitive with this and embed CellBorders
+ // and append to retval
+ aRetval.append(
+ new drawinglayer::primitive2d::TransformPrimitive2D(
+ aTransform,
+ aCellBorderPrimitives));
+ }
}
if(!aRetval.empty())
diff --git a/sw/source/core/layout/paintfrm.cxx b/sw/source/core/layout/paintfrm.cxx
index 4024f341defc..9d15ac754622 100644
--- a/sw/source/core/layout/paintfrm.cxx
+++ b/sw/source/core/layout/paintfrm.cxx
@@ -2489,11 +2489,33 @@ void SwTabFramePainter::PaintLines(OutputDevice& rDev, const SwRect& rRect) cons
{
aRepaintRect.Height( 2 * nRepaintRectSize );
aRepaintRect.Pos().Y() -= nRepaintRectSize;
+
+ // To decide on visibility it is also necessary to expand the RepaintRect
+ // to left/right according existing BorderLine overlap matchings, else there
+ // will be repaint errors when scrolling in e.t TripleLine BorderLines.
+ // aStyles[1] == aLFromT, aStyles[3] == aLFromB, aStyles[4] == aRFromT, aStyles[6] == aRFromB
+ if(aStyles[1].IsUsed() || aStyles[3].IsUsed() || aStyles[4].IsUsed() || aStyles[6].IsUsed())
+ {
+ const double fLineWidthMaxLeft(std::max(aStyles[1].GetWidth(), aStyles[3].GetWidth()));
+ const double fLineWidthMaxRight(std::max(aStyles[4].GetWidth(), aStyles[6].GetWidth()));
+ aRepaintRect.Width(aRepaintRect.Width() + (fLineWidthMaxLeft + fLineWidthMaxRight));
+ aRepaintRect.Pos().X() -= fLineWidthMaxLeft;
+ }
}
else
{
aRepaintRect.Width( 2 * nRepaintRectSize );
aRepaintRect.Pos().X() -= nRepaintRectSize;
+
+ // Accordingly to horizontal case, but for top/bottom
+ // aStyles[3] == aTFromR, aStyles[1] == aTFromL, aStyles[6] == aBFromR, aStyles[4] == aBFromL
+ if(aStyles[3].IsUsed() || aStyles[1].IsUsed() || aStyles[6].IsUsed() || aStyles[4].IsUsed())
+ {
+ const double fLineWidthMaxTop(std::max(aStyles[3].GetWidth(), aStyles[1].GetWidth()));
+ const double fLineWidthMaxBottom(std::max(aStyles[6].GetWidth(), aStyles[4].GetWidth()));
+ aRepaintRect.Height(aRepaintRect.Height() + (fLineWidthMaxTop + fLineWidthMaxBottom));
+ aRepaintRect.Pos().Y() -= fLineWidthMaxTop;
+ }
}
if (!rRect.IsOver(aRepaintRect))
diff --git a/sw/source/ui/table/tautofmt.cxx b/sw/source/ui/table/tautofmt.cxx
index 7c2a2d66e602..530b05850106 100644
--- a/sw/source/ui/table/tautofmt.cxx
+++ b/sw/source/ui/table/tautofmt.cxx
@@ -716,7 +716,7 @@ MAKENUMSTR:
SvtScriptedTextHelper aScriptedText(rRenderContext);
Size aStrSize;
sal_uInt8 nFormatIndex = GetFormatIndex( nCol, nRow );
- const basegfx::B2DRange aCellRange(maArray.GetCellRange( nCol, nRow ));
+ const basegfx::B2DRange aCellRange(maArray.GetCellRange( nCol, nRow, true ));
const tools::Rectangle cellRect(
basegfx::fround(aCellRange.getMinX()), basegfx::fround(aCellRange.getMinY()),
basegfx::fround(aCellRange.getMaxX()), basegfx::fround(aCellRange.getMaxY()));
@@ -811,7 +811,7 @@ void AutoFormatPreview::DrawBackground(vcl::RenderContext& rRenderContext)
rRenderContext.Push(PushFlags::LINECOLOR | PushFlags::FILLCOLOR);
rRenderContext.SetLineColor();
rRenderContext.SetFillColor(aBrushItem.GetColor());
- const basegfx::B2DRange aCellRange(maArray.GetCellRange( nCol, nRow ));
+ const basegfx::B2DRange aCellRange(maArray.GetCellRange( nCol, nRow, true ));
rRenderContext.DrawRect(
tools::Rectangle(
basegfx::fround(aCellRange.getMinX()), basegfx::fround(aCellRange.getMinY()),