diff options
author | Armin Le Grand <Armin.Le.Grand@cib.de> | 2017-07-20 15:11:30 +0200 |
---|---|---|
committer | Armin Le Grand <Armin.Le.Grand@cib.de> | 2017-07-28 17:51:56 +0200 |
commit | e32c12a444e5bd0c6735db8e8008340c29a7e25e (patch) | |
tree | 50262efd53047ee92f5f39f9a1fd6c9e00917fc7 /svx | |
parent | 1118e5b986e4df8a417edcd4ee23a40fb64a0a38 (diff) |
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
Diffstat (limited to 'svx')
-rw-r--r-- | svx/source/dialog/framelink.cxx | 1216 | ||||
-rw-r--r-- | svx/source/dialog/framelinkarray.cxx | 577 | ||||
-rw-r--r-- | svx/source/dialog/frmsel.cxx | 45 |
3 files changed, 361 insertions, 1477 deletions
diff --git a/svx/source/dialog/framelink.cxx b/svx/source/dialog/framelink.cxx index 3dd1b5fa1e2b..c193285b1a25 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 09f4e3a53376..839e9bef5d77 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 aaf935418702..93567852d1a9 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)); + + if (pProcessor2D) { - // 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 - { - // original paint - maArray.DrawArray(*mpVirDev.get()); + maArray.DrawArray(*pProcessor2D.get()); + pProcessor2D.reset(); } } |