borderline: adaptions to primitives
Handling and paint of borderlines greatly adapted
to primitive usage. Solved the double paint mechanisn
to no longer use the sc-local special cases. The
svx tooling for borderline paint is now the only one
and was extended to also handle diagonal lines.
Big cleanups/removals of old paint to OutputDevice
and sc-specific rendering. All other app-usages
of borderline also adapted. Preparations for careful
line-start/end adaption prepared and possible due to
unified coordinate-system usages and basegfx class-usage
Change-Id: If9e4efcfc0fe25e14d4052907038ca5cf222a432
diff --git a/include/svx/framelink.hxx b/include/svx/framelink.hxx
index b907958..b0c11e2 100644
--- a/include/svx/framelink.hxx
+++ b/include/svx/framelink.hxx
@@ -32,6 +32,7 @@
class Point;
namespace tools { class Rectangle; }
class OutputDevice;
namespace svx { namespace frame { class Cell; }}
namespace svx {
namespace frame {
@@ -157,6 +158,9 @@ public:
/** Returns this style mirrored, if it is a double frame style, otherwise a simple copy. */
Style Mirror() const;
/** return the Cell using this style (if set) */
const Cell* GetUsingCell() const { return mpUsingCell; }
private:
Color maColorPrim;
Color maColorSecn;
@@ -168,6 +172,13 @@ private:
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;
};
bool operator==( const Style& rL, const Style& rR );
@@ -277,78 +288,6 @@ inline double GetVerDiagAngle( const tools::Rectangle& rRect )
*/
SVX_DLLPUBLIC long GetTLDiagOffset( long nVerOffs, long nDiagOffs, double fAngle );
/** Returns an X coordinate for a diagonal frame border in the specified height.
This function is for usage with the bottom-left end of a bottom-left to
top-right diagonal frame border, connected to the left end of a horizontal
frame border.
The function returns the relative X position (i.e. for a polygon) of the
diagonal frame border according to the specified relative Y position. The
mentioned positions are relative to the reference point of both frame
borders.
Primary -->/ /<--- Secondary
/ /
/ / The function calculates the X position of i.e.
- - - - - - - - -/- - -X <----- this point (relative from X of reference point).
^ +---/ /------------------------------------------------
nVerOffs | / / <--- The diagonal frame border.
v | / | /
- - - - - - | --+-- <---- Reference point for horizontal and diagonal frame borders.
| |
| The horizontal frame border.
+----------------------------------------------------------
@param nVerOffs
The vertical position of the point to be calculated, relative to the Y
coordinate of the reference point.
@param nDiagOffs
The width offset across the diagonal frame border (0 = middle),
regardless of the gradient of the diagonal frame border (always
vertical to the direction of the diagonal frame border). This value is
not related in any way to the reference point. For details about
relative width offsets, see description of class Style.
@param fAngle
Inner (right) angle between diagonal and horizontal frame border.
*/
long GetBLDiagOffset( long nVerOffs, long nDiagOffs, double fAngle );
/** Returns an X coordinate for a diagonal frame border in the specified height.
This function is for usage with the bottom-right end of a top-left to
bottom-right diagonal frame border, connected to the right end of a
horizontal frame border.
@param nDiagOffs
The width offset across the diagonal frame border (0 = middle),
regardless of the gradient of the diagonal frame border (always
vertical to the direction of the diagonal frame border). This value is
not related in any way to the reference point. For details about
relative width offsets, see description of class Style.
@param fAngle
Inner (left) angle between diagonal and horizontal frame border.
*/
long GetBRDiagOffset( long nDiagOffs, double fAngle );
/** Returns an X coordinate for a diagonal frame border in the specified height.
This function is for usage with the top-right end of a bottom-left to
top-right diagonal frame border, connected to the right end of a horizontal
frame border.
@param nDiagOffs
The width offset across the diagonal frame border (0 = middle),
regardless of the gradient of the diagonal frame border (always
vertical to the direction of the diagonal frame border). This value is
not related in any way to the reference point. For details about
relative width offsets, see description of class Style.
@param fAngle
Inner (left) angle between diagonal and horizontal frame border.
*/
long GetTRDiagOffset( long nDiagOffs, double fAngle );
/** Checks whether two horizontal frame borders are "connectable".
Two borders are "connectable" in terms of this function, if both can be
@@ -431,8 +370,11 @@ SVX_DLLPUBLIC bool CheckFrameBorderConnectable(
*/
SVX_DLLPUBLIC void CreateBorderPrimitives(
drawinglayer::primitive2d::Primitive2DContainer& rTarget, /// target for created primitives
const Point& rLPos, /// Reference point for left end of the processed frame border.
const Point& rRPos, /// Reference point for right end of the processed frame border.
const basegfx::B2DPoint& rOrigin, /// start point of borderline
const basegfx::B2DVector& rX, /// X-Axis with length
const basegfx::B2DVector& rY, /// Y-Axis for perpendicular, normalized. Does *not* need to be perpendicular, but may express a rotation
const Style& rBorder, /// Style of the processed frame border.
const DiagStyle& rLFromTR, /// Diagonal frame border from top-right to left end of rBorder.
@@ -447,15 +389,16 @@ SVX_DLLPUBLIC void CreateBorderPrimitives(
const Style& rRFromB, /// Vertical frame border from bottom to right end of rBorder.
const DiagStyle& rRFromBL, /// Diagonal frame border from bottom-left to right end of rBorder.
const Color* pForceColor, /// If specified, overrides frame border color.
const long rRotationT = 9000, /// Angle of the top slanted frames in 100th of degree
const long rRotationB = 9000 /// Angle of the bottom slanted frames in 100th of degree
const Color* pForceColor /// If specified, overrides frame border color.
);
SVX_DLLPUBLIC void CreateBorderPrimitives(
drawinglayer::primitive2d::Primitive2DContainer& rTarget, /// target for created primitives
const Point& rLPos, /// Reference point for left end of the processed frame border.
const Point& rRPos, /// Reference point for right end of the processed frame border.
const basegfx::B2DPoint& rOrigin, /// start point of borderline
const basegfx::B2DVector& rX, /// X-Axis with length
const basegfx::B2DVector& rY, /// Y-Axis for perpendicular, normalized. Does *not* need to be perpendicular, but may express a rotation
const Style& rBorder, /// Style of the processed frame border.
const Style& rLFromT, /// Vertical frame border from top to left end of rBorder.
@@ -466,9 +409,7 @@ SVX_DLLPUBLIC void CreateBorderPrimitives(
const Style& rRFromR, /// Horizontal frame border from right to right end of rBorder.
const Style& rRFromB, /// Vertical frame border from bottom to right end of rBorder.
const Color* pForceColor, /// If specified, overrides frame border color.
const long rRotationT = 9000, /// Angle of the top slanted frame in 100th of degrees
const long rRotationB = 9000 /// Angle of the bottom slanted frame in 100th of degrees
const Color* pForceColor /// If specified, overrides frame border color.
);
/** Draws both diagonal frame borders, regards all connected frame styles.
@@ -479,7 +420,10 @@ The function preserves all settings of the passed output device.
*/
SVX_DLLPUBLIC void CreateDiagFrameBorderPrimitives(
drawinglayer::primitive2d::Primitive2DContainer& rTarget, /// target for created primitives
const basegfx::B2DRange& rRange, /// geometrical definition for both diagonal frame borders.
const basegfx::B2DPoint& rOrigin, /// Origin of the coordinate system spawning the cell
const basegfx::B2DVector& rXAxis, /// X-Axis of the coordinate system spawning the cell
const basegfx::B2DVector& rYAxis, /// Y-Axis of the coordinate system spawning the cell
const Style& rTLBR, /// Style of the processed top-left to bottom-right diagonal frame border.
const Style& rBLTR, /// Style of the processed bottom-left to top-right diagonal frame border.
@@ -494,164 +438,7 @@ SVX_DLLPUBLIC void CreateDiagFrameBorderPrimitives(
const Style& rTRFromB, /// Vertical frame border from bottom to top-right end of rBLTR.
const Style& rTRFromL, /// Horizontal frame border from left to top-right end of rBLTR.
const Color* pForceColor, /// If specified, overrides frame border color.
const long nRotationT = 9000, /// Angle of the top slanted frame in 100th of degrees
const long nRotationB = 9000 /// Angle of the bottom slanted frame in 100th of degrees
);
/** Draws a horizontal frame border, regards all connected frame styles.
The frame style to draw is passed as parameter rBorder. The function
calculates the adjustment in X direction for left and right end of primary
and secondary line of the frame border (the style may present a double
line). The line ends may differ according to the connected frame styles
coming from top, bottom, left, right, and/or diagonal.
Thick frame styles are always drawn centered (in width) to the passed
reference points. The Y coordinates of both reference points must be equal
(the line cannot be drawn slanted).
The function preserves all settings of the passed output device.
All parameters starting with "rL" refer to the left end of the processed
frame border, all parameters starting with "rR" refer to the right end.
The following part of the parameter name starting with "From" specifies
where the frame border comes from. Example: "rLFromTR" means the frame
border coming from top-right, connected to the left end of rBorder (and
therefore a diagonal frame border).
The follong picture shows the meaning of all passed parameters:
rLFromT / \ rRFromT
| / \ |
| rLFromTR rRFromTL |
| / \ |
| / \ |
--- rLFromL --- ============== rBorder ============== --- rRFromR ---
| \ / |
| \ / |
| rLFromBR rRFromBL |
| \ / |
rLFromB \ / rRFromB
*/
SVX_DLLPUBLIC void DrawHorFrameBorder(
OutputDevice& rDev, /// The output device used to draw the frame border.
const Point& rLPos, /// Reference point for left end of the processed frame border.
const Point& rRPos, /// Reference point for right end of the processed frame border.
const Style& rBorder, /// Style of the processed frame border.
const DiagStyle& rLFromTR, /// Diagonal frame border from top-right to left end of rBorder.
const Style& rLFromT, /// Vertical frame border from top to left end of rBorder.
const Style& rLFromL, /// Horizontal frame border from left to left end of rBorder.
const Style& rLFromB, /// Vertical frame border from bottom to left end of rBorder.
const DiagStyle& rLFromBR, /// Diagonal frame border from bottom-right to left end of rBorder.
const DiagStyle& rRFromTL, /// Diagonal frame border from top-left to right end of rBorder.
const Style& rRFromT, /// Vertical frame border from top to right end of rBorder.
const Style& rRFromR, /// Horizontal frame border from right to right end of rBorder.
const Style& rRFromB, /// Vertical frame border from bottom to right end of rBorder.
const DiagStyle& rRFromBL, /// Diagonal frame border from bottom-left to right end of rBorder.
const Color* pForceColor = nullptr /// If specified, overrides frame border color.
);
/** Draws a vertical frame border, regards all connected frame styles.
The frame style to draw is passed as parameter rBorder. The function
calculates the adjustment in Y direction for top and bottom end of primary
and secondary line of the frame border (the style may present a double
line). The line ends may differ according to the connected frame styles
coming from left, right, top, bottom, and/or diagonal.
Thick frame styles are always drawn centered (in width) to the passed
reference points. The X coordinates of both reference points must be equal
(the line cannot be drawn slanted).
The function preserves all settings of the passed output device.
All parameters starting with "rT" refer to the top end of the processed
frame border, all parameters starting with "rB" refer to the bottom end.
The following part of the parameter name starting with "From" specifies
where the frame border comes from. Example: "rTFromBL" means the frame
border coming from bottom-left, connected to the top end of rBorder (and
therefore a diagonal frame border).
The follong picture shows the meaning of all passed parameters:
|
rTFromT
|
|
--- rTFromL --- --- rTFromR ---
/ # \
/ # \
rTFromBL # rTFromBR
/ # \
/ # \
#
rBorder
#
\ # /
\ # /
rBFromTL # rBFromTR
\ # /
\ # /
--- rBFromL --- --- rBFromR ---
|
|
rBFromB
|
*/
SVX_DLLPUBLIC void DrawVerFrameBorder(
OutputDevice& rDev, /// The output device used to draw the frame border.
const Point& rTPos, /// Reference point for top end of the processed frame border.
const Point& rBPos, /// Reference point for bottom end of the processed frame border.
const Style& rBorder, /// Style of the processed frame border.
const DiagStyle& rTFromBL, /// Diagonal frame border from bottom-right to top end of rBorder.
const Style& rTFromL, /// Horizontal frame border from left to top end of rBorder.
const Style& rTFromT, /// Vertical frame border from top to top end of rBorder.
const Style& rTFromR, /// Horizontal frame border from right to top end of rBorder.
const DiagStyle& rTFromBR, /// Diagonal frame border from bottom-right to top end of rBorder.
const DiagStyle& rBFromTL, /// Diagonal frame border from top-left to bottom end of rBorder.
const Style& rBFromL, /// Horizontal frame border from left to bottom end of rBorder.
const Style& rBFromB, /// Vertical frame border from bottom to bottom end of rBorder.
const Style& rBFromR, /// Horizontal frame border from right to bottom end of rBorder.
const DiagStyle& rBFromTR, /// Diagonal frame border from top-right to bottom end of rBorder.
const Color* pForceColor = nullptr /// If specified, overrides frame border color.
);
/** Draws both diagonal frame borders, regards all connected frame styles.
One or both passed diagonal frame styles may be invisible.
The function preserves all settings of the passed output device.
*/
SVX_DLLPUBLIC void DrawDiagFrameBorders(
OutputDevice& rDev, /// The output device used to draw the frame border.
const tools::Rectangle& rRect, /// Rectangle for both diagonal frame borders.
const Style& rTLBR, /// Style of the processed top-left to bottom-right diagonal frame border.
const Style& rBLTR, /// Style of the processed bottom-left to top-right diagonal frame border.
const Style& rTLFromB, /// Vertical frame border from bottom to top-left end of rTLBR.
const Style& rTLFromR, /// Horizontal frame border from right to top-left end of rTLBR.
const Style& rBRFromT, /// Vertical frame border from top to bottom-right end of rTLBR.
const Style& rBRFromL, /// Horizontal frame border from left to bottom-right end of rTLBR.
const Style& rBLFromT, /// Vertical frame border from top to bottom-left end of rBLTR.
const Style& rBLFromR, /// Horizontal frame border from right to bottom-left end of rBLTR.
const Style& rTRFromB, /// Vertical frame border from bottom to top-right end of rBLTR.
const Style& rTRFromL, /// Horizontal frame border from left to top-right end of rBLTR.
const Color* pForceColor, /// If specified, overrides frame border color.
bool bDiagDblClip /// true = Use clipping for crossing double frame borders.
const Color* pForceColor /// If specified, overrides frame border color.
);
diff --git a/include/svx/framelinkarray.hxx b/include/svx/framelinkarray.hxx
index 9208f67..15d8dcf 100644
--- a/include/svx/framelinkarray.hxx
+++ b/include/svx/framelinkarray.hxx
@@ -23,6 +23,7 @@
#include <drawinglayer/processor2d/baseprocessor2d.hxx>
#include <svx/framelink.hxx>
#include <svx/svxdllapi.h>
#include <svx/rotmodit.hxx>
#include <memory>
#include <vector>
@@ -119,6 +120,12 @@ public:
/** Sets the bottom frame style of the specified row. Ignores merged ranges. */
void SetRowStyleBottom( size_t nRow, const Style& rStyle );
/** Sets the rotation parameters of the cell (nCol,nRow). Ignores merged ranges. */
void SetCellRotation(size_t nCol, size_t nRow, SvxRotateMode eRotMode, double fOrientation);
/** Check if at least one cell is rotated */
bool HasCellRotation() const;
/** Returns the left frame style of the cell (nCol,nRow).
Returns thicker of own left style or right style of the cell to the left.
Returns the style only if visible (i.e. at left border of a merged range).
@@ -246,9 +253,6 @@ public:
clipped too. This array can handle only one clip range at a time. */
void SetClipRange( size_t nFirstCol, size_t nFirstRow, size_t nLastCol, size_t nLastRow );
/** Returns the rectangle (output coordinates) of the current clipping range. */
tools::Rectangle GetClipRangeRectangle() const;
// cell coordinates -------------------------------------------------------
/** Sets the X output coordinate of the left column. */
@@ -313,14 +317,6 @@ public:
Returns the vertical angle of merged ranges. */
double GetVerDiagAngle( size_t nCol, size_t nRow ) const;
/** Specifies whether to use polygon clipping to draw diagonal frame borders.
@descr
If enabled, diagonal frame borders are drawn interrupted, if they are
crossed by a double frame border. Polygon clipping is very expensive
and should only be used for very small output devices (i.e. in the
Border tab page). Default after construction is OFF. */
void SetUseDiagDoubleClipping( bool bSet );
// mirroring --------------------------------------------------------------
/** Mirrors the entire array horizontally. */
@@ -336,16 +332,6 @@ public:
size_t nLastCol, size_t nLastRow,
const Color* pForceColor ) const;
/** Draws the part of the specified range, that is inside the clipping range.
@param pForceColor
If not NULL, only this color will be used to draw all frame borders. */
void DrawRange( OutputDevice& rDev,
size_t nFirstCol, size_t nFirstRow,
size_t nLastCol, size_t nLastRow ) const;
/** Draws the part of the array, that is inside the clipping range. */
void DrawArray(OutputDevice& rDev) const;
/** Draws the part of the array, that is inside the clipping range. */
void DrawArray(drawinglayer::processor2d::BaseProcessor2D& rProcessor) const;
diff --git a/sc/source/core/data/fillinfo.cxx b/sc/source/core/data/fillinfo.cxx
index e5aadd5..a7d9912 100644
--- a/sc/source/core/data/fillinfo.cxx
+++ b/sc/source/core/data/fillinfo.cxx
@@ -936,7 +936,6 @@ void ScDocument::FillInfo(
svx::frame::Array& rArray = rTabInfo.maArray;
rArray.Initialize( nColCount, nRowCount );
rArray.SetUseDiagDoubleClipping( false );
for( size_t nRow = 0; nRow < nRowCount; ++nRow )
{
diff --git a/sc/source/ui/inc/output.hxx b/sc/source/ui/inc/output.hxx
index 8aeee70..5345b69 100644
--- a/sc/source/ui/inc/output.hxx
+++ b/sc/source/ui/inc/output.hxx
@@ -196,7 +196,6 @@ private:
bool bSnapPixel;
bool bAnyRotated; // internal
bool bAnyClipped; // internal
bool bTabProtected;
bool bLayoutRTL;
@@ -302,7 +301,7 @@ public:
// with logic MapMode set!
void DrawEdit(bool bPixelToLogic);
void FindRotated();
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 0a7f9de..8fd5909 100644
--- a/sc/source/ui/miscdlgs/autofmt.cxx
+++ b/sc/source/ui/miscdlgs/autofmt.cxx
@@ -36,6 +36,7 @@
#include <vcl/builderfactory.hxx>
#include <sfx2/viewfrm.hxx>
#include <comphelper/processfactory.hxx>
#include <drawinglayer/processor2d/processor2dtools.hxx>
#include "strings.hrc"
#include "scmod.hxx"
@@ -393,7 +394,19 @@ void ScAutoFmtPreview::PaintCells(vcl::RenderContext& rRenderContext)
// 3) border
if (pCurData->GetIncludeFrame())
maArray.DrawArray(rRenderContext);
{
const drawinglayer::geometry::ViewInformation2D aNewViewInformation2D;
std::unique_ptr<drawinglayer::processor2d::BaseProcessor2D> pProcessor2D(
drawinglayer::processor2d::createPixelProcessor2DFromOutputDevice(
rRenderContext,
aNewViewInformation2D));
if (pProcessor2D)
{
maArray.DrawArray(*pProcessor2D.get());
pProcessor2D.reset();
}
}
}
}
@@ -401,7 +414,7 @@ void ScAutoFmtPreview::Init()
{
SetBorderStyle( WindowBorderStyle::MONO );
maArray.Initialize( 5, 5 );
maArray.SetUseDiagDoubleClipping( false );
// maArray.SetUseDiagDoubleClipping( false );
mnLabelColWidth = 0;
mnDataColWidth1 = 0;
mnDataColWidth2 = 0;
diff --git a/sc/source/ui/view/gridwin4.cxx b/sc/source/ui/view/gridwin4.cxx
index 68a1ec5..a0ea195 100644
--- a/sc/source/ui/view/gridwin4.cxx
+++ b/sc/source/ui/view/gridwin4.cxx
@@ -699,6 +699,10 @@ 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(MapUnit::MapPixel);
diff --git a/sc/source/ui/view/output.cxx b/sc/source/ui/view/output.cxx
index b6d7363..f4db5fe 100644
--- a/sc/source/ui/view/output.cxx
+++ b/sc/source/ui/view/output.cxx
@@ -183,7 +183,6 @@ ScOutputData::ScOutputData( OutputDevice* pNewDev, ScOutputType eNewType,
bShowSpellErrors( false ),
bMarkClipped( false ), // sal_False for printer/metafile etc.
bSnapPixel( false ),
bAnyRotated( false ),
bAnyClipped( false ),
mpTargetPaintWindow(nullptr), // #i74769# use SdrPaintWindow direct
mpSpellCheckCxt(nullptr)
@@ -618,7 +617,7 @@ void ScOutputData::SetPagebreakMode( ScPageBreakData* pPageData )
}
}
void ScOutputData::FindRotated()
void ScOutputData::SetCellRotations()
{
//! save nRotMax
SCCOL nRotMax = nX2;
@@ -652,8 +651,16 @@ void ScOutputData::FindRotated()
ScRotateDir nDir = pPattern->GetRotateDir( pCondSet );
if (nDir != ScRotateDir::NONE)
{
// Needed for CellInfo internal decisions (bg fill, ...)
pInfo->nRotateDir = nDir;
bAnyRotated = true;
// add rotation info to Array information
const long nAttrRotate(pPattern->GetRotateVal(pCondSet));
const SvxRotateMode eRotMode((SvxRotateMode)static_cast<const SvxRotateModeItem&>(pPattern->GetItem(ATTR_ROTATE_MODE, pCondSet)).GetValue());
const double fOrient((bLayoutRTL ? -1.0 : 1.0) * nAttrRotate * F_PI18000); // 1/100th degrees -> [0..2PI]
svx::frame::Array& rArray = mrTabInfo.maArray;
rArray.SetCellRotation(nY+1, nX+1, eRotMode, fOrient);
}
}
}
@@ -985,8 +992,6 @@ void drawCells(vcl::RenderContext& rRenderContext, const Color* pColor, const Sv
void ScOutputData::DrawBackground(vcl::RenderContext& rRenderContext)
{
FindRotated(); //! from the outside?
Size aOnePixel = rRenderContext.PixelToLogic(Size(1,1));
long nOneXLogic = aOnePixel.Width();
long nOneYLogic = aOnePixel.Height();
@@ -1380,8 +1385,10 @@ void ScOutputData::DrawFrame(vcl::RenderContext& rRenderContext)
const Color* pForceColor = bUseSingleColor ? &aSingleColor : nullptr;
if (bAnyRotated)
if (mrTabInfo.maArray.HasCellRotation())
{
DrawRotatedFrame(rRenderContext, pForceColor); // removes the lines that must not be painted here
}
long nInitPosX = nScrX;
if ( bLayoutRTL )
@@ -1617,16 +1624,16 @@ void ScOutputData::DrawRotatedFrame(vcl::RenderContext& rRenderContext, const Co
SvxRotateMode eRotMode = (SvxRotateMode)static_cast<const SvxRotateModeItem&>(
pPattern->GetItem(ATTR_ROTATE_MODE, pCondSet)).GetValue();
if ( nAttrRotate )
if (nAttrRotate)
{
if (nX<nX1) // compute negative position
if (nX < nX1) // compute negative position
{
nPosX = nInitPosX;
SCCOL nCol = nX1;
while (nCol > nX)
{
--nCol;
nPosX -= nLayoutSign * (long) pRowInfo[0].pCellInfo[nCol+1].nWidth;
nPosX -= nLayoutSign * (long)pRowInfo[0].pCellInfo[nCol + 1].nWidth;
}
}
@@ -1636,248 +1643,100 @@ void ScOutputData::DrawRotatedFrame(vcl::RenderContext& rRenderContext, const Co
long nTop = nPosY - 1;
long nBottom = nPosY + nRowHeight - 1;
long nTopLeft = nPosX - nLayoutSign;
long nTopRight = nPosX + ( nColWidth - 1 ) * nLayoutSign;
long nTopRight = nPosX + (nColWidth - 1) * nLayoutSign;
long nBotLeft = nTopLeft;
long nBotRight = nTopRight;
// inclusion of the sign here hasn't been decided yet
// (if not, the extension of the non-rotated background must also be changed)
double nRealOrient = nLayoutSign * nAttrRotate * F_PI18000; // 1/100th degrees
double nCos = cos( nRealOrient );
double nSin = sin( nRealOrient );
double nCos = cos(nRealOrient);
double nSin = sin(nRealOrient);
//! restrict !!!
long nSkew = (long) ( nRowHeight * nCos / nSin );
long nSkew = (long)(nRowHeight * nCos / nSin);
switch (eRotMode)
{
case SVX_ROTATE_MODE_BOTTOM:
nTopLeft += nSkew;
nTopRight += nSkew;
break;
case SVX_ROTATE_MODE_CENTER:
nSkew /= 2;
nTopLeft += nSkew;
nTopRight += nSkew;
nBotLeft -= nSkew;
nBotRight -= nSkew;
break;
case SVX_ROTATE_MODE_TOP:
nBotLeft -= nSkew;
nBotRight -= nSkew;
break;
default:
{
// added to avoid warnings
}
case SVX_ROTATE_MODE_BOTTOM:
nTopLeft += nSkew;
nTopRight += nSkew;
break;
case SVX_ROTATE_MODE_CENTER:
nSkew /= 2;
nTopLeft += nSkew;
nTopRight += nSkew;
nBotLeft -= nSkew;
nBotRight -= nSkew;
break;
case SVX_ROTATE_MODE_TOP:
nBotLeft -= nSkew;
nBotRight -= nSkew;
break;
default:
{
// added to avoid warnings
}
}
Point aPoints[4];
aPoints[0] = Point( nTopLeft, nTop );
aPoints[1] = Point( nTopRight, nTop );
aPoints[2] = Point( nBotRight, nBottom );
aPoints[3] = Point( nBotLeft, nBottom );
aPoints[0] = Point(nTopLeft, nTop);
aPoints[1] = Point(nTopRight, nTop);
aPoints[2] = Point(nBotRight, nBottom);
aPoints[3] = Point(nBotLeft, nBottom);
const SvxBrushItem* pBackground = pInfo->pBackground;
if (!pBackground)
pBackground = static_cast<const SvxBrushItem*>( &pPattern->GetItem(
ATTR_BACKGROUND, pCondSet ));
pBackground = static_cast<const SvxBrushItem*>(&pPattern->GetItem(
ATTR_BACKGROUND, pCondSet));
if (bCellContrast)
{
// high contrast for cell borders and backgrounds -> empty background
pBackground = ScGlobal::GetEmptyBrushItem();
}
if(!pInfo->pColorScale)
if (!pInfo->pColorScale)
{
const Color& rColor = pBackground->GetColor();
if ( rColor.GetTransparency() != 255 )
if (rColor.GetTransparency() != 255)
{
// draw background only for the changed row itself
// (background doesn't extend into other cells).
// For the borders (rotated and normal), clipping should be
// set if the row isn't changed, but at least the borders
// don't cover the cell contents.
if ( rThisRowInfo.bChanged )
if (rThisRowInfo.bChanged)
{
tools::Polygon aPoly( 4, aPoints );
tools::Polygon aPoly(4, aPoints);
// for DrawPolygon, whitout Pen one pixel is left out
// to the right and below...
if ( rColor.GetTransparency() == 0 )
if (rColor.GetTransparency() == 0)
rRenderContext.SetLineColor(rColor);
else
rRenderContext.SetLineColor();
rRenderContext.SetFillColor(rColor);
rRenderContext.DrawPolygon( aPoly );
rRenderContext.DrawPolygon(aPoly);
}
}
}
else
{
tools::Polygon aPoly( 4, aPoints );
tools::Polygon aPoly(4, aPoints);
const Color* pColor = pInfo->pColorScale.get();
// for DrawPolygon, whitout Pen one pixel is left out
// to the right and below...
if ( pColor->GetTransparency() == 0 )
if (pColor->GetTransparency() == 0)
rRenderContext.SetLineColor(*pColor);
else
rRenderContext.SetLineColor();
rRenderContext.SetFillColor(*pColor);
rRenderContext.DrawPolygon( aPoly );
rRenderContext.DrawPolygon(aPoly);
}
svx::frame::Style aTopLine, aBottomLine, aLeftLine, aRightLine;
if ( nX < nX1 || nX > nX2 ) // Attributes in FillInfo not set
{
//! consider page borders for printing !!!!!
const ::editeng::SvxBorderLine* pLeftLine;
const ::editeng::SvxBorderLine* pTopLine;
const ::editeng::SvxBorderLine* pRightLine;
const ::editeng::SvxBorderLine* pBottomLine;
mpDoc->GetBorderLines( nX, nY, nTab,
&pLeftLine, &pTopLine, &pRightLine, &pBottomLine );
aTopLine.Set( pTopLine, mnPPTY );
aBottomLine.Set( pBottomLine, mnPPTY );
aLeftLine.Set( pLeftLine, mnPPTX );
aRightLine.Set( pRightLine, mnPPTX );
}
else
{
size_t nCol = lclGetArrayColFromCellInfoX( nArrX, nX1, nX2, bLayoutRTL );
aTopLine = rArray.GetCellStyleTop( nCol, nRow );
aBottomLine = rArray.GetCellStyleBottom( nCol, nRow );
aLeftLine = rArray.GetCellStyleLeft( nCol, nRow );
aRightLine = rArray.GetCellStyleRight( nCol, nRow );
// in RTL mode the array is already mirrored -> swap back left/right borders
if( bLayoutRTL )
std::swap( aLeftLine, aRightLine );
}
// Horizontal lines
if (aTopLine.Prim() || aTopLine.Secn())
{
long nUpperRotate = lcl_getRotate( mpDoc, nTab, nX, nY - 1 );
drawinglayer::primitive2d::Primitive2DContainer aSequence(1);
svx::frame::CreateBorderPrimitives(
aSequence,
aPoints[bLayoutRTL?1:0], aPoints[bLayoutRTL?0:1], aTopLine,
svx::frame::Style(),
svx::frame::Style(),
aLeftLine,
svx::frame::Style(),
svx::frame::Style(),
aRightLine,
pForceColor, nUpperRotate, nAttrRotate );
pProcessor->process(aSequence);
}
if (aBottomLine.Prim() || aBottomLine.Secn())
{
long nLowerRotate = lcl_getRotate( mpDoc, nTab, nX, nY + 1 );
drawinglayer::primitive2d::Primitive2DContainer aSequence(1);
svx::frame::CreateBorderPrimitives(
aSequence,
aPoints[bLayoutRTL?2:3], aPoints[bLayoutRTL?3:2], aBottomLine,
aLeftLine,
svx::frame::Style(),
svx::frame::Style(),
aRightLine,
svx::frame::Style(),
svx::frame::Style(),
pForceColor, 18000 - nAttrRotate, 18000 - nLowerRotate );
pProcessor->process(aSequence);
}
// Vertical slanted lines
if (aLeftLine.Prim() || aLeftLine.Secn())
{
long nLeftRotate = lcl_getRotate( mpDoc, nTab, nX - 1, nY );
drawinglayer::primitive2d::Primitive2DContainer aSequence(1);
svx::frame::CreateBorderPrimitives(
aSequence,
aPoints[0], aPoints[3], aLeftLine,
aTopLine,
svx::frame::Style(),
svx::frame::Style(),
aBottomLine,
svx::frame::Style(),
svx::frame::Style(),
pForceColor, nAttrRotate, nLeftRotate );
pProcessor->process(aSequence);
}
if (aRightLine.Prim() || aRightLine.Secn())
{
long nRightRotate = lcl_getRotate( mpDoc, nTab, nX + 1, nY );
drawinglayer::primitive2d::Primitive2DContainer aSequence(1);
svx::frame::CreateBorderPrimitives(
aSequence,
aPoints[1], aPoints[2], aRightLine,
svx::frame::Style(),
svx::frame::Style(),
aTopLine,
svx::frame::Style(),
svx::frame::Style(),
aBottomLine,
pForceColor, 18000 - nRightRotate, 18000 - nAttrRotate );
pProcessor->process(aSequence);
}
}
}
nPosX += nColWidth * nLayoutSign;
}
// delete the lines for normal output only afterwards in the second step
nX = nX1 > 0 ? (nX1-1) : static_cast<SCCOL>(0);
for (; nX<=nX2+1; nX++) // visible part +- 1
{
sal_uInt16 nArrX = nX + 1;
CellInfo& rInfo = rThisRowInfo.pCellInfo[nArrX];
if ( rInfo.nRotateDir > ScRotateDir::Standard &&
!rInfo.bHOverlapped && !rInfo.bVOverlapped )
{
size_t nCol = lclGetArrayColFromCellInfoX( nArrX, nX1, nX2, bLayoutRTL );
// horizontal: extend adjacent line
// (only when the rotated cell has a border)
ScRotateDir nDir = rInfo.nRotateDir;
if ( rArray.GetCellStyleTop( nCol, nRow ).Prim() )
{
svx::frame::Style aStyle( lcl_FindHorLine( mpDoc, nX, nY, nTab, nDir, true ), mnPPTY );
rArray.SetCellStyleTop( nCol, nRow, aStyle );
if( nRow > 0 )
rArray.SetCellStyleBottom( nCol, nRow - 1, aStyle );
}
if ( rArray.GetCellStyleBottom( nCol, nRow ).Prim() )
{
svx::frame::Style aStyle( lcl_FindHorLine( mpDoc, nX, nY, nTab, nDir, false ), mnPPTY );
rArray.SetCellStyleBottom( nCol, nRow, aStyle );
if( nRow + 1 < rArray.GetRowCount() )
rArray.SetCellStyleTop( nCol, nRow + 1, aStyle );
}
// always remove vertical borders
if( !rArray.IsMergedOverlappedLeft( nCol, nRow ) )
{
rArray.SetCellStyleLeft( nCol, nRow, svx::frame::Style() );
if( nCol > 0 )
rArray.SetCellStyleRight( nCol - 1, nRow, svx::frame::Style() );
}
if( !rArray.IsMergedOverlappedRight( nCol, nRow ) )
{
rArray.SetCellStyleRight( nCol, nRow, svx::frame::Style() );
if( nCol + 1 < rArray.GetColCount() )
rArray.SetCellStyleLeft( nCol + 1, nRow, svx::frame::Style() );
}
// remove diagonal borders
rArray.SetCellStyleTLBR( nCol, nRow, svx::frame::Style() );
rArray.SetCellStyleBLTR( nCol, nRow, svx::frame::Style() );
}
}
}
nPosY += nRowHeight;
}
diff --git a/sc/source/ui/view/output2.cxx b/sc/source/ui/view/output2.cxx
index 7191d28..7658a37 100644
--- a/sc/source/ui/view/output2.cxx
+++ b/sc/source/ui/view/output2.cxx
@@ -4632,8 +4632,10 @@ void ScOutputData::DrawEdit(bool bPixelToLogic)
pEngine.reset();
if (bAnyRotated)
if (mrTabInfo.maArray.HasCellRotation())
{
DrawRotated(bPixelToLogic); //! call from outside ?
}
}
void ScOutputData::DrawRotated(bool bPixelToLogic)
diff --git a/svx/source/dialog/framelink.cxx b/svx/source/dialog/framelink.cxx
index 3dd1b5f..c193285 100644
--- a/svx/source/dialog/framelink.cxx
+++ b/svx/source/dialog/framelink.cxx
@@ -44,146 +44,6 @@ namespace frame {
namespace {
typedef std::vector< Point > PointVec;
// Link result structs for horizontal and vertical lines and borders.
/** Result struct used by the horizontal/vertical frame link functions.
This struct is used to return coordinate offsets for one end of a single
line in a frame border, i.e. the left end of the primary line of a
horizontal frame border.
1) Usage for horizontal lines
If this struct is returned by the lclLinkHorFrameBorder() function, each
member refers to the X coordinate of one edge of a single line end in a
horizontal frame border. They specify an offset to modify this coordinate
when the line is painted. The values in this struct may change a
rectangular line shape into a line with slanted left or right border, which
is used to connect the line with diagonal lines.
Usage for a left line end: Usage for a right line end:
mnOffs1 mnOffs1
<-------> <------->
+-------------------------------+
| the original horizontal line |
+-------------------------------+
<-------> <------->
mnOffs2 mnOffs2
2) Usage for vertical lines
If this struct is returned by the lclLinkVerFrameBorder() function, each
member refers to the Y coordinate of one edge of a single line end in a
vertical frame border. They specify an offset to modify this coordinate
when the line is painted. The values in this struct may change a
rectangular line shape into a line with slanted top or bottom border, which
is used to connect the line with diagonal lines.
Usage for a top line end: mnOffs1 ^ ^ mnOffs2
| +-------+ |
v | | v
| |
| |
the original vertical line ---> | |
| |
| |
^ | | ^
| +-------+ |
Usage for a bottom line end: mnOffs1 v v mnOffs2
*/
struct LineEndResult
{
long mnOffs1; /// Offset for top or left edge, dependent of context.
long mnOffs2; /// Offset for bottom or right edge, dependent of context
explicit LineEndResult() : mnOffs1( 0 ), mnOffs2( 0 ) {}
void Swap() { std::swap( mnOffs1, mnOffs2 ); }
void Negate() { mnOffs1 = -mnOffs1; mnOffs2 = -mnOffs2; }
};
/** Result struct used by the horizontal/vertical frame link functions.
This struct contains the linking results for one end of a frame border,
including both the primary and secondary line ends.
*/
struct BorderEndResult
{
LineEndResult maPrim; /// Result for primary line.
LineEndResult maSecn; /// Result for secondary line.
LineEndResult maGap; /// Result for gap line.
void Negate() { maPrim.Negate(); maSecn.Negate(); maGap.Negate(); }
};
/** Result struct used by the horizontal/vertical frame link functions.
This struct contains the linking results for both frame border ends, and
therefore for the complete frame border.
*/
struct BorderResult
{
BorderEndResult maBeg; /// Result for begin of border line (left or top end).
BorderEndResult maEnd; /// Result for end of border line (right or bottom end).
};
// Link result structs for diagonal lines and borders.
/** Result struct used by the diagonal frame link functions.
This struct contains the linking results for one line of a diagonal frame
border.
*/
struct DiagLineResult
{
long mnLClip; /// Offset for left border of clipping rectangle.
long mnRClip; /// Offset for right border of clipping rectangle.
long mnTClip; /// Offset for top border of clipping rectangle.
long mnBClip; /// Offset for bottom border of clipping rectangle.
explicit DiagLineResult() : mnLClip( 0 ), mnRClip( 0 ), mnTClip( 0 ), mnBClip( 0 ) {}
};
/** Result struct used by the diagonal frame link functions.
This struct contains the linking results for one diagonal frame border.
*/
struct DiagBorderResult
{
DiagLineResult maPrim; /// Result for primary line.
DiagLineResult maSecn; /// Result for secondary line.
};
/** Result struct used by the diagonal frame link functions.
This struct contains the linking results for both diagonal frame borders.
*/
struct DiagBordersResult
{
DiagBorderResult maTLBR; /// Result for top-left to bottom-right frame border.
DiagBorderResult maBLTR; /// Result for bottom-left to top-right frame border.
};
/** A helper struct containing two points of a line.
*/
struct LinePoints
{
Point maBeg; /// Start position of the line.
Point maEnd; /// End position of the line.
explicit LinePoints( const Point& rBeg, const Point& rEnd ) :
maBeg( rBeg ), maEnd( rEnd ) {}
explicit LinePoints( const tools::Rectangle& rRect, bool bTLBR ) :
maBeg( bTLBR ? rRect.TopLeft() : rRect.TopRight() ),
maEnd( bTLBR ? rRect.BottomRight() : rRect.BottomLeft() ) {}
};
/** Rounds and casts a double value to a long value. */
inline long lclD2L( double fValue )
{
@@ -196,920 +56,6 @@ double lclScaleValue( double nValue, double fScale, sal_uInt16 nMaxWidth )
return std::min<double>(nValue * fScale, nMaxWidth);
}
// Line width offset calculation.
/** Returns the start offset of the single/primary line across the frame border.
All following lclGet*Beg() and lclGet*End() functions return sub units to
increase the computational accuracy, where 256 sub units are equal to
1 map unit of the used OutputDevice.
The following pictures show the upper end of a vertical frame border and
illustrates the return values of all following lclGet*Beg() and lclGet*End()
functions. The first picture shows a single frame border, the second picture
shows a double frame border.
The functions regard the reference point handling mode of the passed border
style.
RefMode::Centered:
All returned offsets are relative to the middle position of the frame
border (offsets left of the middle are returned negative, offsets right
of the middle are returned positive).
RefMode::Begin:
All returned offsets are relative to the begin of the frame border
(lclGetBeg() always returns 0).
RefMode::End:
All returned offsets are relative to the end of the frame border
(lclGetEnd() always returns 0).
|<- lclGetEnd()
|<- lclGetBeforeBeg() |<- lclGetPrimEnd()
| |
||<- lclGetBeg() ||<- lclGetBehindEnd()
|| ||
|#################################|
direction of | #################################
the frame | #################################
border is | #################################
vertical | #################################
v #################################
|
|<- middle of the frame border
lclGetDistEnd() ->||<- lclGetSecnBeg()
||
lclGetBeg() ->| lclGetDistBeg() ->| || |<- lclGetEnd()
| | || |
lclGetBeforeBeg()->|| lclGetPrimEnd() ->|| || ||<- lclGetBehindEnd()
|| || || ||
|######################| |#############|
direction of | ###################### #############
the frame | ###################### #############
border is | ###################### #############
vertical | ###################### | #############
v ###################### | #############
primary line | secondary line
|
|<- middle of the frame border
@return
The start offset of the single/primary line relative to the reference
position of the frame border (sub units; 0 for invisible or one pixel
wide single frame styles).
*/
long lclGetBeg( const Style& rBorder )
{
long nPos = 0;
switch( rBorder.GetRefMode() )
{
case RefMode::Centered: if( rBorder.Prim() ) nPos = -128 * (rBorder.GetWidth() - 1); break;
case RefMode::End: if( rBorder.Prim() ) nPos = -256 * (rBorder.GetWidth() - 1); break;
case RefMode::Begin: break;
}
return nPos;
}
/** Returns the end offset of the single/secondary line across the frame border.
@descr See description of lclGetBeg() for an illustration.
@return The end offset of the single/secondary line relative to the
reference position of the frame border (sub units; 0 for invisible or one
pixel wide single frame styles). */
long lclGetEnd( const Style& rBorder )
{
long nPos = 0;
switch( rBorder.GetRefMode() )
{
case RefMode::Centered: if( rBorder.Prim() ) nPos = 128 * (rBorder.GetWidth() - 1); break;
case RefMode::Begin: if( rBorder.Prim() ) nPos = 256 * (rBorder.GetWidth() - 1); break;
case RefMode::End: break;
}
return nPos;
}
/** Returns the end offset of the primary line across the frame border.
@descr See description of lclGetBeg() for an illustration.
@return The end offset of the primary line relative to the reference
position of the frame border (sub units; the end of the primary line in a
double frame style, otherwise the same as lclGetEnd()). */
inline long lclGetPrimEnd( const Style& rBorder )
{ return rBorder.Prim() ? (lclGetBeg( rBorder ) + 256 * (rBorder.Prim() - 1)) : 0; }
/** Returns the start offset of the secondary line across the frame border.
@descr See description of lclGetBeg() for an illustration.
@return The start offset of the secondary line relative to the reference
position of the frame border (sub units; 0 for single/invisible border
styles). */
inline long lclGetSecnBeg( const Style& rBorder )
{ return rBorder.Secn() ? (lclGetEnd( rBorder ) - 256 * (rBorder.Secn() - 1)) : 0; }
/** Returns the start offset of the distance space across the frame border.
@descr See description of lclGetBeg() for an illustration.
@return The start offset of the distance space relative to the reference
position of the frame border (sub units; 0 for single/invisible border
styles). */
inline long lclGetDistBeg( const Style& rBorder )
{ return rBorder.Secn() ? (lclGetBeg( rBorder ) + 256 * rBorder.Prim()) : 0; }
/** Returns the end offset of the distance space across the frame border.
@descr See description of lclGetBeg() for an illustration.
@return The end offset of the distance space relative to the reference
position of the frame border (sub units; 0 for single/invisible border
styles). */
inline long lclGetDistEnd( const Style& rBorder )
{ return rBorder.Secn() ? (lclGetEnd( rBorder ) - 256 * rBorder.Secn()) : 0; }
/** Returns the offset before start of single/primary line across the frame border.
@descr See description of lclGetBeg() for an illustration.
@return The offset directly before start of single/primary line relative
to the reference position of the frame border (sub units; a value one less
than lclGetBeg() for visible frame styles, or 0 for invisible frame style). */
inline long lclGetBeforeBeg( const Style& rBorder )
{ return rBorder.Prim() ? (lclGetBeg( rBorder ) - 256) : 0; }
/** Returns the offset behind end of single/secondary line across the frame border.
@descr See description of lclGetBeg() for an illustration.
@return The offset directly behind end of single/secondary line relative
to the reference position of the frame border (sub units; a value one
greater than lclGetEnd() for visible frame styles, or 0 for invisible frame
style). */
inline long lclGetBehindEnd( const Style& rBorder )
{ return rBorder.Prim() ? (lclGetEnd( rBorder ) + 256) : 0; }
// Linking functions
// Linking of single horizontal line ends.
/** Calculates X offsets for the left end of a single horizontal frame border.
See DrawHorFrameBorder() function for a description of all parameters.
@param rResult
(out-param) The contained values (sub units) specify offsets for the
X coordinates of the left line end.
*/
void lclLinkLeftEnd_Single(
LineEndResult& rResult, const Style& rBorder,
const DiagStyle& rLFromTR, const Style& rLFromT, const Style& rLFromL, const Style& rLFromB, const DiagStyle& rLFromBR )
{
// both vertical and diagonal frame borders are double
if( rLFromT.Secn() && rLFromB.Secn() && rLFromTR.Secn() && rLFromBR.Secn() )
{
// take left position of upper and lower secondary start
rResult.mnOffs1 = GetBLDiagOffset( lclGetBeg( rBorder ), lclGetSecnBeg( rLFromTR ), rLFromTR.GetAngle() );
rResult.mnOffs2 = GetTLDiagOffset( lclGetEnd( rBorder ), lclGetSecnBeg( rLFromBR ), rLFromBR.GetAngle() );
}
else
{
// both vertical frame borders are double
if( rLFromT.Secn() && rLFromB.Secn() )
{
rResult.mnOffs1 = (!rLFromTR.Secn() && !rLFromBR.Secn() && rtl::math::approxEqual(rLFromT.GetWidth(), rLFromB.GetWidth())) ?
// don't overdraw vertical borders with equal width
lclGetBehindEnd( rLFromT ) :
// take leftmost start of both secondary lines (#46488#)
std::min( lclGetSecnBeg( rLFromT ), lclGetSecnBeg( rLFromB ) );
}
// single border with equal width coming from left
else if( !rLFromL.Secn() && rtl::math::approxEqual(rLFromL.Prim(), rBorder.Prim()) )
// draw to connection point
rResult.mnOffs1 = 0;
// single border coming from left
else if( !rLFromL.Secn() && rLFromL.Prim() )
{
if( rtl::math::approxEqual(rLFromL.Prim(), rBorder.Prim()) )
// draw to reference position, if from left has equal width
rResult.mnOffs1 = 0;
else
rResult.mnOffs1 = (rLFromL < rBorder) ?
// take leftmost start of both frame borders, if from left is thinner
std::min( lclGetBeg( rLFromT ), lclGetBeg( rLFromB ) ) :
// do not overdraw vertical, if from left is thicker
std::max( lclGetBehindEnd( rLFromT ), lclGetBehindEnd( rLFromB ) );
}
// no border coming from left
else if( !rLFromL.Prim() )
// don't overdraw vertical borders with equal width
rResult.mnOffs1 = rtl::math::approxEqual(rLFromT.GetWidth(), rLFromB.GetWidth()) ?
lclGetBehindEnd( rLFromT ) :
std::min( lclGetBeg( rLFromT ), lclGetBeg( rLFromB ) );
// double frame border coming from left and from top
else if( rLFromT.Secn() )
// do not overdraw the vertical double frame border
rResult.mnOffs1 = lclGetBehindEnd( rLFromT );
// double frame border coming from left and from bottom
else if( rLFromB.Secn() )
// do not overdraw the vertical double frame border
rResult.mnOffs1 = lclGetBehindEnd( rLFromB );
// double frame border coming from left, both vertical frame borders are single or off
else
// draw from leftmost start of both frame borders, if from left is not thicker
rResult.mnOffs1 = (rLFromL <= rBorder) ?
std::min( lclGetBeg( rLFromT ), lclGetBeg( rLFromB ) ) :
std::max( lclGetBehindEnd( rLFromT ), lclGetBehindEnd( rLFromB ) );
// bottom-left point is equal to top-left point (results in rectangle)
rResult.mnOffs2 = rResult.mnOffs1;
}
}
/** Calculates X offsets for the left end of a primary horizontal line.
See DrawHorFrameBorder() function for a description of all parameters.
@param rResult
(out-param) The contained values (sub units) specify offsets for the
X coordinates of the left end of the primary line.
*/
void lclLinkLeftEnd_Prim(
LineEndResult& rResult, const Style& rBorder,
const DiagStyle& rLFromTR, const Style& rLFromT, const Style& rLFromL, const Style& rLFromB, const DiagStyle& /*rLFromBR*/ )
{
// double diagonal frame border coming from top right
if( rLFromTR.Secn() )
{
// draw from where secondary diagonal line meets the own primary
rResult.mnOffs1 = GetBLDiagOffset( lclGetBeg( rBorder ), lclGetSecnBeg( rLFromTR ), rLFromTR.GetAngle() );
rResult.mnOffs2 = GetBLDiagOffset( lclGetPrimEnd( rBorder ), lclGetSecnBeg( rLFromTR ), rLFromTR.GetAngle() );
}
// no or single diagonal frame border - ignore it
else
{
// double frame border coming from top
if( rLFromT.Secn() )
// draw from left edge of secondary vertical
rResult.mnOffs1 = lclGetSecnBeg( rLFromT );
// double frame border coming from left (from top is not double)
else if( rLFromL.Secn() )
// do not overdraw single frame border coming from top
rResult.mnOffs1 = rtl::math::approxEqual(rLFromL.GetWidth(), rBorder.GetWidth()) ?
0 : lclGetBehindEnd( rLFromT );
// double frame border coming from bottom (from top and from left are not double)
else if( rLFromB.Secn() )
// draw from left edge of primary vertical from bottom
rResult.mnOffs1 = lclGetBeg( rLFromB );
// no other frame border is double
else
// do not overdraw vertical frame borders
rResult.mnOffs1 = std::max( lclGetBehindEnd( rLFromT ), lclGetBehindEnd( rLFromB ) );
// bottom-left point is equal to top-left point (results in rectangle)
rResult.mnOffs2 = rResult.mnOffs1;
}
}
/** Calculates X offsets for the left end of a secondary horizontal line.
See DrawHorFrameBorder() function for a description of all parameters.
@param rResult
(out-param) The contained values (sub units) specify offsets for the
X coordinates of the left end of the secondary line.
*/
void lclLinkLeftEnd_Secn(
LineEndResult& rResult, const Style& rBorder,
const DiagStyle& rLFromTR, const Style& rLFromT, const Style& rLFromL, const Style& rLFromB, const DiagStyle& rLFromBR )
{
/* Recycle lclLinkLeftEnd_Prim() function with mirrored horizontal borders. */
lclLinkLeftEnd_Prim( rResult, rBorder.Mirror(), rLFromBR, rLFromB, rLFromL.Mirror(), rLFromT, rLFromTR );
rResult.Swap();
}
void lclLinkLeftEnd_Gap(
LineEndResult& rResult, const Style& rBorder,
const DiagStyle& /*rLFromTR*/, const Style& rLFromT, const Style& rLFromL, const Style& rLFromB, const DiagStyle& /*rLFromBR*/ )
{
if ( rLFromT.Secn() )
rResult.mnOffs1 = lclGetDistBeg( rLFromT );
else if ( rLFromL.Secn( ) )
rResult.mnOffs1 = rtl::math::approxEqual( rLFromL.GetWidth(), rBorder.GetWidth() ) ?
0 : lclGetBehindEnd( rLFromT );
else if ( rLFromB.Secn( ) )
rResult.mnOffs1 = lclGetDistBeg( rLFromB );
else
rResult.mnOffs1 = std::max( lclGetBehindEnd( rLFromT ), lclGetBehindEnd( rLFromB ) );
rResult.mnOffs2 = rResult.mnOffs1;
}
// Linking of horizontal frame border ends.
/** Calculates X offsets for the left end of a horizontal frame border.
This function can be used for single and double frame borders.
See DrawHorFrameBorder() function for a description of all parameters.
@param rResult
(out-param) The contained values (sub units) specify offsets for the
X coordinates of the left end of the line(s) in the frame border.
*/
void lclLinkLeftEnd(
BorderEndResult& rResult, const Style& rBorder,
const DiagStyle& rLFromTR, const Style& rLFromT, const Style& rLFromL, const Style& rLFromB, const DiagStyle& rLFromBR )
{
if( rBorder.Secn() )
{
// current frame border is double
lclLinkLeftEnd_Prim( rResult.maPrim, rBorder, rLFromTR, rLFromT, rLFromL, rLFromB, rLFromBR );
lclLinkLeftEnd_Secn( rResult.maSecn, rBorder, rLFromTR, rLFromT, rLFromL, rLFromB, rLFromBR );
lclLinkLeftEnd_Gap( rResult.maGap, rBorder, rLFromTR, rLFromT, rLFromL, rLFromB, rLFromBR );
}
else if( rBorder.Prim() )
{
// current frame border is single
lclLinkLeftEnd_Single( rResult.maPrim, rBorder, rLFromTR, rLFromT, rLFromL, rLFromB, rLFromBR );
}
else
{
SAL_WARN( "svx.dialog", "lclLinkLeftEnd - called for invisible frame style" );
}
}
/** Calculates X offsets for the right end of a horizontal frame border.
This function can be used for single and double frame borders.
See DrawHorFrameBorder() function for a description of all parameters.
@param rResult
(out-param) The contained values (sub units) specify offsets for the
X coordinates of the right end of the line(s) in the frame border.
*/
void lclLinkRightEnd(
BorderEndResult& rResult, const Style& rBorder,
const DiagStyle& rRFromTL, const Style& rRFromT, const Style& rRFromR, const Style& rRFromB, const DiagStyle& rRFromBL )
{
/* Recycle lclLinkLeftEnd() function with mirrored vertical borders. */
lclLinkLeftEnd( rResult, rBorder, rRFromTL.Mirror(), rRFromT.Mirror(), rRFromR, rRFromB.Mirror(), rRFromBL.Mirror() );
rResult.Negate();
}
// Linking of horizontal and vertical frame borders.
/** Calculates X offsets for all line ends of a horizontal frame border.
This function can be used for single and double frame borders.
See DrawHorFrameBorder() function for a description of all parameters.
@param rResult
(out-param) The contained values (sub units) specify offsets for the
X coordinates of both ends of the line(s) in the frame border. To get
the actual X coordinates to draw the lines, these offsets have to be
added to the X coordinates of the reference points of the frame border
(the offsets may be negative).
*/
void lclLinkHorFrameBorder(
BorderResult& rResult, const Style& rBorder,
const DiagStyle& rLFromTR, const Style& rLFromT, const Style& rLFromL, const Style& rLFromB, const DiagStyle& rLFromBR,
const DiagStyle& rRFromTL, const Style& rRFromT, const Style& rRFromR, const Style& rRFromB, const DiagStyle& rRFromBL )
{
lclLinkLeftEnd( rResult.maBeg, rBorder, rLFromTR, rLFromT, rLFromL, rLFromB, rLFromBR );
lclLinkRightEnd( rResult.maEnd, rBorder, rRFromTL, rRFromT, rRFromR, rRFromB, rRFromBL );
}
/** Calculates Y offsets for all line ends of a vertical frame border.
This function can be used for single and double frame borders.
See DrawVerFrameBorder() function for a description of all parameters.
@param rResult
(out-param) The contained values (sub units) specify offsets for the
Y coordinates of both ends of the line(s) in the frame border. To get
the actual Y coordinates to draw the lines, these offsets have to be
added to the Y coordinates of the reference points of the frame border
(the offsets may be negative).
*/
void lclLinkVerFrameBorder(
BorderResult& rResult, const Style& rBorder,
const DiagStyle& rTFromBL, const Style& rTFromL, const Style& rTFromT, const Style& rTFromR, const DiagStyle& rTFromBR,
const DiagStyle& rBFromTL, const Style& rBFromL, const Style& rBFromB, const Style& rBFromR, const DiagStyle& rBFromTR )
{
/* Recycle lclLinkHorFrameBorder() function with correct parameters. The
frame border is virtually mirrored at the top-left to bottom-right
diagonal. rTFromBR and rBFromTL are mirrored to process their primary
and secondary lines correctly. */
lclLinkHorFrameBorder( rResult, rBorder,
rTFromBL, rTFromL, rTFromT, rTFromR, rTFromBR.Mirror(),
rBFromTL.Mirror(), rBFromL, rBFromB, rBFromR, rBFromTR );
}
// Linking of diagonal frame borders.
/** Calculates clipping offsets for a top-left to bottom-right frame border.
This function can be used for single and double frame borders.
See DrawDiagFrameBorders() function for a description of all parameters.
@param rResult
(out-param) The contained values (sub units) specify offsets for all
borders of the reference rectangle containing the diagonal frame border.
*/
void lclLinkTLBRFrameBorder(
DiagBorderResult& rResult, const Style& rBorder,
const Style& rTLFromB, const Style& rTLFromR, const Style& rBRFromT, const Style& rBRFromL )
{
bool bIsDbl = rBorder.Secn() != 0;
rResult.maPrim.mnLClip = lclGetBehindEnd( rTLFromB );
rResult.maPrim.mnRClip = (bIsDbl && rBRFromT.Secn()) ? lclGetEnd( rBRFromT ) : lclGetBeforeBeg( rBRFromT );
rResult.maPrim.mnTClip = (bIsDbl && rTLFromR.Secn()) ? lclGetBeg( rTLFromR ) : lclGetBehindEnd( rTLFromR );
rResult.maPrim.mnBClip = lclGetBeforeBeg( rBRFromL );
if( bIsDbl )
{
rResult.maSecn.mnLClip = rTLFromB.Secn() ? lclGetBeg( rTLFromB ) : lclGetBehindEnd( rTLFromB );
rResult.maSecn.mnRClip = lclGetBeforeBeg( rBRFromT );
rResult.maSecn.mnTClip = lclGetBehindEnd( rTLFromR );
rResult.maSecn.mnBClip = rBRFromL.Secn() ? lclGetEnd( rBRFromL ) : lclGetBeforeBeg( rBRFromL );
}
}
/** Calculates clipping offsets for a bottom-left to top-right frame border.
This function can be used for single and double frame borders.
See DrawDiagFrameBorders() function for a description of all parameters.
@param rResult
(out-param) The contained values (sub units) specify offsets for all
borders of the reference rectangle containing the diagonal frame border.
*/
void lclLinkBLTRFrameBorder(
DiagBorderResult& rResult, const Style& rBorder,
const Style& rBLFromT, const Style& rBLFromR, const Style& rTRFromB, const Style& rTRFromL )
{
bool bIsDbl = rBorder.Secn() != 0;
rResult.maPrim.mnLClip = lclGetBehindEnd( rBLFromT );
rResult.maPrim.mnRClip = (bIsDbl && rTRFromB.Secn()) ? lclGetEnd( rTRFromB ) : lclGetBeforeBeg( rTRFromB );
rResult.maPrim.mnTClip = lclGetBehindEnd( rTRFromL );
rResult.maPrim.mnBClip = (bIsDbl && rBLFromR.Secn()) ? lclGetEnd( rBLFromR ) : lclGetBeforeBeg( rBLFromR );
if( bIsDbl )
{
rResult.maSecn.mnLClip = rBLFromT.Secn() ? lclGetBeg( rBLFromT ) : lclGetBehindEnd( rBLFromT );
rResult.maSecn.mnRClip = lclGetBeforeBeg( rTRFromB );
rResult.maSecn.mnTClip = rTRFromL.Secn() ? lclGetBeg( rTRFromL ) : lclGetBehindEnd( rTRFromL );
rResult.maSecn.mnBClip = lclGetBeforeBeg( rBLFromR );
}
}
/** Calculates clipping offsets for both diagonal frame borders.
This function can be used for single and double frame borders.
See DrawDiagFrameBorders() function for a description of all parameters.
@param rResult
(out-param) The contained values (sub units) specify offsets for all
borders of the reference rectangle containing the diagonal frame
borders.
*/
void lclLinkDiagFrameBorders(
DiagBordersResult& rResult, const Style& rTLBR, const Style& rBLTR,
const Style& rTLFromB, const Style& rTLFromR, const Style& rBRFromT, const Style& rBRFromL,
const Style& rBLFromT, const Style& rBLFromR, const Style& rTRFromB, const Style& rTRFromL )
{
lclLinkTLBRFrameBorder( rResult.maTLBR, rTLBR, rTLFromB, rTLFromR, rBRFromT, rBRFromL );
lclLinkBLTRFrameBorder( rResult.maBLTR, rBLTR, rBLFromT, rBLFromR, rTRFromB, rTRFromL );
}
// Drawing functions
// Simple helper functions
/** Converts sub units to OutputDevice map units. */
inline long lclToMapUnit( long nSubUnits )
{
return ((nSubUnits < 0) ? (nSubUnits - 127) : (nSubUnits + 128)) / 256;
}
/** Converts a point in sub units to an OutputDevice point. */
inline Point lclToMapUnit( long nSubXPos, long nSubYPos )
{
return Point( lclToMapUnit( nSubXPos ), lclToMapUnit( nSubYPos ) );
}
/** Returns a polygon constructed from a vector of points. */
inline tools::Polygon lclCreatePolygon( const PointVec& rPoints )
{
return tools::Polygon( static_cast< sal_uInt16 >( rPoints.size() ), &rPoints[ 0 ] );
}
/** Returns a polygon constructed from the five passed points. */
vcl::Region lclCreatePolygon( const Point& rP1, const Point& rP2, const Point& rP3, const Point& rP4, const Point& rP5 )
{
PointVec aPoints;
aPoints.reserve( 5 );
aPoints.push_back( rP1 );
aPoints.push_back( rP2 );
aPoints.push_back( rP3 );
aPoints.push_back( rP4 );
aPoints.push_back( rP5 );
return vcl::Region(lclCreatePolygon(aPoints));
}
/** Sets the color of the passed frame style to the output device.
Sets the line color and fill color in the output device.
@param rDev
The output device the color has to be set to. The old colors are pushed
onto the device's stack and can be restored with a call to
OutputDevice::Pop(). Please take care about the correct calling order
of Pop() if this function is used with other functions pushing
something onto the stack.
@param rStyle
The border style that contains the line color to be set to the device.
*/
void lclSetColorToOutDev( OutputDevice& rDev, const Color& rColor, const Color* pForceColor )
{
rDev.Push( PushFlags::LINECOLOR | PushFlags::FILLCOLOR );
rDev.SetLineColor( pForceColor ? *pForceColor : rColor );
rDev.SetFillColor( pForceColor ? *pForceColor : rColor );
}
// Drawing of horizontal frame borders.
/** Draws a horizontal thin or thick line into the passed output device.
The X coordinates of the edges of the line are adjusted according to the
passed LineEndResult structs. A one pixel wide line can be drawn dotted.
*/
void lclDrawHorLine(
OutputDevice& rDev,
const Point& rLPos, const LineEndResult& rLRes,
const Point& rRPos, const LineEndResult& rRRes,
long nTOffs, long nBOffs, SvxBorderLineStyle nDashing )
{
LinePoints aTPoints( rLPos + lclToMapUnit( rLRes.mnOffs1, nTOffs ), rRPos + lclToMapUnit( rRRes.mnOffs1, nTOffs ) );
LinePoints aBPoints( rLPos + lclToMapUnit( rLRes.mnOffs2, nBOffs ), rRPos + lclToMapUnit( rRRes.mnOffs2, nBOffs ) );
sal_uInt32 nWidth = lclToMapUnit( std::abs( nTOffs ) ) + lclToMapUnit( std::abs( nBOffs ) );
if ( ( nTOffs >= 0 && nBOffs >= 0 ) || ( nTOffs <= 0 && nBOffs <= 0 ) )
nWidth = std::abs( lclToMapUnit( nTOffs ) - lclToMapUnit( nBOffs ) ) + 1;
Point rLMid = ( aTPoints.maBeg + aBPoints.maBeg ) / 2;
Point rRMid = ( aTPoints.maEnd + aBPoints.maEnd ) / 2;
::svtools::DrawLine( rDev, rLMid, rRMid, nWidth, nDashing );
}
/** Draws a horizontal frame border into the passed output device.
@param rLPos
The top-left or bottom-left reference point of the diagonal frame border.
@param rRPos
The top-right or bottom-right reference point of the diagonal frame border.
@param rBorder
The frame style used to draw the border.
@param rResult
The X coordinates of the edges of all lines of the frame border are
adjusted according to the offsets contained here.
*/
void lclDrawHorFrameBorder(
OutputDevice& rDev, const Point& rLPos, const Point& rRPos,
const Style& rBorder, const BorderResult& rResult, const Color* pForceColor )
{
DBG_ASSERT( rBorder.Prim(), "svx::frame::lclDrawHorFrameBorder - line not visible" );
DBG_ASSERT( rLPos.X() <= rRPos.X(), "svx::frame::lclDrawHorFrameBorder - wrong order of line ends" );
DBG_ASSERT( rLPos.Y() == rRPos.Y(), "svx::frame::lclDrawHorFrameBorder - line not horizontal" );
if( rLPos.X() <= rRPos.X() )
{
if ( rBorder.UseGapColor( ) )
{
lclSetColorToOutDev( rDev, rBorder.GetColorGap(), pForceColor );
lclDrawHorLine( rDev, rLPos, rResult.maBeg.maGap, rRPos, rResult.maEnd.maGap,
lclGetPrimEnd( rBorder ), lclGetSecnBeg( rBorder ), rBorder.Type() );
rDev.Pop(); // Gap color
}
lclSetColorToOutDev( rDev, rBorder.GetColorPrim(), pForceColor );
lclDrawHorLine( rDev, rLPos, rResult.maBeg.maPrim, rRPos, rResult.maEnd.maPrim,
lclGetBeg( rBorder ), lclGetPrimEnd( rBorder ), rBorder.Type() );
rDev.Pop(); // colors
if( rBorder.Secn() )
{
lclSetColorToOutDev( rDev, rBorder.GetColorSecn(), pForceColor );
lclDrawHorLine( rDev, rLPos, rResult.maBeg.maSecn, rRPos, rResult.maEnd.maSecn,
lclGetSecnBeg( rBorder ), lclGetEnd( rBorder ), rBorder.Type() );
rDev.Pop(); // colors
}
}
}
// Drawing of vertical frame borders.
/** Draws a vertical thin or thick line into the passed output device.
The Y coordinates of the edges of the line are adjusted according to the
passed LineEndResult structs. A one pixel wide line can be drawn dotted.
*/
void lclDrawVerLine(
OutputDevice& rDev,
const Point& rTPos, const LineEndResult& rTRes,
const Point& rBPos, const LineEndResult& rBRes,
long nLOffs, long nROffs, SvxBorderLineStyle nDashing )
{
LinePoints aLPoints( rTPos + lclToMapUnit( nLOffs, rTRes.mnOffs1 ), rBPos + lclToMapUnit( nLOffs, rBRes.mnOffs1 ) );
LinePoints aRPoints( rTPos + lclToMapUnit( nROffs, rTRes.mnOffs2 ), rBPos + lclToMapUnit( nROffs, rBRes.mnOffs2 ) );
sal_uInt32 nWidth = lclToMapUnit( std::abs( nLOffs ) ) + lclToMapUnit( std::abs( nROffs ) );
if ( ( nLOffs >= 0 && nROffs >= 0 ) || ( nLOffs <= 0 && nROffs <= 0 ) )
nWidth = std::abs( lclToMapUnit( nLOffs ) - lclToMapUnit( nROffs ) ) + 1;
Point rTMid = ( aLPoints.maBeg + aRPoints.maBeg ) / 2;
Point rBMid = ( aLPoints.maEnd + aRPoints.maEnd ) / 2;
::svtools::DrawLine( rDev, rTMid, rBMid, nWidth, nDashing );
}
/** Draws a vertical frame border into the passed output device.
@param rTPos
The top-left or top-right reference point of the diagonal frame border.
@param rBPos
The bottom-left or bottom-right reference point of the diagonal frame border.
@param rBorder
The frame style used to draw the border.
@param rResult
The Y coordinates of the edges of all lines of the frame border are
adjusted according to the offsets contained here.
*/
void lclDrawVerFrameBorder(
OutputDevice& rDev, const Point& rTPos, const Point& rBPos,
const Style& rBorder, const BorderResult& rResult, const Color* pForceColor )
{
DBG_ASSERT( rBorder.Prim(), "svx::frame::lclDrawVerFrameBorder - line not visible" );
DBG_ASSERT( rTPos.Y() <= rBPos.Y(), "svx::frame::lclDrawVerFrameBorder - wrong order of line ends" );
DBG_ASSERT( rTPos.X() == rBPos.X(), "svx::frame::lclDrawVerFrameBorder - line not vertical" );
if( rTPos.Y() <= rBPos.Y() )
{
if ( rBorder.UseGapColor( ) )
{
lclSetColorToOutDev( rDev, rBorder.GetColorGap(), pForceColor );
lclDrawVerLine( rDev, rTPos, rResult.maBeg.maGap, rBPos, rResult.maEnd.maGap,
lclGetPrimEnd( rBorder ), lclGetSecnBeg( rBorder ), rBorder.Type() );
rDev.Pop(); // Gap color
}
lclSetColorToOutDev( rDev, rBorder.GetColorPrim(), pForceColor );
lclDrawVerLine( rDev, rTPos, rResult.maBeg.maPrim, rBPos, rResult.maEnd.maPrim,
lclGetBeg( rBorder ), lclGetPrimEnd( rBorder ), rBorder.Type() );
rDev.Pop(); // colors
if( rBorder.Secn() )
{
lclSetColorToOutDev( rDev, rBorder.GetColorSecn(), pForceColor );
lclDrawVerLine( rDev, rTPos, rResult.maBeg.maSecn, rBPos, rResult.maEnd.maSecn,
lclGetSecnBeg( rBorder ), lclGetEnd( rBorder ), rBorder.Type() );
rDev.Pop(); // colors
}
}
}
// Drawing of diagonal frame borders, includes clipping functions.
/** Returns the drawing coordinates for a diagonal thin line.
This function can be used for top-left to bottom-right and for bottom-left
to top-right lines.
@param rRect
The reference rectangle of the diagonal frame border.
@param bTLBR
true = top-left to bottom-right; false = bottom-left to top-right.
@param nDiagOffs
Width offset (sub units) across the diagonal frame border.
@return
A struct containg start and end position of the diagonal line.
*/
LinePoints lclGetDiagLineEnds( const tools::Rectangle& rRect, bool bTLBR, long nDiagOffs )
{
LinePoints aPoints( rRect, bTLBR );
bool bVert = rRect.GetWidth() < rRect.GetHeight();
double fAngle = bVert ? GetVerDiagAngle( rRect ) : GetHorDiagAngle( rRect );
// vertical top-left to bottom-right borders are handled mirrored
if( bVert && bTLBR )
nDiagOffs = -nDiagOffs;
long nTOffs = bTLBR ? GetTLDiagOffset( 0, nDiagOffs, fAngle ) : GetTRDiagOffset( nDiagOffs, fAngle );
long nBOffs = bTLBR ? GetBRDiagOffset( nDiagOffs, fAngle ) : GetBLDiagOffset( 0, nDiagOffs, fAngle );
// vertical bottom-left to top-right borders are handled with exchanged end points
if( bVert && !bTLBR )
std::swap( nTOffs, nBOffs );
(bVert ? aPoints.maBeg.Y() : aPoints.maBeg.X()) += lclToMapUnit( nTOffs );
(bVert ? aPoints.maEnd.Y() : aPoints.maEnd.X()) += lclToMapUnit( nBOffs );
return aPoints;
}
// Clipping functions for diagonal frame borders.
/** Limits the clipping region to the inner area of a rectangle.
Takes the values from the passed DiagLineResult struct into account. They
may specify to not clip one or more borders of a rectangle.
@param rDev
The output device with the clipping region to be modified. The old
clipping region is pushed onto the device's stack and can be restored
with a call to OutputDevice::Pop(). Please take care about the correct
calling order of Pop() if this function is used with other functions
pushing something onto the stack.
@param rRect
The reference rectangle of the diagonal frame borders.
@param rResult
The result struct containing modifies for each border of the reference
rectangle.
*/
void lclPushDiagClipRect( OutputDevice& rDev, const tools::Rectangle& rRect, const DiagLineResult& rResult )
{
// PixelToLogic() regards internal offset of the output device
tools::Rectangle aClipRect( rRect );
aClipRect.Left() += lclToMapUnit( rResult.mnLClip );
aClipRect.Top() += lclToMapUnit( rResult.mnTClip );
aClipRect.Right() += lclToMapUnit( rResult.mnRClip );
aClipRect.Bottom() += lclToMapUnit( rResult.mnBClip );
// output device would adjust the rectangle -> invalidate it before
if( (aClipRect.GetWidth() < 1) ||(aClipRect.GetHeight() < 1) )
aClipRect.SetEmpty();
rDev.Push( PushFlags::CLIPREGION );
rDev.IntersectClipRegion( aClipRect );
}
/** Excludes inner area of a crossing double frame border from clipping region.
This function is used to modify the clipping region so that it excludes the
inner free area of a double diagonal frame border. This makes it possible
to draw a diagonal frame border in one step without taking care of the
crossing double frame border.
@param rDev
The output device with the clipping region to be modified. The old
clipping region is pushed onto the device's stack and can be restored
with a call to OutputDevice::Pop(). Please take care about the correct
calling order of Pop() if this function is used with other functions
pushing something onto the stack.
@param rRect
The reference rectangle of the diagonal frame borders.
@param bTLBR
The orientation of the processed frame border (not the orientation of
the crossing frame border).
@param bCrossStyle
The style of the crossing frame border. Must be a double frame style.
*/
void lclPushCrossingClipRegion( OutputDevice& rDev, const tools::Rectangle& rRect, bool bTLBR, const Style& rCrossStyle )
{
DBG_ASSERT( rCrossStyle.Secn(), "lclGetCrossingClipRegion - use only for double styles" );
LinePoints aLPoints( lclGetDiagLineEnds( rRect, !bTLBR, lclGetPrimEnd( rCrossStyle ) ) );
LinePoints aRPoints( lclGetDiagLineEnds( rRect, !bTLBR, lclGetSecnBeg( rCrossStyle ) ) );
vcl::Region aClipReg;
if( bTLBR )
{
aClipReg = lclCreatePolygon(
aLPoints.maBeg, aLPoints.maEnd, rRect.BottomRight(), rRect.BottomLeft(), rRect.TopLeft() );
aClipReg.Union( lclCreatePolygon(
aRPoints.maBeg, aRPoints.maEnd, rRect.BottomRight(), rRect.TopRight(), rRect.TopLeft() ) );
}
else
{
aClipReg = lclCreatePolygon(
aLPoints.maBeg, aLPoints.maEnd, rRect.BottomLeft(), rRect.TopLeft(), rRect.TopRight() );
aClipReg.Union( lclCreatePolygon(
aRPoints.maBeg, aRPoints.maEnd, rRect.BottomLeft(), rRect.BottomRight(), rRect.TopRight() ) );
}
rDev.Push( PushFlags::CLIPREGION );
rDev.IntersectClipRegion( aClipReg );
}
// Drawing functions for diagonal frame borders.
/** Draws a diagonal thin or thick line into the passed output device.
The clipping region of the output device is modified according to the
passed DiagLineResult struct. A one pixel wide line can be drawn dotted.
*/
void lclDrawDiagLine(
OutputDevice& rDev, const tools::Rectangle& rRect, bool bTLBR,
const DiagLineResult& rResult, long nDiagOffs1, long nDiagOffs2, SvxBorderLineStyle nDashing )
{
lclPushDiagClipRect( rDev, rRect, rResult );
LinePoints aLPoints( lclGetDiagLineEnds( rRect, bTLBR, nDiagOffs1 ) );
LinePoints aL2Points( lclGetDiagLineEnds( rRect, bTLBR, nDiagOffs2 ) );
Point aSMid( ( aLPoints.maBeg + aL2Points.maBeg ) / 2 );
Point aEMid( ( aLPoints.maEnd + aL2Points.maEnd ) / 2 );
sal_uInt32 nWidth = lclToMapUnit( std::abs( nDiagOffs1 ) ) + lclToMapUnit( std::abs( nDiagOffs2 ) );
if ( ( nDiagOffs1 <= 0 && nDiagOffs2 <= 0 ) || ( nDiagOffs1 >=0 && nDiagOffs2 >=0 ) )
nWidth = lclToMapUnit( std::abs( nDiagOffs1 - nDiagOffs2 ) );
svtools::DrawLine( rDev, aSMid, aEMid, nWidth, nDashing );
rDev.Pop(); // clipping region
}
/** Draws a diagonal frame border into the passed output device.
The lines of the frame border are drawn interrupted, if the style of the
crossing frame border is double.
@param rRect
The reference rectangle of the diagonal frame border.
@param bTLBR
The orientation of the diagonal frame border.
@param rBorder
The frame style used to draw the border.
@param rResult
Offsets (sub units) to modify the clipping region of the output device.
@param rCrossStyle
Style of the crossing diagonal frame border.
*/
void lclDrawDiagFrameBorder(
OutputDevice& rDev, const tools::Rectangle& rRect, bool bTLBR,
const Style& rBorder, const DiagBorderResult& rResult, const Style& rCrossStyle,
const Color* pForceColor, bool bDiagDblClip )
{
DBG_ASSERT( rBorder.Prim(), "svx::frame::lclDrawDiagFrameBorder - line not visible" );
bool bClip = bDiagDblClip && rCrossStyle.Secn();
if( bClip )
lclPushCrossingClipRegion( rDev, rRect, bTLBR, rCrossStyle );
lclSetColorToOutDev( rDev, rBorder.GetColorPrim(), pForceColor );
lclDrawDiagLine( rDev, rRect, bTLBR, rResult.maPrim, lclGetBeg( rBorder ), lclGetPrimEnd( rBorder ), rBorder.Type() );
rDev.Pop(); // colors
if( rBorder.Secn() )
{
if ( rBorder.UseGapColor( ) )
{
lclSetColorToOutDev( rDev, rBorder.GetColorGap(), pForceColor );
lclDrawDiagLine( rDev, rRect, bTLBR, rResult.maSecn, lclGetDistBeg( rBorder ), lclGetDistEnd( rBorder ), rBorder.Type() );
rDev.Pop(); // colors
}
lclSetColorToOutDev( rDev, rBorder.GetColorSecn(), pForceColor );
lclDrawDiagLine( rDev, rRect, bTLBR, rResult.maSecn, lclGetSecnBeg( rBorder ), lclGetEnd( rBorder ), rBorder.Type() );
rDev.Pop(); // colors
}
if( bClip )
rDev.Pop(); // clipping region
}
/** Draws both diagonal frame borders into the passed output device.
The lines of each frame border is drawn interrupted, if the style of the
other crossing frame border is double.
@param rRect
The reference rectangle of the diagonal frame borders.
@param rTLBR
The frame style of the top-left to bottom-right frame border.
@param rBLTR
The frame style of the bottom-left to top-right frame border.
@param rResult
Offsets (sub units) to modify the clipping region of the output device.
*/
void lclDrawDiagFrameBorders(
OutputDevice& rDev, const tools::Rectangle& rRect,
const Style& rTLBR, const Style& rBLTR, const DiagBordersResult& rResult,
const Color* pForceColor, bool bDiagDblClip )
{
DBG_ASSERT( (rRect.GetWidth() > 1) && (rRect.GetHeight() > 1), "svx::frame::lclDrawDiagFrameBorders - rectangle too small" );
if( (rRect.GetWidth() > 1) && (rRect.GetHeight() > 1) )
{
bool bDrawTLBR = rTLBR.Prim() != 0;
bool bDrawBLTR = rBLTR.Prim() != 0;
bool bFirstDrawBLTR = rTLBR.Secn() != 0;
if( bDrawBLTR && bFirstDrawBLTR )
lclDrawDiagFrameBorder( rDev, rRect, false, rBLTR, rResult.maBLTR, rTLBR, pForceColor, bDiagDblClip );
if( bDrawTLBR )
lclDrawDiagFrameBorder( rDev, rRect, true, rTLBR, rResult.maTLBR, rBLTR, pForceColor, bDiagDblClip );
if( bDrawBLTR && !bFirstDrawBLTR )
lclDrawDiagFrameBorder( rDev, rRect, false, rBLTR, rResult.maBLTR, rTLBR, pForceColor, bDiagDblClip );
}
}
} // namespace
@@ -1121,7 +67,8 @@ void lclDrawDiagFrameBorders(
Style::Style() :
meRefMode(RefMode::Centered),
mfPatternScale(1.0),
mnType(SvxBorderLineStyle::SOLID)
mnType(SvxBorderLineStyle::SOLID),
mpUsingCell(nullptr)
{
Clear();
}
@@ -1129,7 +76,8 @@ Style::Style() :
Style::Style( double nP, double nD, double nS, SvxBorderLineStyle nType ) :
meRefMode(RefMode::Centered),
mfPatternScale(1.0),
mnType(nType)
mnType(nType),
mpUsingCell(nullptr)
{
Clear();
Set( nP, nD, nS );
@@ -1139,14 +87,16 @@ Style::Style( const Color& rColorPrim, const Color& rColorSecn, const Color& rCo
double nP, double nD, double nS, SvxBorderLineStyle nType ) :
meRefMode(RefMode::Centered),
mfPatternScale(1.0),
mnType(nType)
mnType(nType),
mpUsingCell(nullptr)
{
Set( rColorPrim, rColorSecn, rColorGap, bUseGapColor, nP, nD, nS );
}
Style::Style( const editeng::SvxBorderLine* pBorder, double fScale ) :
meRefMode(RefMode::Centered),
mfPatternScale(fScale)
mfPatternScale(fScale),
mpUsingCell(nullptr)
{
Set( pBorder, fScale );
}
@@ -1293,35 +243,16 @@ bool operator<( const Style& rL, const Style& rR )
// Various helper functions
double GetHorDiagAngle( long nWidth, long nHeight )
{
return atan2( static_cast< double >( std::abs( nHeight ) ), static_cast< double >( std::abs( nWidth ) ) );
}
long GetTLDiagOffset( long nVerOffs, long nDiagOffs, double fAngle )
{
return lclD2L( nVerOffs / tan( fAngle ) + nDiagOffs / sin( fAngle ) );
}
long GetBLDiagOffset( long nVerOffs, long nDiagOffs, double fAngle )
{
return lclD2L( -nVerOffs / tan( fAngle ) + nDiagOffs / sin( fAngle ) );
}
long GetBRDiagOffset( long nDiagOffs, double fAngle )
{
return -lclD2L( - nDiagOffs / sin( fAngle ) );
}
long GetTRDiagOffset( long nDiagOffs, double fAngle )
{
return -lclD2L( - nDiagOffs / sin( fAngle ) );
}
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 )
@@ -1347,7 +278,6 @@ bool CheckFrameBorderConnectable( const Style& rLBorder, const Style& rRBorder,
// Drawing functions
// get offset to center of line in question
double lcl_getCenterOfLineOffset(const Style& rBorder, bool bLeftEdge)
{
@@ -1417,8 +347,9 @@ double lcl_GetExtent(
void CreateBorderPrimitives(
drawinglayer::primitive2d::Primitive2DContainer& rTarget,
const Point& rLPos,
const Point& rRPos,
const basegfx::B2DPoint& rOrigin,
const basegfx::B2DVector& rX,
const basegfx::B2DVector& rY,
const Style& rBorder,
const DiagStyle& /*rLFromTR*/,
const Style& rLFromT,
@@ -1430,14 +361,14 @@ void CreateBorderPrimitives(
const Style& /*rRFromR*/,
const Style& rRFromB,
const DiagStyle& /*rRFromBL*/,
const Color* /*pForceColor*/,
const long nRotateT,
const long nRotateB)
const Color* pForceColor)
{
if (rBorder.Prim() || rBorder.Secn())
{
basegfx::B2DPoint aStart(rLPos.getX(), rLPos.getY());
basegfx::B2DPoint aEnd(rRPos.getX(), rRPos.getY());
basegfx::B2DPoint aStart(rOrigin);
basegfx::B2DPoint aEnd(rOrigin + rX);
const long nRotateT = 9000; /// Angle of the top slanted frames in 100th of degree
const long nRotateB = 9000; /// Angle of the bottom slanted frames in 100th of degree
rTarget.append(
drawinglayer::primitive2d::Primitive2DReference(
@@ -1450,17 +381,18 @@ void CreateBorderPrimitives(
lcl_GetExtent(rBorder, rRFromT, rRFromB, 18000 - nRotateT, nRotateB - 18000, true, true), // top-right
lcl_GetExtent(rBorder, rLFromB, rLFromT, nRotateB, -nRotateT, false, false), // bottom-left
lcl_GetExtent(rBorder, rRFromB, rRFromT, 18000 - nRotateB, nRotateT - 18000, false, true), // bottom-right
rBorder.GetColorSecn().getBColor(),
rBorder.GetColorPrim().getBColor(),
rBorder.GetColorGap().getBColor(),
(pForceColor ? *pForceColor : rBorder.GetColorSecn()).getBColor(),
(pForceColor ? *pForceColor : rBorder.GetColorPrim()).getBColor(),
(pForceColor ? *pForceColor : rBorder.GetColorGap()).getBColor(),
rBorder.UseGapColor(), rBorder.Type(), rBorder.PatternScale())));
}
}
void CreateBorderPrimitives(
drawinglayer::primitive2d::Primitive2DContainer& rTarget,
const Point& rLPos,
const Point& rRPos,
const basegfx::B2DPoint& rOrigin,
const basegfx::B2DVector& rX,
const basegfx::B2DVector& rY,
const Style& rBorder,
const Style& rLFromT,
const Style& rLFromL,
@@ -1468,16 +400,15 @@ void CreateBorderPrimitives(
const Style& rRFromT,
const Style& rRFromR,
const Style& rRFromB,
const Color* pForceColor,
const long nRotateT,
const long nRotateB)
const Color* pForceColor)
{
if (rBorder.Prim() || rBorder.Secn())
{
CreateBorderPrimitives(
rTarget,
rLPos,
rRPos,
rOrigin,
rX,
rY,
rBorder,
DiagStyle(),
rLFromT,
@@ -1489,15 +420,15 @@ void CreateBorderPrimitives(
rRFromR,
rRFromB,
DiagStyle(),
pForceColor,
nRotateT,
nRotateB);
pForceColor);
}
}
void CreateDiagFrameBorderPrimitives(
drawinglayer::primitive2d::Primitive2DContainer& rTarget,
const basegfx::B2DRange& rRange,
const basegfx::B2DPoint& rOrigin,
const basegfx::B2DVector& rXAxis,
const basegfx::B2DVector& rYAxis,
const Style& rTLBR,
const Style& rBLTR,
const Style& rTLFromB,
@@ -1508,23 +439,25 @@ void CreateDiagFrameBorderPrimitives(
const Style& rBLFromR,
const Style& rTRFromB,
const Style& rTRFromL,
const Color* /*pForceColor*/,
const long /*nRotationT*/,
const long /*nRotationB*/)
const Color* pForceColor)
{
if (rTLBR.Prim())
{
// top-left to bottom-right
rTarget.append(
new drawinglayer::primitive2d::BorderLinePrimitive2D(
rRange.getMinimum(),
rRange.getMaximum(),
rOrigin,
rOrigin + rXAxis + rYAxis,
rTLBR.Prim(),
rTLBR.Dist(),
rTLBR.Secn(),
0.0, 0.0, 0.0, 0.0,
rTLBR.GetColorSecn().getBColor(),
rTLBR.GetColorPrim().getBColor(),
rTLBR.GetColorGap().getBColor(),
0.0,
0.0,
0.0,
0.0,
(pForceColor ? *pForceColor : rTLBR.GetColorSecn()).getBColor(),
(pForceColor ? *pForceColor : rTLBR.GetColorPrim()).getBColor(),
(pForceColor ? *pForceColor : rTLBR.GetColorGap()).getBColor(),
rTLBR.UseGapColor(),
rTLBR.Type(),
rTLBR.PatternScale()));
@@ -1532,73 +465,26 @@ void CreateDiagFrameBorderPrimitives(
if (rBLTR.Prim())
{
// bottom-left to top-right
rTarget.append(
new drawinglayer::primitive2d::BorderLinePrimitive2D(
basegfx::B2DPoint(rRange.getMinX(), rRange.getMaxY()),
basegfx::B2DPoint(rRange.getMaxX(), rRange.getMinY()),
rOrigin + rYAxis,
rOrigin + rXAxis,
rBLTR.Prim(),
rBLTR.Dist(),
rBLTR.Secn(),
0.0, 0.0, 0.0, 0.0,
rBLTR.GetColorSecn().getBColor(),
rBLTR.GetColorPrim().getBColor(),
rBLTR.GetColorGap().getBColor(),
0.0,
0.0,
0.0,
0.0,
(pForceColor ? *pForceColor : rBLTR.GetColorSecn()).getBColor(),
(pForceColor ? *pForceColor : rBLTR.GetColorPrim()).getBColor(),
(pForceColor ? *pForceColor : rBLTR.GetColorGap()).getBColor(),
rBLTR.UseGapColor(),
rBLTR.Type(),
rBLTR.PatternScale()));
}
}
void DrawHorFrameBorder( OutputDevice& rDev,
const Point& rLPos, const Point& rRPos, const Style& rBorder,
const DiagStyle& rLFromTR, const Style& rLFromT, const Style& rLFromL, const Style& rLFromB, const DiagStyle& rLFromBR,
const DiagStyle& rRFromTL, const Style& rRFromT, const Style& rRFromR, const Style& rRFromB, const DiagStyle& rRFromBL,
const Color* pForceColor )
{
if( rBorder.Prim() )
{
BorderResult aResult;
lclLinkHorFrameBorder( aResult, rBorder,
rLFromTR, rLFromT, rLFromL, rLFromB, rLFromBR,
rRFromTL, rRFromT, rRFromR, rRFromB, rRFromBL );
lclDrawHorFrameBorder( rDev, rLPos, rRPos, rBorder, aResult, pForceColor );
}
}
void DrawVerFrameBorder( OutputDevice& rDev,
const Point& rTPos, const Point& rBPos, const Style& rBorder,
const DiagStyle& rTFromBL, const Style& rTFromL, const Style& rTFromT, const Style& rTFromR, const DiagStyle& rTFromBR,
const DiagStyle& rBFromTL, const Style& rBFromL, const Style& rBFromB, const Style& rBFromR, const DiagStyle& rBFromTR,
const Color* pForceColor )
{
if( rBorder.Prim() )
{
BorderResult aResult;
lclLinkVerFrameBorder( aResult, rBorder,
rTFromBL, rTFromL, rTFromT, rTFromR, rTFromBR,
rBFromTL, rBFromL, rBFromB, rBFromR, rBFromTR );
lclDrawVerFrameBorder( rDev, rTPos, rBPos, rBorder, aResult, pForceColor );
}
}
void DrawDiagFrameBorders(
OutputDevice& rDev, const tools::Rectangle& rRect, const Style& rTLBR, const Style& rBLTR,
const Style& rTLFromB, const Style& rTLFromR, const Style& rBRFromT, const Style& rBRFromL,
const Style& rBLFromT, const Style& rBLFromR, const Style& rTRFromB, const Style& rTRFromL,
const Color* pForceColor, bool bDiagDblClip )
{
if( rTLBR.Prim() || rBLTR.Prim() )
{
DiagBordersResult aResult;
lclLinkDiagFrameBorders( aResult, rTLBR, rBLTR,
rTLFromB, rTLFromR, rBRFromT, rBRFromL, rBLFromT, rBLFromR, rTRFromB, rTRFromL );
lclDrawDiagFrameBorders( rDev, rRect, rTLBR, rBLTR, aResult, pForceColor, bDiagDblClip );
}
}
}
}
diff --git a/svx/source/dialog/framelinkarray.cxx b/svx/source/dialog/framelinkarray.cxx
index 09f4e3a..839e9be 100644
--- a/svx/source/dialog/framelinkarray.cxx
+++ b/svx/source/dialog/framelinkarray.cxx
@@ -28,25 +28,52 @@
namespace svx {
namespace frame {
struct Cell
/// 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:
Style maLeft;
Style maRight;
Style maTop;
Style maBottom;
Style maTLBR;
Style maBLTR;
public:
long mnAddLeft;
long mnAddRight;
long mnAddTop;
long mnAddBottom;
SvxRotateMode meRotMode;
double mfOrientation;
bool mbMergeOrig;
bool mbOverlapX;
bool mbOverlapY;
public:
explicit Cell();
bool IsMerged() const { return mbMergeOrig || mbOverlapX || mbOverlapY; }
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); }
const Style& GetStyleLeft() const { return maLeft; }
const Style& GetStyleRight() const { return maRight; }
const Style& GetStyleTop() const { return maTop; }
const Style& GetStyleBottom() const { return maBottom; }
const Style& GetStyleTLBR() const { return maTLBR; }
const Style& GetStyleBLTR() const { return maBLTR; }
bool IsMerged() const { return mbMergeOrig || mbOverlapX || mbOverlapY; }
bool IsRotated() const { return mfOrientation != 0.0; }
void MirrorSelfX();
};
@@ -59,6 +86,8 @@ Cell::Cell() :
mnAddRight( 0 ),
mnAddTop( 0 ),
mnAddBottom( 0 ),
meRotMode(SvxRotateMode::SVX_ROTATE_MODE_STANDARD ),
mfOrientation( 0.0 ),
mbMergeOrig( false ),
mbOverlapX( false ),
mbOverlapY( false )
@@ -71,6 +100,7 @@ void Cell::MirrorSelfX()
std::swap( mnAddLeft, mnAddRight );
maLeft.MirrorSelf();
maRight.MirrorSelf();
mfOrientation = -mfOrientation;
}
@@ -119,9 +149,9 @@ struct ArrayImpl
size_t mnLastClipRow;
mutable bool mbXCoordsDirty;
mutable bool mbYCoordsDirty;
bool mbDiagDblClip;
bool mbMayHaveCellRotation;
explicit ArrayImpl( size_t nWidth, size_t nHeight, bool bDiagDblClip );
explicit ArrayImpl( size_t nWidth, size_t nHeight );
bool IsValidPos( size_t nCol, size_t nRow ) const
{ return (nCol < mnWidth) && (nRow < mnHeight); }
@@ -157,9 +187,11 @@ struct ArrayImpl
double GetHorDiagAngle( size_t nCol, size_t nRow ) const;
double GetVerDiagAngle( size_t nCol, size_t nRow ) const;
bool HasCellRotation() const;
};
ArrayImpl::ArrayImpl( size_t nWidth, size_t nHeight, bool bDiagDblClip ) :
ArrayImpl::ArrayImpl( size_t nWidth, size_t nHeight ) :
mnWidth( nWidth ),
mnHeight( nHeight ),
mnFirstClipCol( 0 ),
@@ -168,7 +200,7 @@ ArrayImpl::ArrayImpl( size_t nWidth, size_t nHeight, bool bDiagDblClip ) :
mnLastClipRow( nHeight - 1 ),
mbXCoordsDirty( false ),
mbYCoordsDirty( false ),
mbDiagDblClip( bDiagDblClip )
mbMayHaveCellRotation( false )
{
// default-construct all vectors
maCells.resize( mnWidth * mnHeight );
@@ -318,6 +350,19 @@ double ArrayImpl::GetVerDiagAngle( size_t nCol, size_t nRow ) const
return (fAngle > 0.0) ? (F_PI2 - fAngle) : 0.0;
}
bool ArrayImpl::HasCellRotation() const
{
// check cell array
for (const auto& aCell : maCells)
{
if (aCell.IsRotated())
{
return true;
}
}
return false;
}
class MergedCellIterator
{
@@ -385,8 +430,7 @@ Array::~Array()
// array size and column/row indexes
void Array::Initialize( size_t nWidth, size_t nHeight )
{
bool bDiagDblClip = mxImpl.get() ? mxImpl->mbDiagDblClip : DIAG_DBL_CLIP_DEFAULT;
mxImpl.reset( new ArrayImpl( nWidth, nHeight, bDiagDblClip ) );
mxImpl.reset( new ArrayImpl( nWidth, nHeight ) );
}
size_t Array::GetColCount() const
@@ -416,45 +460,45 @@ size_t Array::GetCellIndex( size_t nCol, size_t nRow, bool bRTL ) const
void Array::SetCellStyleLeft( size_t nCol, size_t nRow, const Style& rStyle )
{
DBG_FRAME_CHECK_COLROW( nCol, nRow, "SetCellStyleLeft" );
CELLACC( nCol, nRow ).maLeft = rStyle;
CELLACC( nCol, nRow ).SetStyleLeft(rStyle);
}
void Array::SetCellStyleRight( size_t nCol, size_t nRow, const Style& rStyle )
{
DBG_FRAME_CHECK_COLROW( nCol, nRow, "SetCellStyleRight" );
CELLACC( nCol, nRow ).maRight = rStyle;
CELLACC( nCol, nRow ).SetStyleRight(rStyle);
}
void Array::SetCellStyleTop( size_t nCol, size_t nRow, const Style& rStyle )
{
DBG_FRAME_CHECK_COLROW( nCol, nRow, "SetCellStyleTop" );
CELLACC( nCol, nRow ).maTop = rStyle;
CELLACC( nCol, nRow ).SetStyleTop(rStyle);
}
void Array::SetCellStyleBottom( size_t nCol, size_t nRow, const Style& rStyle )
{
DBG_FRAME_CHECK_COLROW( nCol, nRow, "SetCellStyleBottom" );
CELLACC( nCol, nRow ).maBottom = rStyle;
CELLACC( nCol, nRow ).SetStyleBottom(rStyle);
}
void Array::SetCellStyleTLBR( size_t nCol, size_t nRow, const Style& rStyle )
{
DBG_FRAME_CHECK_COLROW( nCol, nRow, "SetCellStyleTLBR" );
CELLACC( nCol, nRow ).maTLBR = rStyle;
CELLACC( nCol, nRow ).SetStyleTLBR(rStyle);
}
void Array::SetCellStyleBLTR( size_t nCol, size_t nRow, const Style& rStyle )
{
DBG_FRAME_CHECK_COLROW( nCol, nRow, "SetCellStyleBLTR" );
CELLACC( nCol, nRow ).maBLTR = rStyle;
CELLACC( nCol, nRow ).SetStyleBLTR(rStyle);
}
void Array::SetCellStyleDiag( size_t nCol, size_t nRow, const Style& rTLBR, const Style& rBLTR )
{
DBG_FRAME_CHECK_COLROW( nCol, nRow, "SetCellStyleDiag" );
Cell& rCell = CELLACC( nCol, nRow );
rCell.maTLBR = rTLBR;
rCell.maBLTR = rBLTR;
rCell.SetStyleTLBR(rTLBR);
rCell.SetStyleBLTR(rBLTR);
}
void Array::SetColumnStyleLeft( size_t nCol, const Style& rStyle )
@@ -485,6 +529,32 @@ void Array::SetRowStyleBottom( size_t nRow, const Style& rStyle )
SetCellStyleBottom( nCol, nRow, rStyle );
}
void Array::SetCellRotation(size_t nCol, size_t nRow, SvxRotateMode eRotMode, double fOrientation)
{
DBG_FRAME_CHECK_COLROW(nCol, nRow, "SetCellRotation");
Cell& rTarget = CELLACC(nCol, nRow);
rTarget.meRotMode = eRotMode;
rTarget.mfOrientation = fOrientation;
if (!mxImpl->mbMayHaveCellRotation)
{
// activate once when a cell gets actually rotated to allow fast
// answering HasCellRotation() calls
mxImpl->mbMayHaveCellRotation = rTarget.IsRotated();
}
}
bool Array::HasCellRotation() const
{
if (!mxImpl->mbMayHaveCellRotation)
{
// never set, no need to check
return false;
}
return mxImpl->HasCellRotation();
}
const Style& Array::GetCellStyleLeft( size_t nCol, size_t nRow ) const
{
// outside clipping rows or overlapped in merged cells: invisible
@@ -492,15 +562,15 @@ const Style& Array::GetCellStyleLeft( size_t nCol, size_t nRow ) const
return OBJ_STYLE_NONE;
// left clipping border: always own left style
if( nCol == mxImpl->mnFirstClipCol )
return ORIGCELL( nCol, nRow ).maLeft;
return ORIGCELL( nCol, nRow ).GetStyleLeft();
// right clipping border: always right style of left neighbor cell
if( nCol == mxImpl->mnLastClipCol + 1 )
return ORIGCELL( nCol - 1, nRow ).maRight;
return ORIGCELL( nCol - 1, nRow ).GetStyleRight();
// outside clipping columns: invisible
if( !mxImpl->IsColInClipRange( nCol ) )
return OBJ_STYLE_NONE;
// inside clipping range: maximum of own left style and right style of left neighbor cell
return std::max( ORIGCELL( nCol, nRow ).maLeft, ORIGCELL( nCol - 1, nRow ).maRight );
return std::max( ORIGCELL( nCol, nRow ).GetStyleLeft(), ORIGCELL( nCol - 1, nRow ).GetStyleRight() );
}
const Style& Array::GetCellStyleRight( size_t nCol, size_t nRow ) const
@@ -510,15 +580,15 @@ const Style& Array::GetCellStyleRight( size_t nCol, size_t nRow ) const
return OBJ_STYLE_NONE;
// left clipping border: always left style of right neighbor cell
if( nCol + 1 == mxImpl->mnFirstClipCol )
return ORIGCELL( nCol + 1, nRow ).maLeft;
return ORIGCELL( nCol + 1, nRow ).GetStyleLeft();
// right clipping border: always own right style
if( nCol == mxImpl->mnLastClipCol )
return ORIGCELL( nCol, nRow ).maRight;
return ORIGCELL( nCol, nRow ).GetStyleRight();
// outside clipping columns: invisible
if( !mxImpl->IsColInClipRange( nCol ) )
return OBJ_STYLE_NONE;
// inside clipping range: maximum of own right style and left style of right neighbor cell
return std::max( ORIGCELL( nCol, nRow ).maRight, ORIGCELL( nCol + 1, nRow ).maLeft );
return std::max( ORIGCELL( nCol, nRow ).GetStyleRight(), ORIGCELL( nCol + 1, nRow ).GetStyleLeft() );
}
const Style& Array::GetCellStyleTop( size_t nCol, size_t nRow ) const
@@ -528,15 +598,15 @@ const Style& Array::GetCellStyleTop( size_t nCol, size_t nRow ) const
return OBJ_STYLE_NONE;
// top clipping border: always own top style
if( nRow == mxImpl->mnFirstClipRow )
return ORIGCELL( nCol, nRow ).maTop;
return ORIGCELL( nCol, nRow ).GetStyleTop();
// bottom clipping border: always bottom style of top neighbor cell
if( nRow == mxImpl->mnLastClipRow + 1 )
return ORIGCELL( nCol, nRow - 1 ).maBottom;
return ORIGCELL( nCol, nRow - 1 ).GetStyleBottom();
// outside clipping rows: invisible
if( !mxImpl->IsRowInClipRange( nRow ) )
return OBJ_STYLE_NONE;
// inside clipping range: maximum of own top style and bottom style of top neighbor cell
return std::max( ORIGCELL( nCol, nRow ).maTop, ORIGCELL( nCol, nRow - 1 ).maBottom );
return std::max( ORIGCELL( nCol, nRow ).GetStyleTop(), ORIGCELL( nCol, nRow - 1 ).GetStyleBottom() );
}
const Style& Array::GetCellStyleBottom( size_t nCol, size_t nRow ) const
@@ -546,25 +616,25 @@ const Style& Array::GetCellStyleBottom( size_t nCol, size_t nRow ) const
return OBJ_STYLE_NONE;
// top clipping border: always top style of bottom neighbor cell
if( nRow + 1 == mxImpl->mnFirstClipRow )
return ORIGCELL( nCol, nRow + 1 ).maTop;
return ORIGCELL( nCol, nRow + 1 ).GetStyleTop();
// bottom clipping border: always own bottom style
if( nRow == mxImpl->mnLastClipRow )
return ORIGCELL( nCol, nRow ).maBottom;
return ORIGCELL( nCol, nRow ).GetStyleBottom();
// outside clipping rows: invisible
if( !mxImpl->IsRowInClipRange( nRow ) )
return OBJ_STYLE_NONE;
// inside clipping range: maximum of own bottom style and top style of bottom neighbor cell
return std::max( ORIGCELL( nCol, nRow ).maBottom, ORIGCELL( nCol, nRow + 1 ).maTop );
return std::max( ORIGCELL( nCol, nRow ).GetStyleBottom(), ORIGCELL( nCol, nRow + 1 ).GetStyleTop() );
}
const Style& Array::GetCellStyleTLBR( size_t nCol, size_t nRow ) const
{
return CELL( nCol, nRow ).maTLBR;
return CELL( nCol, nRow ).GetStyleTLBR();
}
const Style& Array::GetCellStyleBLTR( size_t nCol, size_t nRow ) const
{
return CELL( nCol, nRow ).maBLTR;
return CELL( nCol, nRow ).GetStyleBLTR();
}
const Style& Array::GetCellStyleTL( size_t nCol, size_t nRow ) const
@@ -576,7 +646,7 @@ const Style& Array::GetCellStyleTL( size_t nCol, size_t nRow ) const
size_t nFirstCol = mxImpl->GetMergedFirstCol( nCol, nRow );
size_t nFirstRow = mxImpl->GetMergedFirstRow( nCol, nRow );
return ((nCol == nFirstCol) && (nRow == nFirstRow)) ?
CELL( nFirstCol, nFirstRow ).maTLBR : OBJ_STYLE_NONE;
CELL( nFirstCol, nFirstRow ).GetStyleTLBR() : OBJ_STYLE_NONE;
}
const Style& Array::GetCellStyleBR( size_t nCol, size_t nRow ) const
@@ -588,7 +658,7 @@ const Style& Array::GetCellStyleBR( size_t nCol, size_t nRow ) const
size_t nLastCol = mxImpl->GetMergedLastCol( nCol, nRow );
size_t nLastRow = mxImpl->GetMergedLastRow( nCol, nRow );
return ((nCol == nLastCol) && (nRow == nLastRow)) ?
CELL( mxImpl->GetMergedFirstCol( nCol, nRow ), mxImpl->GetMergedFirstRow( nCol, nRow ) ).maTLBR : OBJ_STYLE_NONE;
CELL( mxImpl->GetMergedFirstCol( nCol, nRow ), mxImpl->GetMergedFirstRow( nCol, nRow ) ).GetStyleTLBR() : OBJ_STYLE_NONE;
}
const Style& Array::GetCellStyleBL( size_t nCol, size_t nRow ) const
@@ -600,7 +670,7 @@ const Style& Array::GetCellStyleBL( size_t nCol, size_t nRow ) const
size_t nFirstCol = mxImpl->GetMergedFirstCol( nCol, nRow );
size_t nLastRow = mxImpl->GetMergedLastRow( nCol, nRow );
return ((nCol == nFirstCol) && (nRow == nLastRow)) ?
CELL( nFirstCol, mxImpl->GetMergedFirstRow( nCol, nRow ) ).maBLTR : OBJ_STYLE_NONE;
CELL( nFirstCol, mxImpl->GetMergedFirstRow( nCol, nRow ) ).GetStyleBLTR() : OBJ_STYLE_NONE;
}
const Style& Array::GetCellStyleTR( size_t nCol, size_t nRow ) const
@@ -612,7 +682,7 @@ const Style& Array::GetCellStyleTR( size_t nCol, size_t nRow ) const
size_t nFirstRow = mxImpl->GetMergedFirstRow( nCol, nRow );
size_t nLastCol = mxImpl->GetMergedLastCol( nCol, nRow );
return ((nCol == nLastCol) && (nRow == nFirstRow)) ?
CELL( mxImpl->GetMergedFirstCol( nCol, nRow ), nFirstRow ).maBLTR : OBJ_STYLE_NONE;
CELL( mxImpl->GetMergedFirstCol( nCol, nRow ), nFirstRow ).GetStyleBLTR() : OBJ_STYLE_NONE;
}
// cell merging
@@ -709,15 +779,6 @@ void Array::SetClipRange( size_t nFirstCol, size_t nFirstRow, size_t nLastCol, s
mxImpl->mnLastClipRow = nLastRow;
}
tools::Rectangle Array::GetClipRangeRectangle() const
{
return tools::Rectangle(
mxImpl->GetColPosition( mxImpl->mnFirstClipCol ),
mxImpl->GetRowPosition( mxImpl->mnFirstClipRow ),
mxImpl->GetColPosition( mxImpl->mnLastClipCol + 1 ),
mxImpl->GetRowPosition( mxImpl->mnLastClipRow + 1 ) );
}
// cell coordinates
void Array::SetXOffset( long nXOffset )
{
@@ -838,11 +899,6 @@ double Array::GetVerDiagAngle( size_t nCol, size_t nRow ) const
return mxImpl->GetVerDiagAngle( nCol, nRow );
}
void Array::SetUseDiagDoubleClipping( bool bSet )
{
mxImpl->mbDiagDblClip = bSet;
}
// mirroring
void Array::MirrorSelfX()
{
@@ -879,6 +935,46 @@ 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, altready 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
@@ -898,10 +994,11 @@ void Array::DrawRange( drawinglayer::processor2d::BaseProcessor2D& rProcessor,
bool bOverlapY = rCell.mbOverlapY;
bool bFirstCol = nCol == nFirstCol;
bool bFirstRow = nRow == nFirstRow;
if ((!bOverlapX && !bOverlapY) || (bFirstCol && bFirstRow) ||
(!bOverlapY && bFirstCol) || (!bOverlapX && bFirstRow))
if ((!bOverlapX && !bOverlapY) || (bFirstCol && bFirstRow) || (!bOverlapY && bFirstCol) || (!bOverlapX && bFirstRow))
{
const tools::Rectangle aRect(GetCellRect(nCol, nRow));
if ((aRect.GetWidth() > 1) && (aRect.GetHeight() > 1))
{
size_t _nFirstCol = mxImpl->GetMergedFirstCol(nCol, nRow);
@@ -915,10 +1012,17 @@ void Array::DrawRange( drawinglayer::processor2d::BaseProcessor2D& rProcessor,
{
drawinglayer::primitive2d::Primitive2DContainer aSequence;
const basegfx::B2DRange aRange(aRect.Left(), aRect.Top(), aRect.Right(), aRect.Bottom());
basegfx::B2DPoint aOrigin;
basegfx::B2DVector aX;
basegfx::B2DVector aY;
CreateCoordinateSystemForCell(aRange, rCell, aOrigin, aX, aY);
CreateDiagFrameBorderPrimitives(
aSequence,
aRange,
aOrigin,
aX,
aY,
rTLBR,
rBLTR,
GetCellStyleLeft(_nFirstCol, _nFirstRow),
@@ -929,7 +1033,7 @@ void Array::DrawRange( drawinglayer::processor2d::BaseProcessor2D& rProcessor,
GetCellStyleBottom(_nFirstCol, _nLastRow),
GetCellStyleRight(_nLastCol, _nFirstRow),
GetCellStyleTop(_nLastCol, _nFirstRow),
nullptr);
pForceColor);
rProcessor.process(aSequence);
}
@@ -945,7 +1049,7 @@ void Array::DrawRange( drawinglayer::processor2d::BaseProcessor2D& rProcessor,
double fTAngle = mxImpl->GetHorDiagAngle( nFirstCol, nRow - 1 );
// *Start*** variables store the data of the left end of the cached frame border
Point aStartPos( mxImpl->GetColPosition( nFirstCol ), mxImpl->GetRowPosition( nRow ) );
basegfx::B2DPoint aStartPos( mxImpl->GetColPosition( nFirstCol ), mxImpl->GetRowPosition( nRow ) );
const Style* pStart = &GetCellStyleTop( nFirstCol, nRow );
DiagStyle aStartLFromTR( GetCellStyleBL( nFirstCol, nRow - 1 ), fTAngle );
const Style* pStartLFromT = &GetCellStyleLeft( nFirstCol, nRow - 1 );
@@ -980,18 +1084,50 @@ void Array::DrawRange( drawinglayer::processor2d::BaseProcessor2D& rProcessor,
DiagStyle aRFromBL( GetCellStyleTR( nCol, nRow ), fAngle );
// check if current frame border can be connected to cached frame border
if( !CheckFrameBorderConnectable( *pStart, rCurr,
aEndRFromTL, rLFromT, aLFromTR, aEndRFromBL, rLFromB, aLFromBR ) )
if( !CheckFrameBorderConnectable( *pStart, rCurr, aEndRFromTL, rLFromT, aLFromTR, aEndRFromBL, rLFromB, aLFromBR ) )
{
// draw previous frame border
Point aEndPos( mxImpl->GetColPosition( nCol ), aStartPos.Y() );
if ((pStart->Prim() || pStart->Secn()) && (aStartPos.X() <= aEndPos.X()))
basegfx::B2DPoint aEndPos( mxImpl->GetColPosition( nCol ), aStartPos.getY() );
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())
{
// 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
const bool bUpper(&pCell->GetStyleTop() == pStart);
const tools::Rectangle aRect(GetCellRect(nCol - 1, bUpper ? nRow : nRow - 1));
const basegfx::B2DRange aRange(aRect.Left(), aRect.Top(), aRect.Right(), aRect.Bottom());
// adapt to cell coordinate system, including shear
CreateCoordinateSystemForCell(aRange, *pCell, aOrigin, aX, aY);
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 uses normalized 2nd axis
aY.normalize();
}
drawinglayer::primitive2d::Primitive2DContainer aSequence(1);
CreateBorderPrimitives(
aSequence,
aStartPos,
aEndPos,
aOrigin,
aX,
aY,
*pStart,
aStartLFromTR,
*pStartLFromT,
@@ -1026,14 +1162,38 @@ void Array::DrawRange( drawinglayer::processor2d::BaseProcessor2D& rProcessor,
}
// draw last frame border
Point aEndPos( mxImpl->GetColPosition( nCol ), aStartPos.Y() );
if ((pStart->Prim() || pStart->Secn()) && (aStartPos.X() <= aEndPos.X()))
basegfx::B2DPoint aEndPos( mxImpl->GetColPosition( nCol ), aStartPos.getY() );
if ((pStart->Prim() || pStart->Secn()) && (aStartPos.getX() <= aEndPos.getX()))
{
// 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())
{
const bool bUpper(&pCell->GetStyleTop() == pStart);
const tools::Rectangle aRect(GetCellRect(nCol - 1, bUpper ? nRow : nRow - 1));
const basegfx::B2DRange aRange(aRect.Left(), aRect.Top(), aRect.Right(), aRect.Bottom());
CreateCoordinateSystemForCell(aRange, *pCell, aOrigin, aX, aY);
if (!bUpper)
{
aOrigin += aY;
}
aY.normalize();
}
drawinglayer::primitive2d::Primitive2DContainer aSequence(1);
CreateBorderPrimitives(
aSequence,
aStartPos,
aEndPos,
aOrigin,
aX,
aY,
*pStart,
aStartLFromTR,
*pStartLFromT,
@@ -1057,7 +1217,7 @@ void Array::DrawRange( drawinglayer::processor2d::BaseProcessor2D& rProcessor,
double fLAngle = mxImpl->GetVerDiagAngle( nCol - 1, nFirstRow );
// *Start*** variables store the data of the top end of the cached frame border
Point aStartPos( mxImpl->GetColPosition( nCol ), mxImpl->GetRowPosition( nFirstRow ) );
basegfx::B2DPoint aStartPos( mxImpl->GetColPosition( nCol ), mxImpl->GetRowPosition( nFirstRow ) );
const Style* pStart = &GetCellStyleLeft( nCol, nFirstRow );
DiagStyle aStartTFromBL( GetCellStyleTR( nCol - 1, nFirstRow ), fLAngle );
const Style* pStartTFromL = &GetCellStyleTop( nCol - 1, nFirstRow );
@@ -1096,9 +1256,38 @@ void Array::DrawRange( drawinglayer::processor2d::BaseProcessor2D& rProcessor,
aEndBFromTL, rTFromL, aTFromBL, aEndBFromTR, rTFromR, aTFromBR ) )
{
// draw previous frame border
Point aEndPos( aStartPos.X(), mxImpl->GetRowPosition( nRow ) );
if ((pStart->Prim() || pStart->Secn()) && (aStartPos.Y() <= aEndPos.Y()))
basegfx::B2DPoint aEndPos( aStartPos.getX(), mxImpl->GetRowPosition( nRow ) );
if ((pStart->Prim() || pStart->Secn()) && (aStartPos.getY() <= aEndPos.getY()))
{
// 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())
{
const bool bLeft(&pCell->GetStyleLeft() == pStart);
const tools::Rectangle aRect(GetCellRect(bLeft ? nCol : nCol - 1, nRow - 1));
const basegfx::B2DRange aRange(aRect.Left(), aRect.Top(), aRect.Right(), aRect.Bottom());
CreateCoordinateSystemForCell(aRange, *pCell, aOrigin, aX, aY);
if (!bLeft)
{
aOrigin += aX;
}
// 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 thest here, checked in debug mode)
std::swap(aX, aY);
aY.normalize();
aY = -aY;
}
drawinglayer::primitive2d::Primitive2DContainer aSequence(1);
CreateBorderPrimitives(
// This replaces DrawVerFrameBorder which went from top to bottom. To be able to use
@@ -1108,10 +1297,11 @@ void Array::DrawRange( drawinglayer::processor2d::BaseProcessor2D& rProcessor,
// 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
// lines.
aSequence,
aStartPos,
aEndPos,
aOrigin,
aX,
aY,
*pStart,
aStartTFromBR,
*pStartTFromR,
@@ -1146,15 +1336,44 @@ void Array::DrawRange( drawinglayer::processor2d::BaseProcessor2D& rProcessor,
}
// draw last frame border
Point aEndPos( aStartPos.X(), mxImpl->GetRowPosition( nRow ) );
if ((pStart->Prim() || pStart->Secn()) && (aStartPos.Y() <= aEndPos.Y()))
basegfx::B2DPoint aEndPos( aStartPos.getX(), mxImpl->GetRowPosition( nRow ) );
if ((pStart->Prim() || pStart->Secn()) && (aStartPos.getY() <= aEndPos.getY()))
{
// 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())
{
const bool bLeft(&pCell->GetStyleLeft() == pStart);
const tools::Rectangle aRect(GetCellRect(bLeft ? nCol : nCol - 1, nRow - 1));
const basegfx::B2DRange aRange(aRect.Left(), aRect.Top(), aRect.Right(), aRect.Bottom());
CreateCoordinateSystemForCell(aRange, *pCell, aOrigin, aX, aY);
if (!bLeft)
{
aOrigin += aX;
}
// 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;
}
drawinglayer::primitive2d::Primitive2DContainer aSequence(1);
CreateBorderPrimitives(
// also reordered, see call to CreateBorderPrimitives above
aSequence,
aStartPos,
aEndPos,
aOrigin,
aX,
aY,
*pStart,
aStartTFromBR,
*pStartTFromR,
@@ -1172,224 +1391,12 @@ void Array::DrawRange( drawinglayer::processor2d::BaseProcessor2D& rProcessor,
}
}
void Array::DrawRange( OutputDevice& rDev,
size_t nFirstCol, size_t nFirstRow, size_t nLastCol, size_t nLastRow ) const
{
DBG_FRAME_CHECK_COLROW( nFirstCol, nFirstRow, "DrawRange" );
DBG_FRAME_CHECK_COLROW( nLastCol, nLastRow, "DrawRange" );
size_t nCol, nRow;
// *** diagonal frame borders ***
// set clipping region to clip partly visible merged cells
rDev.Push( PushFlags::CLIPREGION );
rDev.IntersectClipRegion( GetClipRangeRectangle() );
for( nRow = nFirstRow; nRow <= nLastRow; ++nRow )
{
for( nCol = nFirstCol; nCol <= nLastCol; ++nCol )
{
const Cell& rCell = CELL( nCol, nRow );
bool bOverlapX = rCell.mbOverlapX;
bool bOverlapY = rCell.mbOverlapY;
bool bFirstCol = nCol == nFirstCol;
bool bFirstRow = nRow == nFirstRow;
if( (!bOverlapX && !bOverlapY) || (bFirstCol && bFirstRow) ||
(!bOverlapY && bFirstCol) || (!bOverlapX && bFirstRow) )
{
tools::Rectangle aRect( GetCellRect( nCol, nRow ) );
if( (aRect.GetWidth() > 1) && (aRect.GetHeight() > 1) )
{
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 );
DrawDiagFrameBorders( rDev, aRect,
GetCellStyleTLBR( _nFirstCol, _nFirstRow ), GetCellStyleBLTR( _nFirstCol, _nFirstRow ),
GetCellStyleLeft( _nFirstCol, _nFirstRow ), GetCellStyleTop( _nFirstCol, _nFirstRow ),
GetCellStyleRight( _nLastCol, _nLastRow ), GetCellStyleBottom( _nLastCol, _nLastRow ),
GetCellStyleLeft( _nFirstCol, _nLastRow ), GetCellStyleBottom( _nFirstCol, _nLastRow ),
GetCellStyleRight( _nLastCol, _nFirstRow ), GetCellStyleTop( _nLastCol, _nFirstRow ),
nullptr, mxImpl->mbDiagDblClip );
}
}
}
}
rDev.Pop(); // clip region
// *** horizontal frame borders ***
for( nRow = nFirstRow; nRow <= nLastRow + 1; ++nRow )
{
double fAngle = mxImpl->GetHorDiagAngle( nFirstCol, nRow );
double fTAngle = mxImpl->GetHorDiagAngle( nFirstCol, nRow - 1 );
// *Start*** variables store the data of the left end of the cached frame border
Point aStartPos( mxImpl->GetColPosition( nFirstCol ), mxImpl->GetRowPosition( nRow ) );
const Style* pStart = &GetCellStyleTop( nFirstCol, nRow );
DiagStyle aStartLFromTR( GetCellStyleBL( nFirstCol, nRow - 1 ), fTAngle );
const Style* pStartLFromT = &GetCellStyleLeft( nFirstCol, nRow - 1 );
const Style* pStartLFromL = &GetCellStyleTop( nFirstCol - 1, nRow );
const Style* pStartLFromB = &GetCellStyleLeft( nFirstCol, nRow );
DiagStyle aStartLFromBR( GetCellStyleTL( nFirstCol, nRow ), fAngle );
// *End*** variables store the data of the right end of the cached frame border
DiagStyle aEndRFromTL( GetCellStyleBR( nFirstCol, nRow - 1 ), fTAngle );
const Style* pEndRFromT = &GetCellStyleRight( nFirstCol, nRow - 1 );
const Style* pEndRFromR = &GetCellStyleTop( nFirstCol + 1, nRow );
const Style* pEndRFromB = &GetCellStyleRight( nFirstCol, nRow );
DiagStyle aEndRFromBL( GetCellStyleTR( nFirstCol, nRow ), fAngle );
for( nCol = nFirstCol + 1; nCol <= nLastCol; ++nCol )
{
fAngle = mxImpl->GetHorDiagAngle( nCol, nRow );
fTAngle = mxImpl->GetHorDiagAngle( nCol, nRow - 1 );
const Style& rCurr = *pEndRFromR;
DiagStyle aLFromTR( GetCellStyleBL( nCol, nRow - 1 ), fTAngle );
const Style& rLFromT = *pEndRFromT;
const Style& rLFromL = *pStart;
const Style& rLFromB = *pEndRFromB;
DiagStyle aLFromBR( GetCellStyleTL( nCol, nRow ), fAngle );
DiagStyle aRFromTL( GetCellStyleBR( nCol, nRow - 1 ), fTAngle );
const Style& rRFromT = GetCellStyleRight( nCol, nRow - 1 );
const Style& rRFromR = GetCellStyleTop( nCol + 1, nRow );
const Style& rRFromB = GetCellStyleRight( nCol, nRow );
DiagStyle aRFromBL( GetCellStyleTR( nCol, nRow ), fAngle );
// check if current frame border can be connected to cached frame border
if( !CheckFrameBorderConnectable( *pStart, rCurr,
aEndRFromTL, rLFromT, aLFromTR, aEndRFromBL, rLFromB, aLFromBR ) )
{
// draw previous frame border
Point aEndPos( mxImpl->GetColPosition( nCol ), aStartPos.Y() );
if( pStart->Prim() && (aStartPos.X() <= aEndPos.X()) )
DrawHorFrameBorder( rDev, aStartPos, aEndPos, *pStart,
aStartLFromTR, *pStartLFromT, *pStartLFromL, *pStartLFromB, aStartLFromBR,
aEndRFromTL, *pEndRFromT, *pEndRFromR, *pEndRFromB, aEndRFromBL );
// re-init "*Start***" variables
aStartPos = aEndPos;
pStart = &rCurr;
aStartLFromTR = aLFromTR;
pStartLFromT = &rLFromT;
pStartLFromL = &rLFromL;
pStartLFromB = &rLFromB;
aStartLFromBR = aLFromBR;
}
// store current styles in "*End***" variables
aEndRFromTL = aRFromTL;
pEndRFromT = &rRFromT;
pEndRFromR = &rRFromR;
pEndRFromB = &rRFromB;
aEndRFromBL = aRFromBL;
}
// draw last frame border
Point aEndPos( mxImpl->GetColPosition( nCol ), aStartPos.Y() );
if( pStart->Prim() && (aStartPos.X() <= aEndPos.X()) )
DrawHorFrameBorder( rDev, aStartPos, aEndPos, *pStart,
aStartLFromTR, *pStartLFromT, *pStartLFromL, *pStartLFromB, aStartLFromBR,
aEndRFromTL, *pEndRFromT, *pEndRFromR, *pEndRFromB, aEndRFromBL );
}
// *** vertical frame borders ***
for( nCol = nFirstCol; nCol <= nLastCol + 1; ++nCol )
{
double fAngle = mxImpl->GetVerDiagAngle( nCol, nFirstRow );
double fLAngle = mxImpl->GetVerDiagAngle( nCol - 1, nFirstRow );
// *Start*** variables store the data of the top end of the cached frame border
Point aStartPos( mxImpl->GetColPosition( nCol ), mxImpl->GetRowPosition( nFirstRow ) );
const Style* pStart = &GetCellStyleLeft( nCol, nFirstRow );
DiagStyle aStartTFromBL( GetCellStyleTR( nCol - 1, nFirstRow ), fLAngle );
const Style* pStartTFromL = &GetCellStyleTop( nCol - 1, nFirstRow );
const Style* pStartTFromT = &GetCellStyleLeft( nCol, nFirstRow - 1 );
const Style* pStartTFromR = &GetCellStyleTop( nCol, nFirstRow );
DiagStyle aStartTFromBR( GetCellStyleTL( nCol, nFirstRow ), fAngle );
// *End*** variables store the data of the bottom end of the cached frame border
DiagStyle aEndBFromTL( GetCellStyleBR( nCol - 1, nFirstRow ), fLAngle );
const Style* pEndBFromL = &GetCellStyleBottom( nCol - 1, nFirstRow );
const Style* pEndBFromB = &GetCellStyleLeft( nCol, nFirstRow + 1 );
const Style* pEndBFromR = &GetCellStyleBottom( nCol, nFirstRow );
DiagStyle aEndBFromTR( GetCellStyleBL( nCol, nFirstRow ), fAngle );
for( nRow = nFirstRow + 1; nRow <= nLastRow; ++nRow )
{
fAngle = mxImpl->GetVerDiagAngle( nCol, nRow );
fLAngle = mxImpl->GetVerDiagAngle( nCol - 1, nRow );
const Style& rCurr = *pEndBFromB;
DiagStyle aTFromBL( GetCellStyleTR( nCol - 1, nRow ), fLAngle );
const Style& rTFromL = *pEndBFromL;
const Style& rTFromT = *pStart;
const Style& rTFromR = *pEndBFromR;
DiagStyle aTFromBR( GetCellStyleTL( nCol, nRow ), fAngle );
DiagStyle aBFromTL( GetCellStyleBR( nCol - 1, nRow ), fLAngle );
const Style& rBFromL = GetCellStyleBottom( nCol - 1, nRow );
const Style& rBFromB = GetCellStyleLeft( nCol, nRow + 1 );
const Style& rBFromR = GetCellStyleBottom( nCol, nRow );
DiagStyle aBFromTR( GetCellStyleBL( nCol, nRow ), fAngle );
// check if current frame border can be connected to cached frame border
if( !CheckFrameBorderConnectable( *pStart, rCurr,
aEndBFromTL, rTFromL, aTFromBL, aEndBFromTR, rTFromR, aTFromBR ) )
{
// draw previous frame border
Point aEndPos( aStartPos.X(), mxImpl->GetRowPosition( nRow ) );
if( pStart->Prim() && (aStartPos.Y() <= aEndPos.Y()) )
DrawVerFrameBorder( rDev, aStartPos, aEndPos, *pStart,
aStartTFromBL, *pStartTFromL, *pStartTFromT, *pStartTFromR, aStartTFromBR,
aEndBFromTL, *pEndBFromL, *pEndBFromB, *pEndBFromR, aEndBFromTR );
// re-init "*Start***" variables
aStartPos = aEndPos;
pStart = &rCurr;
aStartTFromBL = aTFromBL;
pStartTFromL = &rTFromL;
pStartTFromT = &rTFromT;
pStartTFromR = &rTFromR;
aStartTFromBR = aTFromBR;
}
// store current styles in "*End***" variables
aEndBFromTL = aBFromTL;
pEndBFromL = &rBFromL;
pEndBFromB = &rBFromB;
pEndBFromR = &rBFromR;
aEndBFromTR = aBFromTR;
}
// draw last frame border
Point aEndPos( aStartPos.X(), mxImpl->GetRowPosition( nRow ) );
if( pStart->Prim() && (aStartPos.Y() <= aEndPos.Y()) )
DrawVerFrameBorder( rDev, aStartPos, aEndPos, *pStart,
aStartTFromBL, *pStartTFromL, *pStartTFromT, *pStartTFromR, aStartTFromBR,
aEndBFromTL, *pEndBFromL, *pEndBFromB, *pEndBFromR, aEndBFromTR );
}
}
void Array::DrawArray( OutputDevice& rDev ) const
{
if( mxImpl->mnWidth && mxImpl->mnHeight )
DrawRange( rDev, 0, 0, mxImpl->mnWidth - 1, mxImpl->mnHeight - 1 );
}
void Array::DrawArray(drawinglayer::processor2d::BaseProcessor2D& rProcessor) const
{
if (mxImpl->mnWidth && mxImpl->mnHeight)
DrawRange(rProcessor, 0, 0, mxImpl->mnWidth - 1, mxImpl->mnHeight - 1, nullptr);
}
#undef ORIGCELL
#undef CELLACC
#undef CELL
diff --git a/svx/source/dialog/frmsel.cxx b/svx/source/dialog/frmsel.cxx
index aaf9354..9356785 100644
--- a/svx/source/dialog/frmsel.cxx
+++ b/svx/source/dialog/frmsel.cxx
@@ -380,7 +380,6 @@ void FrameSelectorImpl::InitBorderGeometry()
// Frame helper array
maArray.Initialize( mbVer ? 2 : 1, mbHor ? 2 : 1 );
maArray.SetUseDiagDoubleClipping( true );
maArray.SetXOffset( mnLine1 );
maArray.SetAllColWidths( (mbVer ? mnLine2 : mnLine3) - mnLine1 );
@@ -671,33 +670,25 @@ void FrameSelectorImpl::DrawAllFrameBorders()
// Let the helper array draw itself
static bool bUsePrimitives(true);
if (bUsePrimitives)
{
// This is used in the dialog/control for 'Border' attributes. When using
// the original paint below instead of primitives, the advantage currently
// is the correct visualization of diagonal line(s) including overlaying,
// but the rest is bad. Since the edit views use primitives and the preview
// should be 'real' I opt for also changing this to primitives. I will
// keep the old solution and add a switch (above) based on a static bool so
// that interested people may test this out in the debugger.
// This is one more hint to enhance the primitive visualization further to
// support diagonals better - that's the way to go.
const drawinglayer::geometry::ViewInformation2D aNewViewInformation2D;
std::unique_ptr<drawinglayer::processor2d::BaseProcessor2D> pProcessor2D(
drawinglayer::processor2d::createPixelProcessor2DFromOutputDevice(
*mpVirDev.get(),
aNewViewInformation2D));
// This is used in the dialog/control for 'Border' attributes. When using
// the original paint below instead of primitives, the advantage currently
// is the correct visualization of diagonal line(s) including overlaying,
// but the rest is bad. Since the edit views use primitives and the preview
// should be 'real' I opt for also changing this to primitives. I will
// keep the old solution and add a switch (above) based on a static bool so
// that interested people may test this out in the debugger.
// This is one more hint to enhance the primitive visualization further to
// support diagonals better - that's the way to go.
const drawinglayer::geometry::ViewInformation2D aNewViewInformation2D;
std::unique_ptr<drawinglayer::processor2d::BaseProcessor2D> pProcessor2D(
drawinglayer::processor2d::createPixelProcessor2DFromOutputDevice(
*mpVirDev.get(),
aNewViewInformation2D));
if (pProcessor2D)
{
maArray.DrawArray(*pProcessor2D.get());
pProcessor2D.reset();
}
}
else
if (pProcessor2D)
{
// original paint
maArray.DrawArray(*mpVirDev.get());
maArray.DrawArray(*pProcessor2D.get());
pProcessor2D.reset();
}
}
diff --git a/sw/Library_swui.mk b/sw/Library_swui.mk
index a614daf..e33d164 100644
--- a/sw/Library_swui.mk
+++ b/sw/Library_swui.mk
@@ -71,6 +71,7 @@ $(eval $(call gb_Library_use_libraries,swui,\
ucbhelper \
utl \
vcl \
drawinglayer \
))
$(eval $(call gb_Library_add_exception_objects,swui,\
diff --git a/sw/source/core/layout/paintfrm.cxx b/sw/source/core/layout/paintfrm.cxx
index d136f6f..cbb9ed9 100644
--- a/sw/source/core/layout/paintfrm.cxx
+++ b/sw/source/core/layout/paintfrm.cxx
@@ -2746,11 +2746,16 @@ void SwTabFramePainter::PaintLines(OutputDevice& rDev, const SwRect& rRect) cons
if (bHori)
{
const basegfx::B2DPoint aOrigin(aPaintStart.X(), aPaintStart.Y());
const basegfx::B2DVector aX(basegfx::B2DPoint(aPaintEnd.X(), aPaintEnd.Y()) - aOrigin);
const basegfx::B2DVector aY(basegfx::getNormalizedPerpendicular(aX));
drawinglayer::primitive2d::Primitive2DContainer aSequence(1);
svx::frame::CreateBorderPrimitives(
aSequence,
aPaintStart,
aPaintEnd,
aOrigin,
aX,
aY,
aStyles[ 0 ], // current style
aStyles[ 1 ], // aLFromT
aStyles[ 2 ], // aLFromL
@@ -2763,11 +2768,16 @@ void SwTabFramePainter::PaintLines(OutputDevice& rDev, const SwRect& rRect) cons
}
else
{
const basegfx::B2DPoint aOrigin(aPaintEnd.X(), aPaintEnd.Y());
const basegfx::B2DVector aX(basegfx::B2DPoint(aPaintStart.X(), aPaintStart.Y()) - aOrigin);
const basegfx::B2DVector aY(basegfx::getNormalizedPerpendicular(aX));
drawinglayer::primitive2d::Primitive2DContainer aSequence(1);
svx::frame::CreateBorderPrimitives(
aSequence,
aPaintEnd,
aPaintStart,
aOrigin,
aX,
aY,
aStyles[ 0 ], // current style
aStyles[ 4 ], // aBFromL
aStyles[ 5 ], // aBFromB
diff --git a/sw/source/ui/table/tautofmt.cxx b/sw/source/ui/table/tautofmt.cxx
index 0bb614d..6f4a5bf 100644
--- a/sw/source/ui/table/tautofmt.cxx
+++ b/sw/source/ui/table/tautofmt.cxx
@@ -24,7 +24,6 @@
#include <vcl/svapp.hxx>
#include <vcl/settings.hxx>
#include <vcl/builderfactory.hxx>
#include <svl/zforlist.hxx>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/i18n/BreakIterator.hpp>
@@ -32,6 +31,8 @@
#include <svtools/scriptedtext.hxx>
#include <svtools/accessibilityoptions.hxx>
#include <svx/framelinkarray.hxx>
#include <drawinglayer/processor2d/processor2dtools.hxx>
#include "app.hrc"
#include "strings.hrc"
#include "swmodule.hxx"
@@ -819,14 +820,25 @@ void AutoFormatPreview::PaintCells(vcl::RenderContext& rRenderContext)
// 3) border
if (aCurData.IsFrame())
maArray.DrawArray(rRenderContext);
{
const drawinglayer::geometry::ViewInformation2D aNewViewInformation2D;
std::unique_ptr<drawinglayer::processor2d::BaseProcessor2D> pProcessor2D(
drawinglayer::processor2d::createPixelProcessor2DFromOutputDevice(
rRenderContext,
aNewViewInformation2D));
if (pProcessor2D)
{
maArray.DrawArray(*pProcessor2D.get());
pProcessor2D.reset();
}
}
}
void AutoFormatPreview::Init()
{
SetBorderStyle( GetBorderStyle() | WindowBorderStyle::MONO );
maArray.Initialize( 5, 5 );
maArray.SetUseDiagDoubleClipping( false );
nLabelColWidth = 0;
nDataColWidth1 = 0;
nDataColWidth2 = 0;