borderline: Preparing further to use CellCoordinateSystem
Multiple cleanups, made svx::frame::Style a std::shared_ptr class,
preparing basing all border stuff on transformations, so it will
need a CellCoordinateSystem. Added stuff to get this Coordinate
System from the svx::frame::Cell using the Frame and knowledge
about ownerships
Change-Id: Ic2cb59cc92e648ac2fef72f22f8913479769d3e2
diff --git a/basegfx/source/matrix/b2dhommatrixtools.cxx b/basegfx/source/matrix/b2dhommatrixtools.cxx
index 645d4c7..89ab914 100644
--- a/basegfx/source/matrix/b2dhommatrixtools.cxx
+++ b/basegfx/source/matrix/b2dhommatrixtools.cxx
@@ -398,6 +398,20 @@ namespace basegfx
return aRetval;
}
B2DHomMatrix createCoordinateSystemTransform(
const B2DPoint& rOrigin,
const B2DVector& rX,
const B2DVector& rY)
{
return basegfx::B2DHomMatrix(
rX.getX(), rY.getX(), rOrigin.getX(),
rX.getY(), rY.getY(), rOrigin.getY());
}
B2DTuple getColumn(const B2DHomMatrix& rMatrix, sal_uInt16 nCol)
{
return B2DTuple(rMatrix.get(0, nCol), rMatrix.get(1, nCol));
}
} // end of namespace tools
} // end of namespace basegfx
diff --git a/include/basegfx/matrix/b2dhommatrixtools.hxx b/include/basegfx/matrix/b2dhommatrixtools.hxx
index 5dcd1b4..aa3c047 100644
--- a/include/basegfx/matrix/b2dhommatrixtools.hxx
+++ b/include/basegfx/matrix/b2dhommatrixtools.hxx
@@ -131,6 +131,15 @@ namespace basegfx
const B2DRange& rSourceRange,
const B2DRange& rTargetRange);
/// create based on given CoordinateSystem which is defined by origin and x/yaxis
BASEGFX_DLLPUBLIC B2DHomMatrix createCoordinateSystemTransform(
const B2DPoint& rOrigin,
const B2DVector& rX,
const B2DVector& rY);
/// get column vector from B2dHomMatrix, e.g. to extract coordinate system origin and x/yaxis
BASEGFX_DLLPUBLIC B2DTuple getColumn(const B2DHomMatrix& rMatrix, sal_uInt16 nCol);
} // end of namespace tools
} // end of namespace basegfx
diff --git a/include/svx/framelink.hxx b/include/svx/framelink.hxx
index 973c401..d0fb165 100644
--- a/include/svx/framelink.hxx
+++ b/include/svx/framelink.hxx
@@ -107,6 +107,43 @@ enum class RefMode
*/
class SAL_WARN_UNUSED SVX_DLLPUBLIC Style
{
private:
class implStyle
{
private:
friend class Style;
Color maColorPrim;
Color maColorSecn;
Color maColorGap;
bool mbUseGapColor;
RefMode meRefMode; /// Reference point handling for this frame border.
double mfPrim; /// Width of primary (single, left, or top) line.
double mfDist; /// Distance between primary and secondary line.
double mfSecn; /// Width of secondary (right or bottom) line.
double mfPatternScale; /// Scale used for line pattern spacing.
SvxBorderLineStyle mnType;
const Cell* mpUsingCell;
public:
/** Constructs an invisible frame style. */
explicit implStyle() :
maColorPrim(),
maColorSecn(),
maColorGap(),
mbUseGapColor(false),
meRefMode(RefMode::Centered),
mfPrim(0.0),
mfDist(0.0),
mfSecn(0.0),
mfPatternScale(1.0),
mnType(SvxBorderLineStyle::SOLID),
mpUsingCell(nullptr)
{}
};
std::shared_ptr< implStyle > maImplStyle;
public:
/** Constructs an invisible frame style. */
explicit Style();
@@ -118,20 +155,20 @@ public:
/** Constructs a frame style from the passed SvxBorderLine struct. Clears the style, if pBorder is 0. */
explicit Style( const editeng::SvxBorderLine* pBorder, double fScale = 1.0 );
RefMode GetRefMode() const { return meRefMode; }
const Color& GetColorPrim() const { return maColorPrim; }
const Color& GetColorSecn() const { return maColorSecn; }
const Color& GetColorGap() const { return maColorGap; }
bool UseGapColor() const { return mbUseGapColor; }
double Prim() const { return mfPrim; }
double Dist() const { return mfDist; }
double Secn() const { return mfSecn; }
double PatternScale() const { return mfPatternScale;}
void SetPatternScale( double fScale );
SvxBorderLineStyle Type() const { return mnType; }
RefMode GetRefMode() const { return maImplStyle->meRefMode; }
const Color& GetColorPrim() const { return maImplStyle->maColorPrim; }
const Color& GetColorSecn() const { return maImplStyle->maColorSecn; }
const Color& GetColorGap() const { return maImplStyle->maColorGap; }
bool UseGapColor() const { return maImplStyle->mbUseGapColor; }
double Prim() const { return maImplStyle->mfPrim; }
double Dist() const { return maImplStyle->mfDist; }
double Secn() const { return maImplStyle->mfSecn; }
double PatternScale() const { return maImplStyle->mfPatternScale;}
void SetPatternScale( double fScale ) { maImplStyle->mfPatternScale = fScale; }
SvxBorderLineStyle Type() const { return maImplStyle->mnType; }
/** Returns the total width of this frame style. */
double GetWidth() const { return mfPrim + mfDist + mfSecn; }
double GetWidth() const;
/** Sets the frame style to invisible state. */
void Clear();
@@ -146,37 +183,24 @@ public:
void Set( const editeng::SvxBorderLine* pBorder, double fScale, sal_uInt16 nMaxWidth = SAL_MAX_UINT16 );
/** Sets a new reference point handling mode, does not modify other settings. */
void SetRefMode( RefMode eRefMode ) { meRefMode = eRefMode; }
void SetRefMode( RefMode eRefMode ) { maImplStyle->meRefMode = eRefMode; }
/** Sets a new color, does not modify other settings. */
void SetColorPrim( const Color& rColor ) { maColorPrim = rColor; }
void SetColorSecn( const Color& rColor ) { maColorSecn = rColor; }
void SetColorPrim( const Color& rColor ) { maImplStyle->maColorPrim = rColor; }
void SetColorSecn( const Color& rColor ) { maImplStyle->maColorSecn = rColor; }
/** Sets whether to use dotted style for single hair lines. */
void SetType( SvxBorderLineStyle nType ) { mnType = nType; }
void SetType( SvxBorderLineStyle nType ) { maImplStyle->mnType = nType; }
/** 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; }
const Cell* GetUsingCell() const;
private:
Color maColorPrim;
Color maColorSecn;
Color maColorGap;
bool mbUseGapColor;
RefMode meRefMode; /// Reference point handling for this frame border.
double mfPrim; /// Width of primary (single, left, or top) line.
double mfDist; /// Distance between primary and secondary line.
double mfSecn; /// Width of secondary (right or bottom) line.
double mfPatternScale; /// Scale used for line pattern spacing.
SvxBorderLineStyle mnType;
/// need information which cell this style info comes from due to needed
/// rotation info (which is in the cell). Rotation depends on the cell.
/// Encapsulated using a single static friend method that is the single
/// allowed instance to set/modify this value
friend void exclusiveSetUsigCellAtStyle(Style& rStyle, const Cell* pCell);
const Cell* mpUsingCell;
friend class Cell;
void SetUsingCell(const Cell* pCell);
};
bool operator==( const Style& rL, const Style& rR );
diff --git a/include/svx/framelinkarray.hxx b/include/svx/framelinkarray.hxx
index 4801db2..78b95c8 100644
--- a/include/svx/framelinkarray.hxx
+++ b/include/svx/framelinkarray.hxx
@@ -292,6 +292,7 @@ public:
/** 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;
// mirroring --------------------------------------------------------------
@@ -311,6 +312,8 @@ public:
/** Draws the part of the array, that is inside the clipping range. */
void DrawArray(drawinglayer::processor2d::BaseProcessor2D& rProcessor) 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/svx/source/dialog/framelink.cxx b/svx/source/dialog/framelink.cxx
index e5523fe..cbabbcb 100644
--- a/svx/source/dialog/framelink.cxx
+++ b/svx/source/dialog/framelink.cxx
@@ -41,64 +41,36 @@ using namespace editeng;
namespace svx {
namespace frame {
namespace {
/** Converts a width in twips to a width in another map unit (specified by fScale). */
double lclScaleValue( double nValue, double fScale, sal_uInt16 nMaxWidth )
{
return std::min<double>(nValue * fScale, nMaxWidth);
}
} // namespace
// Classes
#define SCALEVALUE( value ) lclScaleValue( value, fScale, nMaxWidth )
Style::Style() :
meRefMode(RefMode::Centered),
mfPatternScale(1.0),
mnType(SvxBorderLineStyle::SOLID),
mpUsingCell(nullptr)
Style::Style() : maImplStyle(new implStyle())
{
Clear();
}
Style::Style( double nP, double nD, double nS, SvxBorderLineStyle nType ) :
meRefMode(RefMode::Centered),
mfPatternScale(1.0),
mnType(nType),
mpUsingCell(nullptr)
Style::Style( double nP, double nD, double nS, SvxBorderLineStyle nType ) : maImplStyle(new implStyle())
{
maImplStyle->mnType = nType;
Clear();
Set( nP, nD, nS );
}
Style::Style( const Color& rColorPrim, const Color& rColorSecn, const Color& rColorGap, bool bUseGapColor,
double nP, double nD, double nS, SvxBorderLineStyle nType ) :
meRefMode(RefMode::Centered),
mfPatternScale(1.0),
mnType(nType),
mpUsingCell(nullptr)
Style::Style( const Color& rColorPrim, const Color& rColorSecn, const Color& rColorGap, bool bUseGapColor, double nP, double nD, double nS, SvxBorderLineStyle nType ) : maImplStyle(new implStyle())
{
maImplStyle->mnType = nType;
Set( rColorPrim, rColorSecn, rColorGap, bUseGapColor, nP, nD, nS );
}
Style::Style( const editeng::SvxBorderLine* pBorder, double fScale ) :
meRefMode(RefMode::Centered),
mfPatternScale(fScale),
mpUsingCell(nullptr)
Style::Style( const editeng::SvxBorderLine* pBorder, double fScale ) : maImplStyle(new implStyle())
{
maImplStyle->mfPatternScale = fScale;
Set( pBorder, fScale );
}
void Style::SetPatternScale( double fScale )
double Style::GetWidth() const
{
mfPatternScale = fScale;
implStyle* pTarget = maImplStyle.get();
return pTarget->mfPrim + pTarget->mfDist + pTarget->mfSecn;
}
void Style::Clear()
@@ -115,66 +87,78 @@ void Style::Set( double nP, double nD, double nS )
>0 0 >0 nP 0 0
>0 >0 >0 nP nD nS
*/
mfPrim = rtl::math::round(nP ? nP : nS, 2);
mfDist = rtl::math::round((nP && nS) ? nD : 0, 2);
mfSecn = rtl::math::round((nP && nD) ? nS : 0, 2);
implStyle* pTarget = maImplStyle.get();
pTarget->mfPrim = rtl::math::round(nP ? nP : nS, 2);
pTarget->mfDist = rtl::math::round((nP && nS) ? nD : 0, 2);
pTarget->mfSecn = rtl::math::round((nP && nD) ? nS : 0, 2);
}
void Style::Set( const Color& rColorPrim, const Color& rColorSecn, const Color& rColorGap, bool bUseGapColor, double nP, double nD, double nS )
{
maColorPrim = rColorPrim;
maColorSecn = rColorSecn;
maColorGap = rColorGap;
mbUseGapColor = bUseGapColor;
implStyle* pTarget = maImplStyle.get();
pTarget->maColorPrim = rColorPrim;
pTarget->maColorSecn = rColorSecn;
pTarget->maColorGap = rColorGap;
pTarget->mbUseGapColor = bUseGapColor;
Set( nP, nD, nS );
}
void Style::Set( const SvxBorderLine& rBorder, double fScale, sal_uInt16 nMaxWidth )
{
maColorPrim = rBorder.GetColorOut();
maColorSecn = rBorder.GetColorIn();
maColorGap = rBorder.GetColorGap();
mbUseGapColor = rBorder.HasGapColor();
implStyle* pTarget = maImplStyle.get();
pTarget->maColorPrim = rBorder.GetColorOut();
pTarget->maColorSecn = rBorder.GetColorIn();
pTarget->maColorGap = rBorder.GetColorGap();
pTarget->mbUseGapColor = rBorder.HasGapColor();
sal_uInt16 nPrim = rBorder.GetOutWidth();
sal_uInt16 nDist = rBorder.GetDistance();
sal_uInt16 nSecn = rBorder.GetInWidth();
mnType = rBorder.GetBorderLineStyle();
pTarget->mnType = rBorder.GetBorderLineStyle();
if( !nSecn ) // no or single frame border
{
Set( SCALEVALUE( nPrim ), 0, 0 );
Set( std::min<double>(nPrim * fScale, nMaxWidth), 0, 0 );
}
else
{
Set( SCALEVALUE( nPrim ), SCALEVALUE( nDist ), SCALEVALUE( nSecn ) );
Set(std::min<double>(nPrim * fScale, nMaxWidth), std::min<double>(nDist * fScale, nMaxWidth), std::min<double>(nSecn * fScale, nMaxWidth));
// Enlarge the style if distance is too small due to rounding losses.
double nPixWidth = SCALEVALUE( nPrim + nDist + nSecn );
double nPixWidth = std::min<double>((nPrim + nDist + nSecn) * fScale, nMaxWidth);
if( nPixWidth > GetWidth() )
mfDist = nPixWidth - mfPrim - mfSecn;
{
pTarget->mfDist = nPixWidth - pTarget->mfPrim - pTarget->mfSecn;
}
// Shrink the style if it is too thick for the control.
while( GetWidth() > nMaxWidth )
{
// First decrease space between lines.
if (mfDist)
--mfDist;
// Still too thick? Decrease the line widths.
if( GetWidth() > nMaxWidth )
if (pTarget->mfDist)
{
if (mfPrim != 0.0 && rtl::math::approxEqual(mfPrim, mfSecn))
{
// Both lines equal - decrease both to keep symmetry.
--mfPrim;
--mfSecn;
}
else
{
// Decrease each line for itself
if (mfPrim)
--mfPrim;
if ((GetWidth() > nMaxWidth) && mfSecn != 0.0)
--mfSecn;
}
--(pTarget->mfDist);
continue;
}
// Still too thick? Decrease the line widths.
if (pTarget->mfPrim != 0.0 && rtl::math::approxEqual(pTarget->mfPrim, pTarget->mfSecn))
{
// Both lines equal - decrease both to keep symmetry.
--(pTarget->mfPrim);
--(pTarget->mfSecn);
continue;
}
// Decrease each line for itself
if (pTarget->mfPrim)
{
--(pTarget->mfPrim);
}
if ((GetWidth() > nMaxWidth) && pTarget->mfSecn != 0.0)
{
--(pTarget->mfSecn);
}
}
}
@@ -183,23 +167,36 @@ void Style::Set( const SvxBorderLine& rBorder, double fScale, sal_uInt16 nMaxWid
void Style::Set( const SvxBorderLine* pBorder, double fScale, sal_uInt16 nMaxWidth )
{
if( pBorder )
{
Set( *pBorder, fScale, nMaxWidth );
}
else
{
Clear();
mnType = SvxBorderLineStyle::SOLID;
maImplStyle->mnType = SvxBorderLineStyle::SOLID;
}
}
Style& Style::MirrorSelf()
{
if (mfSecn)
std::swap( mfPrim, mfSecn );
if( meRefMode != RefMode::Centered )
meRefMode = (meRefMode == RefMode::Begin) ? RefMode::End : RefMode::Begin;
implStyle* pTarget = maImplStyle.get();
if (pTarget->mfSecn)
{
std::swap( pTarget->mfPrim, pTarget->mfSecn );
}
if( pTarget->meRefMode != RefMode::Centered )
{
pTarget->meRefMode = (pTarget->meRefMode == RefMode::Begin) ? RefMode::End : RefMode::Begin;
}
return *this;
}
const Cell* Style::GetUsingCell() const { return maImplStyle->mpUsingCell; }
void Style::SetUsingCell(const Cell* pCell) { maImplStyle->mpUsingCell = pCell; }
bool operator==( const Style& rL, const Style& rR )
{
return (rL.Prim() == rR.Prim()) && (rL.Dist() == rR.Dist()) && (rL.Secn() == rR.Secn()) &&
@@ -228,8 +225,6 @@ bool operator<( const Style& rL, const Style& rR )
return false;
}
#undef SCALEVALUE
bool CheckFrameBorderConnectable( const Style& rLBorder, const Style& rRBorder,
const Style& rTFromTL, const Style& rTFromT, const Style& rTFromTR,
const Style& rBFromBL, const Style& rBFromB, const Style& rBFromBR )
diff --git a/svx/source/dialog/framelinkarray.cxx b/svx/source/dialog/framelinkarray.cxx
index ef6c410..70a7175 100644
--- a/svx/source/dialog/framelinkarray.cxx
+++ b/svx/source/dialog/framelinkarray.cxx
@@ -24,14 +24,11 @@
#include <algorithm>
#include <vcl/outdev.hxx>
#include <drawinglayer/primitive2d/borderlineprimitive2d.hxx>
#include <basegfx/matrix/b2dhommatrixtools.hxx>
namespace svx {
namespace frame {
/// single exclusive friend method to change mpUsingCell at style when style
/// is set at Cell, see friend definition for more info
void exclusiveSetUsigCellAtStyle(Style& rStyle, const Cell* pCell) { rStyle.mpUsingCell = pCell; }
class Cell
{
private:
@@ -48,8 +45,10 @@ public:
long mnAddTop;
long mnAddBottom;
SvxRotateMode meRotMode;
double mfOrientation;
SvxRotateMode meRotMode;
double mfOrientation;
basegfx::B2DHomMatrix maCoordinateSystem;
size_t maCellIndex;
bool mbMergeOrig;
bool mbOverlapX;
@@ -58,12 +57,12 @@ public:
public:
explicit Cell();
void SetStyleLeft(const Style& rStyle) { maLeft = rStyle; exclusiveSetUsigCellAtStyle(maLeft, this); }
void SetStyleRight(const Style& rStyle) { maRight = rStyle; exclusiveSetUsigCellAtStyle(maRight, this); }
void SetStyleTop(const Style& rStyle) { maTop = rStyle; exclusiveSetUsigCellAtStyle(maTop, this); }
void SetStyleBottom(const Style& rStyle) { maBottom = rStyle; exclusiveSetUsigCellAtStyle(maBottom, this); }
void SetStyleTLBR(const Style& rStyle) { maTLBR = rStyle; exclusiveSetUsigCellAtStyle(maTLBR, this); }
void SetStyleBLTR(const Style& rStyle) { maBLTR = rStyle; exclusiveSetUsigCellAtStyle(maBLTR, this); }
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); }
const Style& GetStyleLeft() const { return maLeft; }
const Style& GetStyleRight() const { return maRight; }
@@ -76,11 +75,65 @@ public:
bool IsRotated() const { return mfOrientation != 0.0; }
void MirrorSelfX();
basegfx::B2DHomMatrix CreateCoordinateSystem(const Array& rArray) const;
};
typedef std::vector< long > LongVec;
typedef std::vector< Cell > CellVec;
basegfx::B2DHomMatrix Cell::CreateCoordinateSystem(const Array& rArray) const
{
if(!maCoordinateSystem.isIdentity())
{
return maCoordinateSystem;
}
if(-1 == maCellIndex)
{
rArray.AddCellIndices();
}
if(-1 != maCellIndex)
{
const basegfx::B2DRange aRange(rArray.GetCellRange(maCellIndex));
basegfx::B2DPoint aOrigin(aRange.getMinimum());
basegfx::B2DVector aX(aRange.getWidth(), 0.0);
basegfx::B2DVector aY(0.0, aRange.getHeight());
if (IsRotated() && SvxRotateMode::SVX_ROTATE_MODE_STANDARD != 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;
}
}
// use column vectors as coordinate axes, homogen column for translation
const_cast<Cell*>(this)->maCoordinateSystem = basegfx::tools::createCoordinateSystemTransform(aOrigin, aX, aY);
}
return maCoordinateSystem;
}
Cell::Cell() :
mnAddLeft( 0 ),
mnAddRight( 0 ),
@@ -88,6 +141,8 @@ 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 )
@@ -101,6 +156,8 @@ void Cell::MirrorSelfX()
maLeft.MirrorSelf();
maRight.MirrorSelf();
mfOrientation = -mfOrientation;
maCoordinateSystem.identity();
maCellIndex = static_cast<size_t>(-1);
}
@@ -808,6 +865,11 @@ long Array::GetHeight() const
return GetRowPosition( mxImpl->mnHeight ) - GetRowPosition( 0 );
}
basegfx::B2DRange Array::GetCellRange( size_t nCellIndex ) 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 );
@@ -866,46 +928,6 @@ void Array::MirrorSelfX()
}
// drawing
void CreateCoordinateSystemForCell(
const basegfx::B2DRange& rRange,
const Cell& rCell,
basegfx::B2DPoint& rOrigin,
basegfx::B2DVector& rX,
basegfx::B2DVector& rY)
{
// fill in defaults
rOrigin = rRange.getMinimum();
rX = basegfx::B2DVector(rRange.getWidth(), 0.0);
rY = basegfx::B2DVector(0.0, rRange.getHeight());
if (rCell.IsRotated() && SvxRotateMode::SVX_ROTATE_MODE_STANDARD != rCell.meRotMode)
{
// when rotated, adapt values. Get Skew (cos/sin == 1/tan)
const double fSkew(rRange.getHeight() * (cos(rCell.mfOrientation) / sin(rCell.mfOrientation)));
switch (rCell.meRotMode)
{
case SvxRotateMode::SVX_ROTATE_MODE_TOP:
// shear Y-Axis
rY.setX(-fSkew);
break;
case SvxRotateMode::SVX_ROTATE_MODE_CENTER:
// shear origin half, Y full
rOrigin.setX(rOrigin.getX() + (fSkew * 0.5));
rY.setX(-fSkew);
break;
case SvxRotateMode::SVX_ROTATE_MODE_BOTTOM:
// shear origin full, Y full
rOrigin.setX(rOrigin.getX() + fSkew);
rY.setX(-fSkew);
break;
default: // SvxRotateMode::SVX_ROTATE_MODE_STANDARD, already excluded above
break;
}
}
}
void Array::DrawRange( drawinglayer::processor2d::BaseProcessor2D& rProcessor,
size_t nFirstCol, size_t nFirstRow, size_t nLastCol, size_t nLastRow,
const Color* pForceColor ) const
@@ -942,17 +964,13 @@ void Array::DrawRange( drawinglayer::processor2d::BaseProcessor2D& rProcessor,
if (rTLBR.GetWidth() || rBLTR.GetWidth())
{
drawinglayer::primitive2d::Primitive2DContainer aSequence;
basegfx::B2DPoint aOrigin;
basegfx::B2DVector aX;
basegfx::B2DVector aY;
CreateCoordinateSystemForCell(aRange, rCell, aOrigin, aX, aY);
basegfx::B2DHomMatrix aCoordinateSystem(rCell.CreateCoordinateSystem(*this));
CreateDiagFrameBorderPrimitives(
aSequence,
aOrigin,
aX,
aY,
basegfx::tools::getColumn(aCoordinateSystem, 2),
basegfx::tools::getColumn(aCoordinateSystem, 0),
basegfx::tools::getColumn(aCoordinateSystem, 1),
rTLBR,
rBLTR,
GetCellStyleLeft(_nFirstCol, _nFirstRow),
@@ -1016,54 +1034,40 @@ void Array::DrawRange( drawinglayer::processor2d::BaseProcessor2D& rProcessor,
if ((pStart->Prim() || pStart->Secn()) && (aStartPos.getX() <= aEndPos.getX()))
{
// prepare defaults for borderline coordinate system
basegfx::B2DPoint aOrigin(aStartPos);
basegfx::B2DVector aX(aEndPos - aStartPos);
basegfx::B2DVector aY(0.0, 1.0);
const Cell* pCell = pStart->GetUsingCell();
if (pCell && pCell->IsRotated())
if(pCell)
{
// To apply the shear, we need to get the cell range. We have the defining cell,
// but there is no call at it to directly get it's range. To get the correct one,
// we need to take care if the borderline is at top or bottom, so use pointer
// compare here to find out
basegfx::B2DHomMatrix aCoordinateSystem(pCell->CreateCoordinateSystem(*this));
const bool bUpper(&pCell->GetStyleTop() == pStart);
const basegfx::B2DRange aRange(GetCellRange(nCol - 1, bUpper ? nRow : nRow - 1));
// adapt to cell coordinate system, including shear
CreateCoordinateSystemForCell(aRange, *pCell, aOrigin, aX, aY);
if (!bUpper)
if(!bUpper)
{
// for the lower edge we need to translate to get to the
// borderline coordinate system. For the upper one, all is
// okay already
aOrigin += aY;
// borderline coordinate system
aCoordinateSystem.set(0, 2, aCoordinateSystem.get(0, 2) + aCoordinateSystem.get(0, 1));
aCoordinateSystem.set(1, 2, aCoordinateSystem.get(1, 2) + aCoordinateSystem.get(1, 1));
}
// borderline coordinate system uses normalized 2nd axis
aY.normalize();
drawinglayer::primitive2d::Primitive2DContainer aSequence;
CreateBorderPrimitives(
aSequence,
basegfx::tools::getColumn(aCoordinateSystem, 2),
basegfx::tools::getColumn(aCoordinateSystem, 0),
basegfx::B2DVector(basegfx::tools::getColumn(aCoordinateSystem, 1)).normalize(),
*pStart,
aStartLFromTR,
*pStartLFromT,
*pStartLFromL,
*pStartLFromB,
aStartLFromBR,
aEndRFromTL,
*pEndRFromT,
*pEndRFromR,
*pEndRFromB,
aEndRFromBL,
pForceColor);
rProcessor.process(aSequence);
}
drawinglayer::primitive2d::Primitive2DContainer aSequence;
CreateBorderPrimitives(
aSequence,
aOrigin,
aX,
aY,
*pStart,
aStartLFromTR,
*pStartLFromT,
*pStartLFromL,
*pStartLFromB,
aStartLFromBR,
aEndRFromTL,
*pEndRFromT,
*pEndRFromR,
*pEndRFromB,
aEndRFromBL,
pForceColor);
rProcessor.process(aSequence);
}
// re-init "*Start***" variables
@@ -1090,45 +1094,41 @@ void Array::DrawRange( drawinglayer::processor2d::BaseProcessor2D& rProcessor,
{
// for description of involved coordinate systems have a look at
// the first CreateBorderPrimitives call above
basegfx::B2DPoint aOrigin(aStartPos);
basegfx::B2DVector aX(aEndPos - aStartPos);
basegfx::B2DVector aY(0.0, 1.0);
const Cell* pCell = pStart->GetUsingCell();
if (pCell && pCell->IsRotated())
if(pCell)
{
basegfx::B2DHomMatrix aCoordinateSystem(pCell->CreateCoordinateSystem(*this));
const bool bUpper(&pCell->GetStyleTop() == pStart);
const basegfx::B2DRange aRange(GetCellRange(nCol - 1, bUpper ? nRow : nRow - 1));
CreateCoordinateSystemForCell(aRange, *pCell, aOrigin, aX, aY);
if (!bUpper)
if(!bUpper)
{
aOrigin += aY;
// for the lower edge we need to translate to get to the
// borderline coordinate system
aCoordinateSystem.set(0, 2, aCoordinateSystem.get(0, 2) + aCoordinateSystem.get(0, 1));
aCoordinateSystem.set(1, 2, aCoordinateSystem.get(1, 2) + aCoordinateSystem.get(1, 1));
}
aY.normalize();
drawinglayer::primitive2d::Primitive2DContainer aSequence;
CreateBorderPrimitives(
aSequence,
basegfx::tools::getColumn(aCoordinateSystem, 2),
basegfx::tools::getColumn(aCoordinateSystem, 0),
basegfx::B2DVector(basegfx::tools::getColumn(aCoordinateSystem, 1)).normalize(),
*pStart,
aStartLFromTR,
*pStartLFromT,
*pStartLFromL,
*pStartLFromB,
aStartLFromBR,
aEndRFromTL,
*pEndRFromT,
*pEndRFromR,
*pEndRFromB,
aEndRFromBL,
pForceColor);
rProcessor.process(aSequence);
}
drawinglayer::primitive2d::Primitive2DContainer aSequence;
CreateBorderPrimitives(
aSequence,
aOrigin,
aX,
aY,
*pStart,
aStartLFromTR,
*pStartLFromT,
*pStartLFromL,
*pStartLFromB,
aStartLFromBR,
aEndRFromTL,
*pEndRFromT,
*pEndRFromR,
*pEndRFromB,
aEndRFromBL,
pForceColor);
rProcessor.process(aSequence);
}
}
@@ -1177,59 +1177,57 @@ void Array::DrawRange( drawinglayer::processor2d::BaseProcessor2D& rProcessor,
{
// for description of involved coordinate systems have a look at
// the first CreateBorderPrimitives call above. Additionally adapt to vertical
basegfx::B2DPoint aOrigin(aStartPos);
basegfx::B2DVector aX(aEndPos - aStartPos);
basegfx::B2DVector aY(-1.0, 0.0);
const Cell* pCell = pStart->GetUsingCell();
if (pCell && pCell->IsRotated())
if(pCell)
{
basegfx::B2DHomMatrix aCoordinateSystem(pCell->CreateCoordinateSystem(*this));
const bool bLeft(&pCell->GetStyleLeft() == pStart);
const basegfx::B2DRange aRange(GetCellRange(bLeft ? nCol : nCol - 1, nRow - 1));
CreateCoordinateSystemForCell(aRange, *pCell, aOrigin, aX, aY);
if (!bLeft)
if(!bLeft)
{
aOrigin += aX;
// for the Right edge we need to translate to get to the
// borderline coordinate system
aCoordinateSystem.set(0, 2, aCoordinateSystem.get(0, 2) + aCoordinateSystem.get(0, 0));
aCoordinateSystem.set(1, 2, aCoordinateSystem.get(1, 2) + aCoordinateSystem.get(1, 0));
}
// The *coordinate system* of the edge has to be given, which for vertical
// lines uses the Y-Vector as X-Axis and the X-Vector as Y-Axis, so swap both
// and mirror aX to keep the same orientation (should be (-1.0, 0.0) for
// horizontal lines anyways, this could be used as test here, checked in debug mode)
std::swap(aX, aY);
aY.normalize();
aY = -aY;
}
const basegfx::B2DTuple aX(basegfx::tools::getColumn(aCoordinateSystem, 0));
const basegfx::B2DTuple aY(basegfx::tools::getColumn(aCoordinateSystem, 1));
aCoordinateSystem = basegfx::tools::createCoordinateSystemTransform(basegfx::tools::getColumn(aCoordinateSystem, 2), aY, -aX);
drawinglayer::primitive2d::Primitive2DContainer aSequence;
CreateBorderPrimitives(
// This replaces DrawVerFrameBorder which went from top to bottom. To be able to use
// the same method as for horizontal (CreateBorderPrimitives), the given borders
// have to be rearranged. Best is to look at the explanations of parameters in
// framelink.hxx and the former calls to DrawVerFrameBorder and it's parameters.
// In principle, the order of the five TFrom and BFrom has to be
// inverted to get the same orientation. Before, EndPos and StartPos were changed
// which avoids the reordering, but also leads to inverted line patters for vertical
// lines.
aSequence,
aOrigin,
aX,
aY,
*pStart,
aStartTFromBR,
*pStartTFromR,
*pStartTFromT,
*pStartTFromL,
aStartTFromBL,
aEndBFromTR,
*pEndBFromR,
*pEndBFromB,
*pEndBFromL,
aEndBFromTL,
pForceColor);
rProcessor.process(aSequence);
drawinglayer::primitive2d::Primitive2DContainer aSequence;
CreateBorderPrimitives(
// This replaces DrawVerFrameBorder which went from top to bottom. To be able to use
// the same method as for horizontal (CreateBorderPrimitives), the given borders
// have to be rearranged. Best is to look at the explanations of parameters in
// framelink.hxx and the former calls to DrawVerFrameBorder and it's parameters.
// In principle, the order of the five TFrom and BFrom has to be
// inverted to get the same orientation. Before, EndPos and StartPos were changed
// which avoids the reordering, but also leads to inverted line patters for vertical
// lines.
aSequence,
basegfx::tools::getColumn(aCoordinateSystem, 2),
basegfx::tools::getColumn(aCoordinateSystem, 0),
basegfx::B2DVector(basegfx::tools::getColumn(aCoordinateSystem, 1)).normalize(),
*pStart,
aStartTFromBR,
*pStartTFromR,
*pStartTFromT,
*pStartTFromL,
aStartTFromBL,
aEndBFromTR,
*pEndBFromR,
*pEndBFromB,
*pEndBFromL,
aEndBFromTL,
pForceColor);
rProcessor.process(aSequence);
}
}
// re-init "*Start***" variables
@@ -1256,51 +1254,50 @@ void Array::DrawRange( drawinglayer::processor2d::BaseProcessor2D& rProcessor,
{
// for description of involved coordinate systems have a look at
// the first CreateBorderPrimitives call above, adapt to vertical
basegfx::B2DPoint aOrigin(aStartPos);
basegfx::B2DVector aX(aEndPos - aStartPos);
basegfx::B2DVector aY(-1.0, 0.0);
const Cell* pCell = pStart->GetUsingCell();
if (pCell && pCell->IsRotated())
if(pCell)
{
basegfx::B2DHomMatrix aCoordinateSystem(pCell->CreateCoordinateSystem(*this));
const bool bLeft(&pCell->GetStyleLeft() == pStart);
const basegfx::B2DRange aRange(GetCellRange(bLeft ? nCol : nCol - 1, nRow - 1));
CreateCoordinateSystemForCell(aRange, *pCell, aOrigin, aX, aY);
if (!bLeft)
if(!bLeft)
{
aOrigin += aX;
// for the Right edge we need to translate to get to the
// borderline coordinate system
aCoordinateSystem.set(0, 2, aCoordinateSystem.get(0, 2) + aCoordinateSystem.get(0, 0));
aCoordinateSystem.set(1, 2, aCoordinateSystem.get(1, 2) + aCoordinateSystem.get(1, 0));
}
// The *coordinate system* of the edge has to be given, which for vertical
// lines uses the Y-Vector as X-Axis and the X-Vector as Y-Axis, so swap both
// and mirror aX to keep the same orientation (should be (-1.0, 0.0) for horizontal lines anyways)
std::swap(aX, aY);
aY.normalize();
aY = -aY;
}
// and mirror aX to keep the same orientation (should be (-1.0, 0.0) for
// horizontal lines anyways, this could be used as test here, checked in debug mode)
const basegfx::B2DTuple aX(basegfx::tools::getColumn(aCoordinateSystem, 0));
const basegfx::B2DTuple aY(basegfx::tools::getColumn(aCoordinateSystem, 1));
aCoordinateSystem = basegfx::tools::createCoordinateSystemTransform(basegfx::tools::getColumn(aCoordinateSystem, 2), aY, -aX);
drawinglayer::primitive2d::Primitive2DContainer aSequence;
CreateBorderPrimitives(
// also reordered, see call to CreateBorderPrimitives above
aSequence,
aOrigin,
aX,
aY,
*pStart,
aStartTFromBR,
*pStartTFromR,
*pStartTFromT,
*pStartTFromL,
aStartTFromBL,
aEndBFromTR,
*pEndBFromR,
*pEndBFromB,
*pEndBFromL,
aEndBFromTL,
pForceColor);
rProcessor.process(aSequence);
drawinglayer::primitive2d::Primitive2DContainer aSequence;
CreateBorderPrimitives(
// also reordered, see call to CreateBorderPrimitives above
aSequence,
basegfx::tools::getColumn(aCoordinateSystem, 2),
basegfx::tools::getColumn(aCoordinateSystem, 0),
basegfx::B2DVector(basegfx::tools::getColumn(aCoordinateSystem, 1)).normalize(),
*pStart,
aStartTFromBR,
*pStartTFromR,
*pStartTFromT,
*pStartTFromL,
aStartTFromBL,
aEndBFromTR,
*pEndBFromR,
*pEndBFromB,
*pEndBFromL,
aEndBFromTL,
pForceColor);
rProcessor.process(aSequence);
}
}
}
}
@@ -1311,6 +1308,14 @@ void Array::DrawArray(drawinglayer::processor2d::BaseProcessor2D& rProcessor) co
DrawRange(rProcessor, 0, 0, mxImpl->mnWidth - 1, mxImpl->mnHeight - 1, nullptr);
}
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