1*cdf0e10cSrcweir /************************************************************************* 2*cdf0e10cSrcweir * 3*cdf0e10cSrcweir * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4*cdf0e10cSrcweir * 5*cdf0e10cSrcweir * Copyright 2000, 2010 Oracle and/or its affiliates. 6*cdf0e10cSrcweir * 7*cdf0e10cSrcweir * OpenOffice.org - a multi-platform office productivity suite 8*cdf0e10cSrcweir * 9*cdf0e10cSrcweir * This file is part of OpenOffice.org. 10*cdf0e10cSrcweir * 11*cdf0e10cSrcweir * OpenOffice.org is free software: you can redistribute it and/or modify 12*cdf0e10cSrcweir * it under the terms of the GNU Lesser General Public License version 3 13*cdf0e10cSrcweir * only, as published by the Free Software Foundation. 14*cdf0e10cSrcweir * 15*cdf0e10cSrcweir * OpenOffice.org is distributed in the hope that it will be useful, 16*cdf0e10cSrcweir * but WITHOUT ANY WARRANTY; without even the implied warranty of 17*cdf0e10cSrcweir * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18*cdf0e10cSrcweir * GNU Lesser General Public License version 3 for more details 19*cdf0e10cSrcweir * (a copy is included in the LICENSE file that accompanied this code). 20*cdf0e10cSrcweir * 21*cdf0e10cSrcweir * You should have received a copy of the GNU Lesser General Public License 22*cdf0e10cSrcweir * version 3 along with OpenOffice.org. If not, see 23*cdf0e10cSrcweir * <http://www.openoffice.org/license.html> 24*cdf0e10cSrcweir * for a copy of the LGPLv3 License. 25*cdf0e10cSrcweir * 26*cdf0e10cSrcweir ************************************************************************/ 27*cdf0e10cSrcweir 28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 29*cdf0e10cSrcweir #include "precompiled_svx.hxx" 30*cdf0e10cSrcweir #include <svx/framelink.hxx> 31*cdf0e10cSrcweir 32*cdf0e10cSrcweir #include <math.h> 33*cdf0e10cSrcweir #include <vcl/outdev.hxx> 34*cdf0e10cSrcweir #include <editeng/borderline.hxx> 35*cdf0e10cSrcweir 36*cdf0e10cSrcweir // ---------------------------------------------------------------------------- 37*cdf0e10cSrcweir 38*cdf0e10cSrcweir /** Define to select the drawing mode of thin dotted lines. 39*cdf0e10cSrcweir 40*cdf0e10cSrcweir 0 = Draw lines using an own implementation (recommended). Draws always 41*cdf0e10cSrcweir little dots in an appropriate distance. 42*cdf0e10cSrcweir 1 = Draw dotted lines using vcl/LineInfo. Results in dashed lines instead 43*cdf0e10cSrcweir of dotted lines, which may look ugly for diagonal lines. 44*cdf0e10cSrcweir */ 45*cdf0e10cSrcweir #define SVX_FRAME_USE_LINEINFO 0 46*cdf0e10cSrcweir 47*cdf0e10cSrcweir // ---------------------------------------------------------------------------- 48*cdf0e10cSrcweir 49*cdf0e10cSrcweir #if SVX_FRAME_USE_LINEINFO 50*cdf0e10cSrcweir #include <vcl/lineinfo.hxx> 51*cdf0e10cSrcweir #endif 52*cdf0e10cSrcweir 53*cdf0e10cSrcweir namespace svx { 54*cdf0e10cSrcweir namespace frame { 55*cdf0e10cSrcweir 56*cdf0e10cSrcweir // ============================================================================ 57*cdf0e10cSrcweir // ============================================================================ 58*cdf0e10cSrcweir 59*cdf0e10cSrcweir namespace { 60*cdf0e10cSrcweir 61*cdf0e10cSrcweir typedef std::vector< Point > PointVec; 62*cdf0e10cSrcweir 63*cdf0e10cSrcweir // ---------------------------------------------------------------------------- 64*cdf0e10cSrcweir // Link result structs for horizontal and vertical lines and borders. 65*cdf0e10cSrcweir 66*cdf0e10cSrcweir /** Result struct used by the horizontal/vertical frame link functions. 67*cdf0e10cSrcweir 68*cdf0e10cSrcweir This struct is used to return coordinate offsets for one end of a single 69*cdf0e10cSrcweir line in a frame border, i.e. the left end of the primary line of a 70*cdf0e10cSrcweir horizontal frame border. 71*cdf0e10cSrcweir 72*cdf0e10cSrcweir 1) Usage for horizontal lines 73*cdf0e10cSrcweir 74*cdf0e10cSrcweir If this struct is returned by the lclLinkHorFrameBorder() function, each 75*cdf0e10cSrcweir member refers to the X coordinate of one edge of a single line end in a 76*cdf0e10cSrcweir horizontal frame border. They specify an offset to modify this coordinate 77*cdf0e10cSrcweir when the line is painted. The values in this struct may change a 78*cdf0e10cSrcweir rectangular line shape into a line with slanted left or right border, which 79*cdf0e10cSrcweir is used to connect the line with diagonal lines. 80*cdf0e10cSrcweir 81*cdf0e10cSrcweir Usage for a left line end: Usage for a right line end: 82*cdf0e10cSrcweir mnOffs1 mnOffs1 83*cdf0e10cSrcweir <-------> <-------> 84*cdf0e10cSrcweir +-------------------------------+ 85*cdf0e10cSrcweir | the original horizontal line | 86*cdf0e10cSrcweir +-------------------------------+ 87*cdf0e10cSrcweir <-------> <-------> 88*cdf0e10cSrcweir mnOffs2 mnOffs2 89*cdf0e10cSrcweir 90*cdf0e10cSrcweir 2) Usage for vertical lines 91*cdf0e10cSrcweir 92*cdf0e10cSrcweir If this struct is returned by the lclLinkVerFrameBorder() function, each 93*cdf0e10cSrcweir member refers to the Y coordinate of one edge of a single line end in a 94*cdf0e10cSrcweir vertical frame border. They specify an offset to modify this coordinate 95*cdf0e10cSrcweir when the line is painted. The values in this struct may change a 96*cdf0e10cSrcweir rectangular line shape into a line with slanted top or bottom border, which 97*cdf0e10cSrcweir is used to connect the line with diagonal lines. 98*cdf0e10cSrcweir 99*cdf0e10cSrcweir Usage for a top line end: mnOffs1 ^ ^ mnOffs2 100*cdf0e10cSrcweir | +-------+ | 101*cdf0e10cSrcweir v | | v 102*cdf0e10cSrcweir | | 103*cdf0e10cSrcweir | | 104*cdf0e10cSrcweir the original vertical line ---> | | 105*cdf0e10cSrcweir | | 106*cdf0e10cSrcweir | | 107*cdf0e10cSrcweir ^ | | ^ 108*cdf0e10cSrcweir | +-------+ | 109*cdf0e10cSrcweir Usage for a bottom line end: mnOffs1 v v mnOffs2 110*cdf0e10cSrcweir */ 111*cdf0e10cSrcweir struct LineEndResult 112*cdf0e10cSrcweir { 113*cdf0e10cSrcweir long mnOffs1; /// Offset for top or left edge, dependent of context. 114*cdf0e10cSrcweir long mnOffs2; /// Offset for bottom or right edge, dependent of context 115*cdf0e10cSrcweir 116*cdf0e10cSrcweir inline explicit LineEndResult() : mnOffs1( 0 ), mnOffs2( 0 ) {} 117*cdf0e10cSrcweir 118*cdf0e10cSrcweir inline void Swap() { std::swap( mnOffs1, mnOffs2 ); } 119*cdf0e10cSrcweir inline void Negate() { mnOffs1 = -mnOffs1; mnOffs2 = -mnOffs2; } 120*cdf0e10cSrcweir }; 121*cdf0e10cSrcweir 122*cdf0e10cSrcweir /** Result struct used by the horizontal/vertical frame link functions. 123*cdf0e10cSrcweir 124*cdf0e10cSrcweir This struct contains the linking results for one end of a frame border, 125*cdf0e10cSrcweir including both the primary and secondary line ends. 126*cdf0e10cSrcweir */ 127*cdf0e10cSrcweir struct BorderEndResult 128*cdf0e10cSrcweir { 129*cdf0e10cSrcweir LineEndResult maPrim; /// Result for primary line. 130*cdf0e10cSrcweir LineEndResult maSecn; /// Result for secondary line. 131*cdf0e10cSrcweir 132*cdf0e10cSrcweir inline void Negate() { maPrim.Negate(); maSecn.Negate(); } 133*cdf0e10cSrcweir }; 134*cdf0e10cSrcweir 135*cdf0e10cSrcweir /** Result struct used by the horizontal/vertical frame link functions. 136*cdf0e10cSrcweir 137*cdf0e10cSrcweir This struct contains the linking results for both frame border ends, and 138*cdf0e10cSrcweir therefore for the complete frame border. 139*cdf0e10cSrcweir */ 140*cdf0e10cSrcweir struct BorderResult 141*cdf0e10cSrcweir { 142*cdf0e10cSrcweir BorderEndResult maBeg; /// Result for begin of border line (left or top end). 143*cdf0e10cSrcweir BorderEndResult maEnd; /// Result for end of border line (right or bottom end). 144*cdf0e10cSrcweir }; 145*cdf0e10cSrcweir 146*cdf0e10cSrcweir // ---------------------------------------------------------------------------- 147*cdf0e10cSrcweir // Link result structs for diagonal lines and borders. 148*cdf0e10cSrcweir 149*cdf0e10cSrcweir /** Result struct used by the diagonal frame link functions. 150*cdf0e10cSrcweir 151*cdf0e10cSrcweir This struct contains the linking results for one line of a diagonal frame 152*cdf0e10cSrcweir border. 153*cdf0e10cSrcweir */ 154*cdf0e10cSrcweir struct DiagLineResult 155*cdf0e10cSrcweir { 156*cdf0e10cSrcweir long mnLClip; /// Offset for left border of clipping rectangle. 157*cdf0e10cSrcweir long mnRClip; /// Offset for right border of clipping rectangle. 158*cdf0e10cSrcweir long mnTClip; /// Offset for top border of clipping rectangle. 159*cdf0e10cSrcweir long mnBClip; /// Offset for bottom border of clipping rectangle. 160*cdf0e10cSrcweir 161*cdf0e10cSrcweir inline explicit DiagLineResult() : mnLClip( 0 ), mnRClip( 0 ), mnTClip( 0 ), mnBClip( 0 ) {} 162*cdf0e10cSrcweir }; 163*cdf0e10cSrcweir 164*cdf0e10cSrcweir /** Result struct used by the diagonal frame link functions. 165*cdf0e10cSrcweir 166*cdf0e10cSrcweir This struct contains the linking results for one diagonal frame border. 167*cdf0e10cSrcweir */ 168*cdf0e10cSrcweir struct DiagBorderResult 169*cdf0e10cSrcweir { 170*cdf0e10cSrcweir DiagLineResult maPrim; /// Result for primary line. 171*cdf0e10cSrcweir DiagLineResult maSecn; /// Result for secondary line. 172*cdf0e10cSrcweir }; 173*cdf0e10cSrcweir 174*cdf0e10cSrcweir /** Result struct used by the diagonal frame link functions. 175*cdf0e10cSrcweir 176*cdf0e10cSrcweir This struct contains the linking results for both diagonal frame borders. 177*cdf0e10cSrcweir */ 178*cdf0e10cSrcweir struct DiagBordersResult 179*cdf0e10cSrcweir { 180*cdf0e10cSrcweir DiagBorderResult maTLBR; /// Result for top-left to bottom-right frame border. 181*cdf0e10cSrcweir DiagBorderResult maBLTR; /// Result for bottom-left to top-right frame border. 182*cdf0e10cSrcweir }; 183*cdf0e10cSrcweir 184*cdf0e10cSrcweir // ---------------------------------------------------------------------------- 185*cdf0e10cSrcweir 186*cdf0e10cSrcweir /** A helper struct containing two points of a line. 187*cdf0e10cSrcweir */ 188*cdf0e10cSrcweir struct LinePoints 189*cdf0e10cSrcweir { 190*cdf0e10cSrcweir Point maBeg; /// Start position of the line. 191*cdf0e10cSrcweir Point maEnd; /// End position of the line. 192*cdf0e10cSrcweir 193*cdf0e10cSrcweir explicit LinePoints( const Point& rBeg, const Point& rEnd ) : 194*cdf0e10cSrcweir maBeg( rBeg ), maEnd( rEnd ) {} 195*cdf0e10cSrcweir explicit LinePoints( const Rectangle& rRect, bool bTLBR ) : 196*cdf0e10cSrcweir maBeg( bTLBR ? rRect.TopLeft() : rRect.TopRight() ), 197*cdf0e10cSrcweir maEnd( bTLBR ? rRect.BottomRight() : rRect.BottomLeft() ) {} 198*cdf0e10cSrcweir }; 199*cdf0e10cSrcweir 200*cdf0e10cSrcweir // ============================================================================ 201*cdf0e10cSrcweir 202*cdf0e10cSrcweir /** Rounds and casts a double value to a long value. */ 203*cdf0e10cSrcweir inline long lclD2L( double fValue ) 204*cdf0e10cSrcweir { 205*cdf0e10cSrcweir return static_cast< long >( (fValue < 0.0) ? (fValue - 0.5) : (fValue + 0.5) ); 206*cdf0e10cSrcweir } 207*cdf0e10cSrcweir 208*cdf0e10cSrcweir /** Converts a width in twips to a width in another map unit (specified by fScale). */ 209*cdf0e10cSrcweir sal_uInt16 lclScaleValue( long nValue, double fScale, sal_uInt16 nMaxWidth ) 210*cdf0e10cSrcweir { 211*cdf0e10cSrcweir // convert any width except 0 to at least 1 unit 212*cdf0e10cSrcweir // #i61324# 1 twip must scale to 1/100mm 213*cdf0e10cSrcweir return nValue ? static_cast< sal_uInt16 >( std::min< long >( std::max( 214*cdf0e10cSrcweir static_cast< long >( nValue * fScale ), 1L ), nMaxWidth ) ) : 0; 215*cdf0e10cSrcweir } 216*cdf0e10cSrcweir 217*cdf0e10cSrcweir // ---------------------------------------------------------------------------- 218*cdf0e10cSrcweir // Line width offset calculation. 219*cdf0e10cSrcweir 220*cdf0e10cSrcweir /** Returns the start offset of the single/primary line across the frame border. 221*cdf0e10cSrcweir 222*cdf0e10cSrcweir All following lclGet*Beg() and lclGet*End() functions return sub units to 223*cdf0e10cSrcweir increase the computational accuracy, where 256 sub units are equal to 224*cdf0e10cSrcweir 1 map unit of the used OutputDevice. 225*cdf0e10cSrcweir 226*cdf0e10cSrcweir The following pictures show the upper end of a vertical frame border and 227*cdf0e10cSrcweir illustrates the return values of all following lclGet*Beg() and lclGet*End() 228*cdf0e10cSrcweir functions. The first picture shows a single frame border, the second picture 229*cdf0e10cSrcweir shows a double frame border. 230*cdf0e10cSrcweir 231*cdf0e10cSrcweir The functions regard the reference point handling mode of the passed border 232*cdf0e10cSrcweir style. 233*cdf0e10cSrcweir REFMODE_CENTERED: 234*cdf0e10cSrcweir All returned offsets are relative to the middle position of the frame 235*cdf0e10cSrcweir border (offsets left of the middle are returned negative, offsets right 236*cdf0e10cSrcweir of the middle are returned positive). 237*cdf0e10cSrcweir REFMODE_BEGIN: 238*cdf0e10cSrcweir All returned offsets are relative to the begin of the frame border 239*cdf0e10cSrcweir (lclGetBeg() always returns 0). 240*cdf0e10cSrcweir REFMODE_END: 241*cdf0e10cSrcweir All returned offsets are relative to the end of the frame border 242*cdf0e10cSrcweir (lclGetEnd() always returns 0). 243*cdf0e10cSrcweir 244*cdf0e10cSrcweir |<- lclGetEnd() 245*cdf0e10cSrcweir |<- lclGetBeforeBeg() |<- lclGetPrimEnd() 246*cdf0e10cSrcweir | | 247*cdf0e10cSrcweir ||<- lclGetBeg() ||<- lclGetBehindEnd() 248*cdf0e10cSrcweir || || 249*cdf0e10cSrcweir |#################################| 250*cdf0e10cSrcweir direction of | ################################# 251*cdf0e10cSrcweir the frame | ################################# 252*cdf0e10cSrcweir border is | ################################# 253*cdf0e10cSrcweir vertical | ################################# 254*cdf0e10cSrcweir v ################################# 255*cdf0e10cSrcweir | 256*cdf0e10cSrcweir |<- middle of the frame border 257*cdf0e10cSrcweir 258*cdf0e10cSrcweir 259*cdf0e10cSrcweir lclGetDistEnd() ->||<- lclGetSecnBeg() 260*cdf0e10cSrcweir || 261*cdf0e10cSrcweir lclGetBeg() ->| lclGetDistBeg() ->| || |<- lclGetEnd() 262*cdf0e10cSrcweir | | || | 263*cdf0e10cSrcweir lclGetBeforeBeg()->|| lclGetPrimEnd() ->|| || ||<- lclGetBehindEnd() 264*cdf0e10cSrcweir || || || || 265*cdf0e10cSrcweir |######################| |#############| 266*cdf0e10cSrcweir direction of | ###################### ############# 267*cdf0e10cSrcweir the frame | ###################### ############# 268*cdf0e10cSrcweir border is | ###################### ############# 269*cdf0e10cSrcweir vertical | ###################### | ############# 270*cdf0e10cSrcweir v ###################### | ############# 271*cdf0e10cSrcweir primary line | secondary line 272*cdf0e10cSrcweir | 273*cdf0e10cSrcweir |<- middle of the frame border 274*cdf0e10cSrcweir 275*cdf0e10cSrcweir @return 276*cdf0e10cSrcweir The start offset of the single/primary line relative to the reference 277*cdf0e10cSrcweir position of the frame border (sub units; 0 for invisible or one pixel 278*cdf0e10cSrcweir wide single frame styles). 279*cdf0e10cSrcweir */ 280*cdf0e10cSrcweir long lclGetBeg( const Style& rBorder ) 281*cdf0e10cSrcweir { 282*cdf0e10cSrcweir long nPos = 0; 283*cdf0e10cSrcweir switch( rBorder.GetRefMode() ) 284*cdf0e10cSrcweir { 285*cdf0e10cSrcweir case REFMODE_CENTERED: if( rBorder.Prim() ) nPos = -128 * (rBorder.GetWidth() - 1); break; 286*cdf0e10cSrcweir case REFMODE_END: if( rBorder.Prim() ) nPos = -256 * (rBorder.GetWidth() - 1); break; 287*cdf0e10cSrcweir case REFMODE_BEGIN: break; 288*cdf0e10cSrcweir } 289*cdf0e10cSrcweir return nPos; 290*cdf0e10cSrcweir } 291*cdf0e10cSrcweir 292*cdf0e10cSrcweir /** Returns the end offset of the single/secondary line across the frame border. 293*cdf0e10cSrcweir @descr See description of lclGetBeg() for an illustration. 294*cdf0e10cSrcweir @return The end offset of the single/secondary line relative to the 295*cdf0e10cSrcweir reference position of the frame border (sub units; 0 for invisible or one 296*cdf0e10cSrcweir pixel wide single frame styles). */ 297*cdf0e10cSrcweir long lclGetEnd( const Style& rBorder ) 298*cdf0e10cSrcweir { 299*cdf0e10cSrcweir long nPos = 0; 300*cdf0e10cSrcweir switch( rBorder.GetRefMode() ) 301*cdf0e10cSrcweir { 302*cdf0e10cSrcweir case REFMODE_CENTERED: if( rBorder.Prim() ) nPos = 128 * (rBorder.GetWidth() - 1); break; 303*cdf0e10cSrcweir case REFMODE_BEGIN: if( rBorder.Prim() ) nPos = 256 * (rBorder.GetWidth() - 1); break; 304*cdf0e10cSrcweir case REFMODE_END: break; 305*cdf0e10cSrcweir } 306*cdf0e10cSrcweir return nPos; 307*cdf0e10cSrcweir } 308*cdf0e10cSrcweir 309*cdf0e10cSrcweir /** Returns the end offset of the primary line across the frame border. 310*cdf0e10cSrcweir @descr See description of lclGetBeg() for an illustration. 311*cdf0e10cSrcweir @return The end offset of the primary line relative to the reference 312*cdf0e10cSrcweir position of the frame border (sub units; the end of the primary line in a 313*cdf0e10cSrcweir double frame style, otherwise the same as lclGetEnd()). */ 314*cdf0e10cSrcweir inline long lclGetPrimEnd( const Style& rBorder ) 315*cdf0e10cSrcweir { return rBorder.Prim() ? (lclGetBeg( rBorder ) + 256 * (rBorder.Prim() - 1)) : 0; } 316*cdf0e10cSrcweir 317*cdf0e10cSrcweir /** Returns the start offset of the secondary line across the frame border. 318*cdf0e10cSrcweir @descr See description of lclGetBeg() for an illustration. 319*cdf0e10cSrcweir @return The start offset of the secondary line relative to the reference 320*cdf0e10cSrcweir position of the frame border (sub units; 0 for single/invisible border 321*cdf0e10cSrcweir styles). */ 322*cdf0e10cSrcweir inline long lclGetSecnBeg( const Style& rBorder ) 323*cdf0e10cSrcweir { return rBorder.Secn() ? (lclGetEnd( rBorder ) - 256 * (rBorder.Secn() - 1)) : 0; } 324*cdf0e10cSrcweir 325*cdf0e10cSrcweir /** Returns the start offset of the distance space across the frame border. 326*cdf0e10cSrcweir @descr See description of lclGetBeg() for an illustration. 327*cdf0e10cSrcweir @return The start offset of the distance space relative to the reference 328*cdf0e10cSrcweir position of the frame border (sub units; 0 for single/invisible border 329*cdf0e10cSrcweir styles). */ 330*cdf0e10cSrcweir inline long lclGetDistBeg( const Style& rBorder ) 331*cdf0e10cSrcweir { return rBorder.Secn() ? (lclGetBeg( rBorder ) + 256 * rBorder.Prim()) : 0; } 332*cdf0e10cSrcweir 333*cdf0e10cSrcweir /** Returns the end offset of the distance space across the frame border. 334*cdf0e10cSrcweir @descr See description of lclGetBeg() for an illustration. 335*cdf0e10cSrcweir @return The end offset of the distance space relative to the reference 336*cdf0e10cSrcweir position of the frame border (sub units; 0 for single/invisible border 337*cdf0e10cSrcweir styles). */ 338*cdf0e10cSrcweir inline long lclGetDistEnd( const Style& rBorder ) 339*cdf0e10cSrcweir { return rBorder.Secn() ? (lclGetEnd( rBorder ) - 256 * rBorder.Secn()) : 0; } 340*cdf0e10cSrcweir 341*cdf0e10cSrcweir /** Returns the offset before start of single/primary line across the frame border. 342*cdf0e10cSrcweir @descr See description of lclGetBeg() for an illustration. 343*cdf0e10cSrcweir @return The offset directly before start of single/primary line relative 344*cdf0e10cSrcweir to the reference position of the frame border (sub units; a value one less 345*cdf0e10cSrcweir than lclGetBeg() for visible frame styles, or 0 for invisible frame style). */ 346*cdf0e10cSrcweir inline long lclGetBeforeBeg( const Style& rBorder ) 347*cdf0e10cSrcweir { return rBorder.Prim() ? (lclGetBeg( rBorder ) - 256) : 0; } 348*cdf0e10cSrcweir 349*cdf0e10cSrcweir /** Returns the offset behind end of single/secondary line across the frame border. 350*cdf0e10cSrcweir @descr See description of lclGetBeg() for an illustration. 351*cdf0e10cSrcweir @return The offset directly behind end of single/secondary line relative 352*cdf0e10cSrcweir to the reference position of the frame border (sub units; a value one 353*cdf0e10cSrcweir greater than lclGetEnd() for visible frame styles, or 0 for invisible frame 354*cdf0e10cSrcweir style). */ 355*cdf0e10cSrcweir inline long lclGetBehindEnd( const Style& rBorder ) 356*cdf0e10cSrcweir { return rBorder.Prim() ? (lclGetEnd( rBorder ) + 256) : 0; } 357*cdf0e10cSrcweir 358*cdf0e10cSrcweir // ============================================================================ 359*cdf0e10cSrcweir // Linking functions 360*cdf0e10cSrcweir // ============================================================================ 361*cdf0e10cSrcweir 362*cdf0e10cSrcweir // ---------------------------------------------------------------------------- 363*cdf0e10cSrcweir // Linking of single horizontal line ends. 364*cdf0e10cSrcweir 365*cdf0e10cSrcweir /** Calculates X offsets for the left end of a single horizontal frame border. 366*cdf0e10cSrcweir 367*cdf0e10cSrcweir See DrawHorFrameBorder() function for a description of all parameters. 368*cdf0e10cSrcweir 369*cdf0e10cSrcweir @param rResult 370*cdf0e10cSrcweir (out-param) The contained values (sub units) specify offsets for the 371*cdf0e10cSrcweir X coordinates of the left line end. 372*cdf0e10cSrcweir */ 373*cdf0e10cSrcweir void lclLinkLeftEnd_Single( 374*cdf0e10cSrcweir LineEndResult& rResult, const Style& rBorder, 375*cdf0e10cSrcweir const DiagStyle& rLFromTR, const Style& rLFromT, const Style& rLFromL, const Style& rLFromB, const DiagStyle& rLFromBR ) 376*cdf0e10cSrcweir { 377*cdf0e10cSrcweir // both vertical and diagonal frame borders are double 378*cdf0e10cSrcweir if( rLFromT.Secn() && rLFromB.Secn() && rLFromTR.Secn() && rLFromBR.Secn() ) 379*cdf0e10cSrcweir { 380*cdf0e10cSrcweir // take left position of upper and lower secondary start 381*cdf0e10cSrcweir rResult.mnOffs1 = GetBLDiagOffset( lclGetBeg( rBorder ), lclGetSecnBeg( rLFromTR ), rLFromTR.GetAngle() ); 382*cdf0e10cSrcweir rResult.mnOffs2 = GetTLDiagOffset( lclGetEnd( rBorder ), lclGetSecnBeg( rLFromBR ), rLFromBR.GetAngle() ); 383*cdf0e10cSrcweir } 384*cdf0e10cSrcweir else 385*cdf0e10cSrcweir { 386*cdf0e10cSrcweir // both vertical frame borders are double 387*cdf0e10cSrcweir if( rLFromT.Secn() && rLFromB.Secn() ) 388*cdf0e10cSrcweir rResult.mnOffs1 = (!rLFromTR.Secn() && !rLFromBR.Secn() && (rLFromT.GetWidth() == rLFromB.GetWidth())) ? 389*cdf0e10cSrcweir // don't overdraw vertical borders with equal width 390*cdf0e10cSrcweir lclGetBehindEnd( rLFromT ) : 391*cdf0e10cSrcweir // take leftmost start of both secondary lines (#46488#) 392*cdf0e10cSrcweir rResult.mnOffs1 = std::min( lclGetSecnBeg( rLFromT ), lclGetSecnBeg( rLFromB ) ); 393*cdf0e10cSrcweir 394*cdf0e10cSrcweir // single border with equal width coming from left 395*cdf0e10cSrcweir else if( !rLFromL.Secn() && (rLFromL.Prim() == rBorder.Prim()) ) 396*cdf0e10cSrcweir // draw to connection point 397*cdf0e10cSrcweir rResult.mnOffs1 = 0; 398*cdf0e10cSrcweir 399*cdf0e10cSrcweir // single border coming from left 400*cdf0e10cSrcweir else if( !rLFromL.Secn() && rLFromL.Prim() ) 401*cdf0e10cSrcweir { 402*cdf0e10cSrcweir if( rLFromL.Prim() == rBorder.Prim() ) 403*cdf0e10cSrcweir // draw to reference position, if from left has equal width 404*cdf0e10cSrcweir rResult.mnOffs1 = 0; 405*cdf0e10cSrcweir else 406*cdf0e10cSrcweir rResult.mnOffs1 = (rLFromL < rBorder) ? 407*cdf0e10cSrcweir // take leftmost start of both frame borders, if from left is thinner 408*cdf0e10cSrcweir std::min( lclGetBeg( rLFromT ), lclGetBeg( rLFromB ) ) : 409*cdf0e10cSrcweir // do not overdraw vertical, if from left is thicker 410*cdf0e10cSrcweir std::max( lclGetBehindEnd( rLFromT ), lclGetBehindEnd( rLFromB ) ); 411*cdf0e10cSrcweir } 412*cdf0e10cSrcweir 413*cdf0e10cSrcweir // no border coming from left 414*cdf0e10cSrcweir else if( !rLFromL.Prim() ) 415*cdf0e10cSrcweir // don't overdraw vertical borders with equal width 416*cdf0e10cSrcweir rResult.mnOffs1 = (rLFromT.GetWidth() == rLFromB.GetWidth()) ? 417*cdf0e10cSrcweir lclGetBehindEnd( rLFromT ) : 418*cdf0e10cSrcweir std::min( lclGetBeg( rLFromT ), lclGetBeg( rLFromB ) ); 419*cdf0e10cSrcweir 420*cdf0e10cSrcweir // double frame border coming from left and from top 421*cdf0e10cSrcweir else if( rLFromT.Secn() ) 422*cdf0e10cSrcweir // do not overdraw the vertical double frame border 423*cdf0e10cSrcweir rResult.mnOffs1 = lclGetBehindEnd( rLFromT ); 424*cdf0e10cSrcweir 425*cdf0e10cSrcweir // double frame border coming from left and from bottom 426*cdf0e10cSrcweir else if( rLFromB.Secn() ) 427*cdf0e10cSrcweir // do not overdraw the vertical double frame border 428*cdf0e10cSrcweir rResult.mnOffs1 = lclGetBehindEnd( rLFromB ); 429*cdf0e10cSrcweir 430*cdf0e10cSrcweir // double frame border coming from left, both vertical frame borders are single or off 431*cdf0e10cSrcweir else 432*cdf0e10cSrcweir // draw from leftmost start of both frame borders, if from left is not thicker 433*cdf0e10cSrcweir rResult.mnOffs1 = (rLFromL <= rBorder) ? 434*cdf0e10cSrcweir std::min( lclGetBeg( rLFromT ), lclGetBeg( rLFromB ) ) : 435*cdf0e10cSrcweir std::max( lclGetBehindEnd( rLFromT ), lclGetBehindEnd( rLFromB ) ); 436*cdf0e10cSrcweir 437*cdf0e10cSrcweir // bottom-left point is equal to top-left point (results in rectangle) 438*cdf0e10cSrcweir rResult.mnOffs2 = rResult.mnOffs1; 439*cdf0e10cSrcweir } 440*cdf0e10cSrcweir } 441*cdf0e10cSrcweir 442*cdf0e10cSrcweir /** Calculates X offsets for the left end of a primary horizontal line. 443*cdf0e10cSrcweir 444*cdf0e10cSrcweir See DrawHorFrameBorder() function for a description of all parameters. 445*cdf0e10cSrcweir 446*cdf0e10cSrcweir @param rResult 447*cdf0e10cSrcweir (out-param) The contained values (sub units) specify offsets for the 448*cdf0e10cSrcweir X coordinates of the left end of the primary line. 449*cdf0e10cSrcweir */ 450*cdf0e10cSrcweir void lclLinkLeftEnd_Prim( 451*cdf0e10cSrcweir LineEndResult& rResult, const Style& rBorder, 452*cdf0e10cSrcweir const DiagStyle& rLFromTR, const Style& rLFromT, const Style& rLFromL, const Style& rLFromB, const DiagStyle& /*rLFromBR*/ ) 453*cdf0e10cSrcweir { 454*cdf0e10cSrcweir // double diagonal frame border coming from top right 455*cdf0e10cSrcweir if( rLFromTR.Secn() ) 456*cdf0e10cSrcweir { 457*cdf0e10cSrcweir // draw from where secondary diagonal line meets the own primary 458*cdf0e10cSrcweir rResult.mnOffs1 = GetBLDiagOffset( lclGetBeg( rBorder ), lclGetSecnBeg( rLFromTR ), rLFromTR.GetAngle() ); 459*cdf0e10cSrcweir rResult.mnOffs2 = GetBLDiagOffset( lclGetPrimEnd( rBorder ), lclGetSecnBeg( rLFromTR ), rLFromTR.GetAngle() ); 460*cdf0e10cSrcweir } 461*cdf0e10cSrcweir 462*cdf0e10cSrcweir // no or single diagonal frame border - ignore it 463*cdf0e10cSrcweir else 464*cdf0e10cSrcweir { 465*cdf0e10cSrcweir // double frame border coming from top 466*cdf0e10cSrcweir if( rLFromT.Secn() ) 467*cdf0e10cSrcweir // draw from left edge of secondary vertical 468*cdf0e10cSrcweir rResult.mnOffs1 = lclGetSecnBeg( rLFromT ); 469*cdf0e10cSrcweir 470*cdf0e10cSrcweir // double frame border coming from left (from top is not double) 471*cdf0e10cSrcweir else if( rLFromL.Secn() ) 472*cdf0e10cSrcweir // do not overdraw single frame border coming from top 473*cdf0e10cSrcweir rResult.mnOffs1 = (rLFromL.GetWidth() == rBorder.GetWidth()) ? 474*cdf0e10cSrcweir 0 : lclGetBehindEnd( rLFromT ); 475*cdf0e10cSrcweir 476*cdf0e10cSrcweir // double frame border coming from bottom (from top and from left are not double) 477*cdf0e10cSrcweir else if( rLFromB.Secn() ) 478*cdf0e10cSrcweir // draw from left edge of primary vertical from bottom 479*cdf0e10cSrcweir rResult.mnOffs1 = lclGetBeg( rLFromB ); 480*cdf0e10cSrcweir 481*cdf0e10cSrcweir // no other frame border is double 482*cdf0e10cSrcweir else 483*cdf0e10cSrcweir // do not overdraw vertical frame borders 484*cdf0e10cSrcweir rResult.mnOffs1 = std::max( lclGetBehindEnd( rLFromT ), lclGetBehindEnd( rLFromB ) ); 485*cdf0e10cSrcweir 486*cdf0e10cSrcweir // bottom-left point is equal to top-left point (results in rectangle) 487*cdf0e10cSrcweir rResult.mnOffs2 = rResult.mnOffs1; 488*cdf0e10cSrcweir } 489*cdf0e10cSrcweir } 490*cdf0e10cSrcweir 491*cdf0e10cSrcweir /** Calculates X offsets for the left end of a secondary horizontal line. 492*cdf0e10cSrcweir 493*cdf0e10cSrcweir See DrawHorFrameBorder() function for a description of all parameters. 494*cdf0e10cSrcweir 495*cdf0e10cSrcweir @param rResult 496*cdf0e10cSrcweir (out-param) The contained values (sub units) specify offsets for the 497*cdf0e10cSrcweir X coordinates of the left end of the secondary line. 498*cdf0e10cSrcweir */ 499*cdf0e10cSrcweir void lclLinkLeftEnd_Secn( 500*cdf0e10cSrcweir LineEndResult& rResult, const Style& rBorder, 501*cdf0e10cSrcweir const DiagStyle& rLFromTR, const Style& rLFromT, const Style& rLFromL, const Style& rLFromB, const DiagStyle& rLFromBR ) 502*cdf0e10cSrcweir { 503*cdf0e10cSrcweir /* Recycle lclLinkLeftEnd_Prim() function with mirrored horizontal borders. */ 504*cdf0e10cSrcweir lclLinkLeftEnd_Prim( rResult, rBorder.Mirror(), rLFromBR, rLFromB, rLFromL.Mirror(), rLFromT, rLFromTR ); 505*cdf0e10cSrcweir rResult.Swap(); 506*cdf0e10cSrcweir } 507*cdf0e10cSrcweir 508*cdf0e10cSrcweir // ---------------------------------------------------------------------------- 509*cdf0e10cSrcweir // Linking of horizontal frame border ends. 510*cdf0e10cSrcweir 511*cdf0e10cSrcweir /** Calculates X offsets for the left end of a horizontal frame border. 512*cdf0e10cSrcweir 513*cdf0e10cSrcweir This function can be used for single and double frame borders. 514*cdf0e10cSrcweir See DrawHorFrameBorder() function for a description of all parameters. 515*cdf0e10cSrcweir 516*cdf0e10cSrcweir @param rResult 517*cdf0e10cSrcweir (out-param) The contained values (sub units) specify offsets for the 518*cdf0e10cSrcweir X coordinates of the left end of the line(s) in the frame border. 519*cdf0e10cSrcweir */ 520*cdf0e10cSrcweir void lclLinkLeftEnd( 521*cdf0e10cSrcweir BorderEndResult& rResult, const Style& rBorder, 522*cdf0e10cSrcweir const DiagStyle& rLFromTR, const Style& rLFromT, const Style& rLFromL, const Style& rLFromB, const DiagStyle& rLFromBR ) 523*cdf0e10cSrcweir { 524*cdf0e10cSrcweir if( rBorder.Secn() ) 525*cdf0e10cSrcweir { 526*cdf0e10cSrcweir // current frame border is double 527*cdf0e10cSrcweir lclLinkLeftEnd_Prim( rResult.maPrim, rBorder, rLFromTR, rLFromT, rLFromL, rLFromB, rLFromBR ); 528*cdf0e10cSrcweir lclLinkLeftEnd_Secn( rResult.maSecn, rBorder, rLFromTR, rLFromT, rLFromL, rLFromB, rLFromBR ); 529*cdf0e10cSrcweir } 530*cdf0e10cSrcweir else if( rBorder.Prim() ) 531*cdf0e10cSrcweir { 532*cdf0e10cSrcweir // current frame border is single 533*cdf0e10cSrcweir lclLinkLeftEnd_Single( rResult.maPrim, rBorder, rLFromTR, rLFromT, rLFromL, rLFromB, rLFromBR ); 534*cdf0e10cSrcweir } 535*cdf0e10cSrcweir else 536*cdf0e10cSrcweir { 537*cdf0e10cSrcweir DBG_ERRORFILE( "lclLinkLeftEnd - called for invisible frame style" ); 538*cdf0e10cSrcweir } 539*cdf0e10cSrcweir } 540*cdf0e10cSrcweir 541*cdf0e10cSrcweir /** Calculates X offsets for the right end of a horizontal frame border. 542*cdf0e10cSrcweir 543*cdf0e10cSrcweir This function can be used for single and double frame borders. 544*cdf0e10cSrcweir See DrawHorFrameBorder() function for a description of all parameters. 545*cdf0e10cSrcweir 546*cdf0e10cSrcweir @param rResult 547*cdf0e10cSrcweir (out-param) The contained values (sub units) specify offsets for the 548*cdf0e10cSrcweir X coordinates of the right end of the line(s) in the frame border. 549*cdf0e10cSrcweir */ 550*cdf0e10cSrcweir void lclLinkRightEnd( 551*cdf0e10cSrcweir BorderEndResult& rResult, const Style& rBorder, 552*cdf0e10cSrcweir const DiagStyle& rRFromTL, const Style& rRFromT, const Style& rRFromR, const Style& rRFromB, const DiagStyle& rRFromBL ) 553*cdf0e10cSrcweir { 554*cdf0e10cSrcweir /* Recycle lclLinkLeftEnd() function with mirrored vertical borders. */ 555*cdf0e10cSrcweir lclLinkLeftEnd( rResult, rBorder, rRFromTL.Mirror(), rRFromT.Mirror(), rRFromR, rRFromB.Mirror(), rRFromBL.Mirror() ); 556*cdf0e10cSrcweir rResult.Negate(); 557*cdf0e10cSrcweir } 558*cdf0e10cSrcweir 559*cdf0e10cSrcweir // ---------------------------------------------------------------------------- 560*cdf0e10cSrcweir // Linking of horizontal and vertical frame borders. 561*cdf0e10cSrcweir 562*cdf0e10cSrcweir /** Calculates X offsets for all line ends of a horizontal frame border. 563*cdf0e10cSrcweir 564*cdf0e10cSrcweir This function can be used for single and double frame borders. 565*cdf0e10cSrcweir See DrawHorFrameBorder() function for a description of all parameters. 566*cdf0e10cSrcweir 567*cdf0e10cSrcweir @param rResult 568*cdf0e10cSrcweir (out-param) The contained values (sub units) specify offsets for the 569*cdf0e10cSrcweir X coordinates of both ends of the line(s) in the frame border. To get 570*cdf0e10cSrcweir the actual X coordinates to draw the lines, these offsets have to be 571*cdf0e10cSrcweir added to the X coordinates of the reference points of the frame border 572*cdf0e10cSrcweir (the offsets may be negative). 573*cdf0e10cSrcweir */ 574*cdf0e10cSrcweir void lclLinkHorFrameBorder( 575*cdf0e10cSrcweir BorderResult& rResult, const Style& rBorder, 576*cdf0e10cSrcweir const DiagStyle& rLFromTR, const Style& rLFromT, const Style& rLFromL, const Style& rLFromB, const DiagStyle& rLFromBR, 577*cdf0e10cSrcweir const DiagStyle& rRFromTL, const Style& rRFromT, const Style& rRFromR, const Style& rRFromB, const DiagStyle& rRFromBL ) 578*cdf0e10cSrcweir { 579*cdf0e10cSrcweir lclLinkLeftEnd( rResult.maBeg, rBorder, rLFromTR, rLFromT, rLFromL, rLFromB, rLFromBR ); 580*cdf0e10cSrcweir lclLinkRightEnd( rResult.maEnd, rBorder, rRFromTL, rRFromT, rRFromR, rRFromB, rRFromBL ); 581*cdf0e10cSrcweir } 582*cdf0e10cSrcweir 583*cdf0e10cSrcweir /** Calculates Y offsets for all line ends of a vertical frame border. 584*cdf0e10cSrcweir 585*cdf0e10cSrcweir This function can be used for single and double frame borders. 586*cdf0e10cSrcweir See DrawVerFrameBorder() function for a description of all parameters. 587*cdf0e10cSrcweir 588*cdf0e10cSrcweir @param rResult 589*cdf0e10cSrcweir (out-param) The contained values (sub units) specify offsets for the 590*cdf0e10cSrcweir Y coordinates of both ends of the line(s) in the frame border. To get 591*cdf0e10cSrcweir the actual Y coordinates to draw the lines, these offsets have to be 592*cdf0e10cSrcweir added to the Y coordinates of the reference points of the frame border 593*cdf0e10cSrcweir (the offsets may be negative). 594*cdf0e10cSrcweir */ 595*cdf0e10cSrcweir void lclLinkVerFrameBorder( 596*cdf0e10cSrcweir BorderResult& rResult, const Style& rBorder, 597*cdf0e10cSrcweir const DiagStyle& rTFromBL, const Style& rTFromL, const Style& rTFromT, const Style& rTFromR, const DiagStyle& rTFromBR, 598*cdf0e10cSrcweir const DiagStyle& rBFromTL, const Style& rBFromL, const Style& rBFromB, const Style& rBFromR, const DiagStyle& rBFromTR ) 599*cdf0e10cSrcweir { 600*cdf0e10cSrcweir /* Recycle lclLinkHorFrameBorder() function with correct parameters. The 601*cdf0e10cSrcweir frame border is virtually mirrored at the top-left to bottom-right 602*cdf0e10cSrcweir diagonal. rTFromBR and rBFromTL are mirrored to process their primary 603*cdf0e10cSrcweir and secondary lines correctly. */ 604*cdf0e10cSrcweir lclLinkHorFrameBorder( rResult, rBorder, 605*cdf0e10cSrcweir rTFromBL, rTFromL, rTFromT, rTFromR, rTFromBR.Mirror(), 606*cdf0e10cSrcweir rBFromTL.Mirror(), rBFromL, rBFromB, rBFromR, rBFromTR ); 607*cdf0e10cSrcweir } 608*cdf0e10cSrcweir 609*cdf0e10cSrcweir // ============================================================================ 610*cdf0e10cSrcweir 611*cdf0e10cSrcweir #if 0 612*cdf0e10cSrcweir // Not used anymore, but not deleted for possible future usage. 613*cdf0e10cSrcweir 614*cdf0e10cSrcweir /** Returns the relative Y offset of the intercept point of 2 diagonal borders. 615*cdf0e10cSrcweir 616*cdf0e10cSrcweir @param nTLBROffs 617*cdf0e10cSrcweir Width offset (sub units) across the top-left to bottom-right frame border. 618*cdf0e10cSrcweir @param fTLBRAngle 619*cdf0e10cSrcweir Inner angle between horizontal and top-left to bottom-right frame border. 620*cdf0e10cSrcweir @param nBLTROffs 621*cdf0e10cSrcweir Width offset (sub units) across the bottom-left to top-right frame border. 622*cdf0e10cSrcweir @param fBLTRAngle 623*cdf0e10cSrcweir Inner angle between horizontal and bottom-left to top-right frame border. 624*cdf0e10cSrcweir @return 625*cdf0e10cSrcweir Offset (sub units) relative to the Y position of the centered intercept 626*cdf0e10cSrcweir point of both diagonal frame borders. 627*cdf0e10cSrcweir */ 628*cdf0e10cSrcweir long lclGetDiagDiagOffset( long nTLBROffs, double fTLBRAngle, long nBLTROffs, double fBLTRAngle ) 629*cdf0e10cSrcweir { 630*cdf0e10cSrcweir double fASin = sin( fTLBRAngle ); 631*cdf0e10cSrcweir double fACos = cos( fTLBRAngle ); 632*cdf0e10cSrcweir double fAX = -nTLBROffs * fASin; 633*cdf0e10cSrcweir double fAY = nTLBROffs * fACos; 634*cdf0e10cSrcweir double fRAX = fACos; 635*cdf0e10cSrcweir double fRAY = fASin; 636*cdf0e10cSrcweir 637*cdf0e10cSrcweir double fBSin = sin( fBLTRAngle ); 638*cdf0e10cSrcweir double fBCos = cos( fBLTRAngle ); 639*cdf0e10cSrcweir double fBX = nBLTROffs * fBSin; 640*cdf0e10cSrcweir double fBY = nBLTROffs * fBCos; 641*cdf0e10cSrcweir double fRBX = fBCos; 642*cdf0e10cSrcweir double fRBY = -fBSin; 643*cdf0e10cSrcweir 644*cdf0e10cSrcweir double fKA = (fRBX * (fBY - fAY) - fRBY * (fBX - fAX)) / (fRBX * fRAY - fRAX * fRBY); 645*cdf0e10cSrcweir return lclD2L( fAY + fKA * fRAY ); 646*cdf0e10cSrcweir } 647*cdf0e10cSrcweir #endif 648*cdf0e10cSrcweir 649*cdf0e10cSrcweir // ---------------------------------------------------------------------------- 650*cdf0e10cSrcweir // Linking of diagonal frame borders. 651*cdf0e10cSrcweir 652*cdf0e10cSrcweir /** Calculates clipping offsets for a top-left to bottom-right frame border. 653*cdf0e10cSrcweir 654*cdf0e10cSrcweir This function can be used for single and double frame borders. 655*cdf0e10cSrcweir See DrawDiagFrameBorders() function for a description of all parameters. 656*cdf0e10cSrcweir 657*cdf0e10cSrcweir @param rResult 658*cdf0e10cSrcweir (out-param) The contained values (sub units) specify offsets for all 659*cdf0e10cSrcweir borders of the reference rectangle containing the diagonal frame border. 660*cdf0e10cSrcweir */ 661*cdf0e10cSrcweir void lclLinkTLBRFrameBorder( 662*cdf0e10cSrcweir DiagBorderResult& rResult, const Style& rBorder, 663*cdf0e10cSrcweir const Style& rTLFromB, const Style& rTLFromR, const Style& rBRFromT, const Style& rBRFromL ) 664*cdf0e10cSrcweir { 665*cdf0e10cSrcweir bool bIsDbl = rBorder.Secn() != 0; 666*cdf0e10cSrcweir 667*cdf0e10cSrcweir rResult.maPrim.mnLClip = lclGetBehindEnd( rTLFromB ); 668*cdf0e10cSrcweir rResult.maPrim.mnRClip = (bIsDbl && rBRFromT.Secn()) ? lclGetEnd( rBRFromT ) : lclGetBeforeBeg( rBRFromT ); 669*cdf0e10cSrcweir rResult.maPrim.mnTClip = (bIsDbl && rTLFromR.Secn()) ? lclGetBeg( rTLFromR ) : lclGetBehindEnd( rTLFromR ); 670*cdf0e10cSrcweir rResult.maPrim.mnBClip = lclGetBeforeBeg( rBRFromL ); 671*cdf0e10cSrcweir 672*cdf0e10cSrcweir if( bIsDbl ) 673*cdf0e10cSrcweir { 674*cdf0e10cSrcweir rResult.maSecn.mnLClip = rTLFromB.Secn() ? lclGetBeg( rTLFromB ) : lclGetBehindEnd( rTLFromB ); 675*cdf0e10cSrcweir rResult.maSecn.mnRClip = lclGetBeforeBeg( rBRFromT ); 676*cdf0e10cSrcweir rResult.maSecn.mnTClip = lclGetBehindEnd( rTLFromR ); 677*cdf0e10cSrcweir rResult.maSecn.mnBClip = rBRFromL.Secn() ? lclGetEnd( rBRFromL ) : lclGetBeforeBeg( rBRFromL ); 678*cdf0e10cSrcweir } 679*cdf0e10cSrcweir } 680*cdf0e10cSrcweir 681*cdf0e10cSrcweir /** Calculates clipping offsets for a bottom-left to top-right frame border. 682*cdf0e10cSrcweir 683*cdf0e10cSrcweir This function can be used for single and double frame borders. 684*cdf0e10cSrcweir See DrawDiagFrameBorders() function for a description of all parameters. 685*cdf0e10cSrcweir 686*cdf0e10cSrcweir @param rResult 687*cdf0e10cSrcweir (out-param) The contained values (sub units) specify offsets for all 688*cdf0e10cSrcweir borders of the reference rectangle containing the diagonal frame border. 689*cdf0e10cSrcweir */ 690*cdf0e10cSrcweir void lclLinkBLTRFrameBorder( 691*cdf0e10cSrcweir DiagBorderResult& rResult, const Style& rBorder, 692*cdf0e10cSrcweir const Style& rBLFromT, const Style& rBLFromR, const Style& rTRFromB, const Style& rTRFromL ) 693*cdf0e10cSrcweir { 694*cdf0e10cSrcweir bool bIsDbl = rBorder.Secn() != 0; 695*cdf0e10cSrcweir 696*cdf0e10cSrcweir rResult.maPrim.mnLClip = lclGetBehindEnd( rBLFromT ); 697*cdf0e10cSrcweir rResult.maPrim.mnRClip = (bIsDbl && rTRFromB.Secn()) ? lclGetEnd( rTRFromB ) : lclGetBeforeBeg( rTRFromB ); 698*cdf0e10cSrcweir rResult.maPrim.mnTClip = lclGetBehindEnd( rTRFromL ); 699*cdf0e10cSrcweir rResult.maPrim.mnBClip = (bIsDbl && rBLFromR.Secn()) ? lclGetEnd( rBLFromR ) : lclGetBeforeBeg( rBLFromR ); 700*cdf0e10cSrcweir 701*cdf0e10cSrcweir if( bIsDbl ) 702*cdf0e10cSrcweir { 703*cdf0e10cSrcweir rResult.maSecn.mnLClip = rBLFromT.Secn() ? lclGetBeg( rBLFromT ) : lclGetBehindEnd( rBLFromT ); 704*cdf0e10cSrcweir rResult.maSecn.mnRClip = lclGetBeforeBeg( rTRFromB ); 705*cdf0e10cSrcweir rResult.maSecn.mnTClip = rTRFromL.Secn() ? lclGetBeg( rTRFromL ) : lclGetBehindEnd( rTRFromL ); 706*cdf0e10cSrcweir rResult.maSecn.mnBClip = lclGetBeforeBeg( rBLFromR ); 707*cdf0e10cSrcweir } 708*cdf0e10cSrcweir } 709*cdf0e10cSrcweir 710*cdf0e10cSrcweir /** Calculates clipping offsets for both diagonal frame borders. 711*cdf0e10cSrcweir 712*cdf0e10cSrcweir This function can be used for single and double frame borders. 713*cdf0e10cSrcweir See DrawDiagFrameBorders() function for a description of all parameters. 714*cdf0e10cSrcweir 715*cdf0e10cSrcweir @param rResult 716*cdf0e10cSrcweir (out-param) The contained values (sub units) specify offsets for all 717*cdf0e10cSrcweir borders of the reference rectangle containing the diagonal frame 718*cdf0e10cSrcweir borders. 719*cdf0e10cSrcweir */ 720*cdf0e10cSrcweir void lclLinkDiagFrameBorders( 721*cdf0e10cSrcweir DiagBordersResult& rResult, const Style& rTLBR, const Style& rBLTR, 722*cdf0e10cSrcweir const Style& rTLFromB, const Style& rTLFromR, const Style& rBRFromT, const Style& rBRFromL, 723*cdf0e10cSrcweir const Style& rBLFromT, const Style& rBLFromR, const Style& rTRFromB, const Style& rTRFromL ) 724*cdf0e10cSrcweir { 725*cdf0e10cSrcweir lclLinkTLBRFrameBorder( rResult.maTLBR, rTLBR, rTLFromB, rTLFromR, rBRFromT, rBRFromL ); 726*cdf0e10cSrcweir lclLinkBLTRFrameBorder( rResult.maBLTR, rBLTR, rBLFromT, rBLFromR, rTRFromB, rTRFromL ); 727*cdf0e10cSrcweir } 728*cdf0e10cSrcweir 729*cdf0e10cSrcweir // ============================================================================ 730*cdf0e10cSrcweir // Drawing functions 731*cdf0e10cSrcweir // ============================================================================ 732*cdf0e10cSrcweir 733*cdf0e10cSrcweir // ---------------------------------------------------------------------------- 734*cdf0e10cSrcweir // Simple helper functions 735*cdf0e10cSrcweir 736*cdf0e10cSrcweir /** Converts sub units to OutputDevice map units. */ 737*cdf0e10cSrcweir inline long lclToMapUnit( long nSubUnits ) 738*cdf0e10cSrcweir { 739*cdf0e10cSrcweir return ((nSubUnits < 0) ? (nSubUnits - 127) : (nSubUnits + 128)) / 256; 740*cdf0e10cSrcweir } 741*cdf0e10cSrcweir 742*cdf0e10cSrcweir /** Converts a point in sub units to an OutputDevice point. */ 743*cdf0e10cSrcweir inline Point lclToMapUnit( long nSubXPos, long nSubYPos ) 744*cdf0e10cSrcweir { 745*cdf0e10cSrcweir return Point( lclToMapUnit( nSubXPos ), lclToMapUnit( nSubYPos ) ); 746*cdf0e10cSrcweir } 747*cdf0e10cSrcweir 748*cdf0e10cSrcweir /** Returns a polygon constructed from a vector of points. */ 749*cdf0e10cSrcweir inline Polygon lclCreatePolygon( const PointVec& rPoints ) 750*cdf0e10cSrcweir { 751*cdf0e10cSrcweir return Polygon( static_cast< sal_uInt16 >( rPoints.size() ), &rPoints[ 0 ] ); 752*cdf0e10cSrcweir } 753*cdf0e10cSrcweir 754*cdf0e10cSrcweir /** Returns a polygon constructed from the four passed points. */ 755*cdf0e10cSrcweir Polygon lclCreatePolygon( const Point& rP1, const Point& rP2, const Point& rP3, const Point& rP4 ) 756*cdf0e10cSrcweir { 757*cdf0e10cSrcweir PointVec aPoints; 758*cdf0e10cSrcweir aPoints.reserve( 4 ); 759*cdf0e10cSrcweir aPoints.push_back( rP1 ); 760*cdf0e10cSrcweir aPoints.push_back( rP2 ); 761*cdf0e10cSrcweir aPoints.push_back( rP3 ); 762*cdf0e10cSrcweir aPoints.push_back( rP4 ); 763*cdf0e10cSrcweir return lclCreatePolygon( aPoints ); 764*cdf0e10cSrcweir } 765*cdf0e10cSrcweir 766*cdf0e10cSrcweir /** Returns a polygon constructed from the five passed points. */ 767*cdf0e10cSrcweir Polygon lclCreatePolygon( const Point& rP1, const Point& rP2, const Point& rP3, const Point& rP4, const Point& rP5 ) 768*cdf0e10cSrcweir { 769*cdf0e10cSrcweir PointVec aPoints; 770*cdf0e10cSrcweir aPoints.reserve( 5 ); 771*cdf0e10cSrcweir aPoints.push_back( rP1 ); 772*cdf0e10cSrcweir aPoints.push_back( rP2 ); 773*cdf0e10cSrcweir aPoints.push_back( rP3 ); 774*cdf0e10cSrcweir aPoints.push_back( rP4 ); 775*cdf0e10cSrcweir aPoints.push_back( rP5 ); 776*cdf0e10cSrcweir return lclCreatePolygon( aPoints ); 777*cdf0e10cSrcweir } 778*cdf0e10cSrcweir 779*cdf0e10cSrcweir /** Returns a polygon constructed from the two passed line positions. */ 780*cdf0e10cSrcweir inline Polygon lclCreatePolygon( const LinePoints& rPoints1, const LinePoints& rPoints2 ) 781*cdf0e10cSrcweir { 782*cdf0e10cSrcweir return lclCreatePolygon( rPoints1.maBeg, rPoints1.maEnd, rPoints2.maEnd, rPoints2.maBeg ); 783*cdf0e10cSrcweir } 784*cdf0e10cSrcweir 785*cdf0e10cSrcweir /** Sets the color of the passed frame style to the output device. 786*cdf0e10cSrcweir 787*cdf0e10cSrcweir Sets the line color and fill color in the output device. 788*cdf0e10cSrcweir 789*cdf0e10cSrcweir @param rDev 790*cdf0e10cSrcweir The output device the color has to be set to. The old colors are pushed 791*cdf0e10cSrcweir onto the device's stack and can be restored with a call to 792*cdf0e10cSrcweir OutputDevice::Pop(). Please take care about the correct calling order 793*cdf0e10cSrcweir of Pop() if this function is used with other functions pushing 794*cdf0e10cSrcweir something onto the stack. 795*cdf0e10cSrcweir @param rStyle 796*cdf0e10cSrcweir The border style that contains the line color to be set to the device. 797*cdf0e10cSrcweir */ 798*cdf0e10cSrcweir void lclSetColorToOutDev( OutputDevice& rDev, const Style& rStyle, const Color* pForceColor ) 799*cdf0e10cSrcweir { 800*cdf0e10cSrcweir rDev.Push( PUSH_LINECOLOR | PUSH_FILLCOLOR ); 801*cdf0e10cSrcweir rDev.SetLineColor( pForceColor ? *pForceColor : rStyle.GetColor() ); 802*cdf0e10cSrcweir rDev.SetFillColor( pForceColor ? *pForceColor : rStyle.GetColor() ); 803*cdf0e10cSrcweir } 804*cdf0e10cSrcweir 805*cdf0e10cSrcweir // ---------------------------------------------------------------------------- 806*cdf0e10cSrcweir // Generic drawing functions. 807*cdf0e10cSrcweir 808*cdf0e10cSrcweir /** Draws a thin (1 pixel wide) line, optionally dotted, into the passed output device. */ 809*cdf0e10cSrcweir void lclDrawThinLine( OutputDevice& rDev, const Point& rBeg, const Point& rEnd, bool bDotted ) 810*cdf0e10cSrcweir { 811*cdf0e10cSrcweir #if SVX_FRAME_USE_LINEINFO 812*cdf0e10cSrcweir if( bDotted && (rBeg != rEnd) ) 813*cdf0e10cSrcweir { 814*cdf0e10cSrcweir // using LineInfo for dotted lines looks ugly and does not work well for diagonal lines 815*cdf0e10cSrcweir LineInfo aLineInfo( LINE_DASH, 1 ); 816*cdf0e10cSrcweir aLineInfo.SetDotCount( 1 ); 817*cdf0e10cSrcweir aLineInfo.SetDotLen( 1 ); 818*cdf0e10cSrcweir aLineInfo.SetDistance( 3 ); 819*cdf0e10cSrcweir rDev.DrawLine( rBeg, rEnd, aLineInfo ); 820*cdf0e10cSrcweir } 821*cdf0e10cSrcweir #else 822*cdf0e10cSrcweir Point aBeg( rDev.LogicToPixel( rBeg ) ); 823*cdf0e10cSrcweir Point aEnd( rDev.LogicToPixel( rEnd ) ); 824*cdf0e10cSrcweir if( bDotted && (aBeg != aEnd) ) 825*cdf0e10cSrcweir { 826*cdf0e10cSrcweir bool bHor = Abs( aEnd.X() - aBeg.X() ) > Abs( aEnd.Y() - aBeg.Y() ); 827*cdf0e10cSrcweir const Point& rBegPos( bHor ? ((aBeg.X() < aEnd.X()) ? aBeg : aEnd) : ((aBeg.Y() < aEnd.Y()) ? aBeg : aEnd ) ); 828*cdf0e10cSrcweir const Point& rEndPos( (rBegPos == aBeg) ? aEnd : aBeg ); 829*cdf0e10cSrcweir 830*cdf0e10cSrcweir long nAlongBeg = bHor ? rBegPos.X() : rBegPos.Y(); 831*cdf0e10cSrcweir long nAcrssBeg = bHor ? rBegPos.Y() : rBegPos.X(); 832*cdf0e10cSrcweir long nAlongSize = (bHor ? rEndPos.X() : rEndPos.Y()) - nAlongBeg; 833*cdf0e10cSrcweir long nAcrssSize = (bHor ? rEndPos.Y() : rEndPos.X()) - nAcrssBeg; 834*cdf0e10cSrcweir double fGradient = static_cast< double >( nAcrssSize ) / nAlongSize; 835*cdf0e10cSrcweir 836*cdf0e10cSrcweir PointVec aPoints; 837*cdf0e10cSrcweir aPoints.reserve( (nAlongSize + 1) / 2 ); 838*cdf0e10cSrcweir for( long nAlongIdx = 0; nAlongIdx <= nAlongSize; nAlongIdx += 2 ) 839*cdf0e10cSrcweir { 840*cdf0e10cSrcweir long nAl = nAlongBeg + nAlongIdx; 841*cdf0e10cSrcweir long nAc = nAcrssBeg + lclD2L( fGradient * nAlongIdx ); 842*cdf0e10cSrcweir aPoints.push_back( Point( bHor ? nAl : nAc, bHor ? nAc : nAl ) ); 843*cdf0e10cSrcweir } 844*cdf0e10cSrcweir 845*cdf0e10cSrcweir rDev.Push( PUSH_MAPMODE ); 846*cdf0e10cSrcweir rDev.SetMapMode( MAP_PIXEL ); 847*cdf0e10cSrcweir rDev.DrawPixel( lclCreatePolygon( aPoints ) ); 848*cdf0e10cSrcweir rDev.Pop(); // map mode 849*cdf0e10cSrcweir } 850*cdf0e10cSrcweir #endif 851*cdf0e10cSrcweir else 852*cdf0e10cSrcweir rDev.DrawLine( rBeg, rEnd ); 853*cdf0e10cSrcweir } 854*cdf0e10cSrcweir 855*cdf0e10cSrcweir /** Draws a thin (1 pixel wide) line, optionally dotted, into the passed output device. */ 856*cdf0e10cSrcweir inline void lclDrawThinLine( OutputDevice& rDev, const LinePoints& rPoints, bool bDotted ) 857*cdf0e10cSrcweir { 858*cdf0e10cSrcweir lclDrawThinLine( rDev, rPoints.maBeg, rPoints.maEnd, bDotted ); 859*cdf0e10cSrcweir } 860*cdf0e10cSrcweir 861*cdf0e10cSrcweir /** Draws a polygon with four points into the passed output device. */ 862*cdf0e10cSrcweir inline void lclDrawPolygon( OutputDevice& rDev, const Point& rP1, const Point& rP2, const Point& rP3, const Point& rP4 ) 863*cdf0e10cSrcweir { 864*cdf0e10cSrcweir rDev.DrawPolygon( lclCreatePolygon( rP1, rP2, rP3, rP4 ) ); 865*cdf0e10cSrcweir } 866*cdf0e10cSrcweir 867*cdf0e10cSrcweir /** Draws a polygon specified by two borders into the passed output device. */ 868*cdf0e10cSrcweir inline void lclDrawPolygon( OutputDevice& rDev, const LinePoints& rPoints1, const LinePoints& rPoints2 ) 869*cdf0e10cSrcweir { 870*cdf0e10cSrcweir rDev.DrawPolygon( lclCreatePolygon( rPoints1, rPoints2 ) ); 871*cdf0e10cSrcweir } 872*cdf0e10cSrcweir 873*cdf0e10cSrcweir // ============================================================================ 874*cdf0e10cSrcweir // Drawing of horizontal frame borders. 875*cdf0e10cSrcweir 876*cdf0e10cSrcweir /** Draws a horizontal thin or thick line into the passed output device. 877*cdf0e10cSrcweir 878*cdf0e10cSrcweir The X coordinates of the edges of the line are adjusted according to the 879*cdf0e10cSrcweir passed LineEndResult structs. A one pixel wide line can be drawn dotted. 880*cdf0e10cSrcweir */ 881*cdf0e10cSrcweir void lclDrawHorLine( 882*cdf0e10cSrcweir OutputDevice& rDev, 883*cdf0e10cSrcweir const Point& rLPos, const LineEndResult& rLRes, 884*cdf0e10cSrcweir const Point& rRPos, const LineEndResult& rRRes, 885*cdf0e10cSrcweir long nTOffs, long nBOffs, bool bDotted ) 886*cdf0e10cSrcweir { 887*cdf0e10cSrcweir LinePoints aTPoints( rLPos + lclToMapUnit( rLRes.mnOffs1, nTOffs ), rRPos + lclToMapUnit( rRRes.mnOffs1, nTOffs ) ); 888*cdf0e10cSrcweir if( nTOffs == nBOffs ) 889*cdf0e10cSrcweir lclDrawThinLine( rDev, aTPoints, bDotted ); 890*cdf0e10cSrcweir else 891*cdf0e10cSrcweir { 892*cdf0e10cSrcweir LinePoints aBPoints( rLPos + lclToMapUnit( rLRes.mnOffs2, nBOffs ), rRPos + lclToMapUnit( rRRes.mnOffs2, nBOffs ) ); 893*cdf0e10cSrcweir lclDrawPolygon( rDev, aTPoints, aBPoints ); 894*cdf0e10cSrcweir } 895*cdf0e10cSrcweir } 896*cdf0e10cSrcweir 897*cdf0e10cSrcweir /** Draws a horizontal frame border into the passed output device. 898*cdf0e10cSrcweir 899*cdf0e10cSrcweir @param rLPos 900*cdf0e10cSrcweir The top-left or bottom-left reference point of the diagonal frame border. 901*cdf0e10cSrcweir @param rRPos 902*cdf0e10cSrcweir The top-right or bottom-right reference point of the diagonal frame border. 903*cdf0e10cSrcweir @param rBorder 904*cdf0e10cSrcweir The frame style used to draw the border. 905*cdf0e10cSrcweir @param rResult 906*cdf0e10cSrcweir The X coordinates of the edges of all lines of the frame border are 907*cdf0e10cSrcweir adjusted according to the offsets contained here. 908*cdf0e10cSrcweir */ 909*cdf0e10cSrcweir void lclDrawHorFrameBorder( 910*cdf0e10cSrcweir OutputDevice& rDev, const Point& rLPos, const Point& rRPos, 911*cdf0e10cSrcweir const Style& rBorder, const BorderResult& rResult, const Color* pForceColor ) 912*cdf0e10cSrcweir { 913*cdf0e10cSrcweir DBG_ASSERT( rBorder.Prim(), "svx::frame::lclDrawHorFrameBorder - line not visible" ); 914*cdf0e10cSrcweir DBG_ASSERT( rLPos.X() <= rRPos.X(), "svx::frame::lclDrawHorFrameBorder - wrong order of line ends" ); 915*cdf0e10cSrcweir DBG_ASSERT( rLPos.Y() == rRPos.Y(), "svx::frame::lclDrawHorFrameBorder - line not horizontal" ); 916*cdf0e10cSrcweir if( rLPos.X() <= rRPos.X() ) 917*cdf0e10cSrcweir { 918*cdf0e10cSrcweir lclSetColorToOutDev( rDev, rBorder, pForceColor ); 919*cdf0e10cSrcweir lclDrawHorLine( rDev, rLPos, rResult.maBeg.maPrim, rRPos, rResult.maEnd.maPrim, 920*cdf0e10cSrcweir lclGetBeg( rBorder ), lclGetPrimEnd( rBorder ), rBorder.Dotted() ); 921*cdf0e10cSrcweir if( rBorder.Secn() ) 922*cdf0e10cSrcweir lclDrawHorLine( rDev, rLPos, rResult.maBeg.maSecn, rRPos, rResult.maEnd.maSecn, 923*cdf0e10cSrcweir lclGetSecnBeg( rBorder ), lclGetEnd( rBorder ), rBorder.Dotted() ); 924*cdf0e10cSrcweir rDev.Pop(); // colors 925*cdf0e10cSrcweir } 926*cdf0e10cSrcweir } 927*cdf0e10cSrcweir 928*cdf0e10cSrcweir // ---------------------------------------------------------------------------- 929*cdf0e10cSrcweir // Drawing of vertical frame borders. 930*cdf0e10cSrcweir 931*cdf0e10cSrcweir /** Draws a vertical thin or thick line into the passed output device. 932*cdf0e10cSrcweir 933*cdf0e10cSrcweir The Y coordinates of the edges of the line are adjusted according to the 934*cdf0e10cSrcweir passed LineEndResult structs. A one pixel wide line can be drawn dotted. 935*cdf0e10cSrcweir */ 936*cdf0e10cSrcweir void lclDrawVerLine( 937*cdf0e10cSrcweir OutputDevice& rDev, 938*cdf0e10cSrcweir const Point& rTPos, const LineEndResult& rTRes, 939*cdf0e10cSrcweir const Point& rBPos, const LineEndResult& rBRes, 940*cdf0e10cSrcweir long nLOffs, long nROffs, bool bDotted ) 941*cdf0e10cSrcweir { 942*cdf0e10cSrcweir LinePoints aLPoints( rTPos + lclToMapUnit( nLOffs, rTRes.mnOffs1 ), rBPos + lclToMapUnit( nLOffs, rBRes.mnOffs1 ) ); 943*cdf0e10cSrcweir if( nLOffs == nROffs ) 944*cdf0e10cSrcweir lclDrawThinLine( rDev, aLPoints, bDotted ); 945*cdf0e10cSrcweir else 946*cdf0e10cSrcweir { 947*cdf0e10cSrcweir LinePoints aRPoints( rTPos + lclToMapUnit( nROffs, rTRes.mnOffs2 ), rBPos + lclToMapUnit( nROffs, rBRes.mnOffs2 ) ); 948*cdf0e10cSrcweir lclDrawPolygon( rDev, aLPoints, aRPoints ); 949*cdf0e10cSrcweir } 950*cdf0e10cSrcweir } 951*cdf0e10cSrcweir 952*cdf0e10cSrcweir /** Draws a vertical frame border into the passed output device. 953*cdf0e10cSrcweir 954*cdf0e10cSrcweir @param rTPos 955*cdf0e10cSrcweir The top-left or top-right reference point of the diagonal frame border. 956*cdf0e10cSrcweir @param rBPos 957*cdf0e10cSrcweir The bottom-left or bottom-right reference point of the diagonal frame border. 958*cdf0e10cSrcweir @param rBorder 959*cdf0e10cSrcweir The frame style used to draw the border. 960*cdf0e10cSrcweir @param rResult 961*cdf0e10cSrcweir The Y coordinates of the edges of all lines of the frame border are 962*cdf0e10cSrcweir adjusted according to the offsets contained here. 963*cdf0e10cSrcweir */ 964*cdf0e10cSrcweir void lclDrawVerFrameBorder( 965*cdf0e10cSrcweir OutputDevice& rDev, const Point& rTPos, const Point& rBPos, 966*cdf0e10cSrcweir const Style& rBorder, const BorderResult& rResult, const Color* pForceColor ) 967*cdf0e10cSrcweir { 968*cdf0e10cSrcweir DBG_ASSERT( rBorder.Prim(), "svx::frame::lclDrawVerFrameBorder - line not visible" ); 969*cdf0e10cSrcweir DBG_ASSERT( rTPos.Y() <= rBPos.Y(), "svx::frame::lclDrawVerFrameBorder - wrong order of line ends" ); 970*cdf0e10cSrcweir DBG_ASSERT( rTPos.X() == rBPos.X(), "svx::frame::lclDrawVerFrameBorder - line not vertical" ); 971*cdf0e10cSrcweir if( rTPos.Y() <= rBPos.Y() ) 972*cdf0e10cSrcweir { 973*cdf0e10cSrcweir lclSetColorToOutDev( rDev, rBorder, pForceColor ); 974*cdf0e10cSrcweir lclDrawVerLine( rDev, rTPos, rResult.maBeg.maPrim, rBPos, rResult.maEnd.maPrim, 975*cdf0e10cSrcweir lclGetBeg( rBorder ), lclGetPrimEnd( rBorder ), rBorder.Dotted() ); 976*cdf0e10cSrcweir if( rBorder.Secn() ) 977*cdf0e10cSrcweir lclDrawVerLine( rDev, rTPos, rResult.maBeg.maSecn, rBPos, rResult.maEnd.maSecn, 978*cdf0e10cSrcweir lclGetSecnBeg( rBorder ), lclGetEnd( rBorder ), rBorder.Dotted() ); 979*cdf0e10cSrcweir rDev.Pop(); // colors 980*cdf0e10cSrcweir } 981*cdf0e10cSrcweir } 982*cdf0e10cSrcweir 983*cdf0e10cSrcweir // ============================================================================ 984*cdf0e10cSrcweir // Drawing of diagonal frame borders, incudes clipping functions. 985*cdf0e10cSrcweir 986*cdf0e10cSrcweir /** Returns the drawing coordinates for a diagonal thin line. 987*cdf0e10cSrcweir 988*cdf0e10cSrcweir This function can be used for top-left to bottom-right and for bottom-left 989*cdf0e10cSrcweir to top-right lines. 990*cdf0e10cSrcweir 991*cdf0e10cSrcweir @param rRect 992*cdf0e10cSrcweir The reference rectangle of the diagonal frame border. 993*cdf0e10cSrcweir @param bTLBR 994*cdf0e10cSrcweir true = top-left to bottom-right; false = bottom-left to top-right. 995*cdf0e10cSrcweir @param nDiagOffs 996*cdf0e10cSrcweir Width offset (sub units) across the diagonal frame border. 997*cdf0e10cSrcweir @return 998*cdf0e10cSrcweir A struct containg start and end position of the diagonal line. 999*cdf0e10cSrcweir */ 1000*cdf0e10cSrcweir LinePoints lclGetDiagLineEnds( const Rectangle& rRect, bool bTLBR, long nDiagOffs ) 1001*cdf0e10cSrcweir { 1002*cdf0e10cSrcweir LinePoints aPoints( rRect, bTLBR ); 1003*cdf0e10cSrcweir bool bVert = rRect.GetWidth() < rRect.GetHeight(); 1004*cdf0e10cSrcweir double fAngle = bVert ? GetVerDiagAngle( rRect ) : GetHorDiagAngle( rRect ); 1005*cdf0e10cSrcweir // vertical top-left to bottom-right borders are handled mirrored 1006*cdf0e10cSrcweir if( bVert && bTLBR ) 1007*cdf0e10cSrcweir nDiagOffs = -nDiagOffs; 1008*cdf0e10cSrcweir long nTOffs = bTLBR ? GetTLDiagOffset( 0, nDiagOffs, fAngle ) : GetTRDiagOffset( 0, nDiagOffs, fAngle ); 1009*cdf0e10cSrcweir long nBOffs = bTLBR ? GetBRDiagOffset( 0, nDiagOffs, fAngle ) : GetBLDiagOffset( 0, nDiagOffs, fAngle ); 1010*cdf0e10cSrcweir // vertical bottom-left to top-right borders are handled with exchanged end points 1011*cdf0e10cSrcweir if( bVert && !bTLBR ) 1012*cdf0e10cSrcweir std::swap( nTOffs, nBOffs ); 1013*cdf0e10cSrcweir (bVert ? aPoints.maBeg.Y() : aPoints.maBeg.X()) += lclToMapUnit( nTOffs ); 1014*cdf0e10cSrcweir (bVert ? aPoints.maEnd.Y() : aPoints.maEnd.X()) += lclToMapUnit( nBOffs ); 1015*cdf0e10cSrcweir return aPoints; 1016*cdf0e10cSrcweir } 1017*cdf0e10cSrcweir 1018*cdf0e10cSrcweir // ---------------------------------------------------------------------------- 1019*cdf0e10cSrcweir // Clipping functions for diagonal frame borders. 1020*cdf0e10cSrcweir 1021*cdf0e10cSrcweir /** Limits the clipping region to the inner area of a rectange. 1022*cdf0e10cSrcweir 1023*cdf0e10cSrcweir Takes the values from the passed DiagLineResult struct into account. They 1024*cdf0e10cSrcweir may specify to not clip one or more borders of a rectangle. 1025*cdf0e10cSrcweir 1026*cdf0e10cSrcweir @param rDev 1027*cdf0e10cSrcweir The output device with the clipping region to be modified. The old 1028*cdf0e10cSrcweir clipping region is pushed onto the device's stack and can be restored 1029*cdf0e10cSrcweir with a call to OutputDevice::Pop(). Please take care about the correct 1030*cdf0e10cSrcweir calling order of Pop() if this function is used with other functions 1031*cdf0e10cSrcweir pushing something onto the stack. 1032*cdf0e10cSrcweir @param rRect 1033*cdf0e10cSrcweir The reference rectangle of the diagonal frame borders. 1034*cdf0e10cSrcweir @param rResult 1035*cdf0e10cSrcweir The result struct containing modifies for each border of the reference 1036*cdf0e10cSrcweir rectangle. 1037*cdf0e10cSrcweir */ 1038*cdf0e10cSrcweir void lclPushDiagClipRect( OutputDevice& rDev, const Rectangle& rRect, const DiagLineResult& rResult ) 1039*cdf0e10cSrcweir { 1040*cdf0e10cSrcweir // PixelToLogic() regards internal offset of the output device 1041*cdf0e10cSrcweir Rectangle aClipRect( rRect ); 1042*cdf0e10cSrcweir aClipRect.Left() += lclToMapUnit( rResult.mnLClip ); 1043*cdf0e10cSrcweir aClipRect.Top() += lclToMapUnit( rResult.mnTClip ); 1044*cdf0e10cSrcweir aClipRect.Right() += lclToMapUnit( rResult.mnRClip ); 1045*cdf0e10cSrcweir aClipRect.Bottom() += lclToMapUnit( rResult.mnBClip ); 1046*cdf0e10cSrcweir // output device would adjust the rectangle -> invalidate it before 1047*cdf0e10cSrcweir if( (aClipRect.GetWidth() < 1) ||(aClipRect.GetHeight() < 1) ) 1048*cdf0e10cSrcweir aClipRect.SetEmpty(); 1049*cdf0e10cSrcweir 1050*cdf0e10cSrcweir rDev.Push( PUSH_CLIPREGION ); 1051*cdf0e10cSrcweir rDev.IntersectClipRegion( aClipRect ); 1052*cdf0e10cSrcweir } 1053*cdf0e10cSrcweir 1054*cdf0e10cSrcweir /** Excludes inner area of a crossing double frame border from clipping region. 1055*cdf0e10cSrcweir 1056*cdf0e10cSrcweir This function is used to modify the clipping region so that it excludes the 1057*cdf0e10cSrcweir inner free area of a double diagonal frame border. This makes it possible 1058*cdf0e10cSrcweir to draw a diagonal frame border in one step without taking care of the 1059*cdf0e10cSrcweir crossing double frame border. 1060*cdf0e10cSrcweir 1061*cdf0e10cSrcweir @param rDev 1062*cdf0e10cSrcweir The output device with the clipping region to be modified. The old 1063*cdf0e10cSrcweir clipping region is pushed onto the device's stack and can be restored 1064*cdf0e10cSrcweir with a call to OutputDevice::Pop(). Please take care about the correct 1065*cdf0e10cSrcweir calling order of Pop() if this function is used with other functions 1066*cdf0e10cSrcweir pushing something onto the stack. 1067*cdf0e10cSrcweir @param rRect 1068*cdf0e10cSrcweir The reference rectangle of the diagonal frame borders. 1069*cdf0e10cSrcweir @param bTLBR 1070*cdf0e10cSrcweir The orientation of the processed frame border (not the orientation of 1071*cdf0e10cSrcweir the crossing frame border). 1072*cdf0e10cSrcweir @param bCrossStyle 1073*cdf0e10cSrcweir The style of the crossing frame border. Must be a double frame style. 1074*cdf0e10cSrcweir */ 1075*cdf0e10cSrcweir void lclPushCrossingClipRegion( OutputDevice& rDev, const Rectangle& rRect, bool bTLBR, const Style& rCrossStyle ) 1076*cdf0e10cSrcweir { 1077*cdf0e10cSrcweir DBG_ASSERT( rCrossStyle.Secn(), "lclGetCrossingClipRegion - use only for double styles" ); 1078*cdf0e10cSrcweir LinePoints aLPoints( lclGetDiagLineEnds( rRect, !bTLBR, lclGetPrimEnd( rCrossStyle ) ) ); 1079*cdf0e10cSrcweir LinePoints aRPoints( lclGetDiagLineEnds( rRect, !bTLBR, lclGetSecnBeg( rCrossStyle ) ) ); 1080*cdf0e10cSrcweir 1081*cdf0e10cSrcweir Region aClipReg; 1082*cdf0e10cSrcweir if( bTLBR ) 1083*cdf0e10cSrcweir { 1084*cdf0e10cSrcweir aClipReg = lclCreatePolygon( 1085*cdf0e10cSrcweir aLPoints.maBeg, aLPoints.maEnd, rRect.BottomRight(), rRect.BottomLeft(), rRect.TopLeft() ); 1086*cdf0e10cSrcweir aClipReg.Union( lclCreatePolygon( 1087*cdf0e10cSrcweir aRPoints.maBeg, aRPoints.maEnd, rRect.BottomRight(), rRect.TopRight(), rRect.TopLeft() ) ); 1088*cdf0e10cSrcweir } 1089*cdf0e10cSrcweir else 1090*cdf0e10cSrcweir { 1091*cdf0e10cSrcweir aClipReg = lclCreatePolygon( 1092*cdf0e10cSrcweir aLPoints.maBeg, aLPoints.maEnd, rRect.BottomLeft(), rRect.TopLeft(), rRect.TopRight() ); 1093*cdf0e10cSrcweir aClipReg.Union( lclCreatePolygon( 1094*cdf0e10cSrcweir aRPoints.maBeg, aRPoints.maEnd, rRect.BottomLeft(), rRect.BottomRight(), rRect.TopRight() ) ); 1095*cdf0e10cSrcweir } 1096*cdf0e10cSrcweir 1097*cdf0e10cSrcweir rDev.Push( PUSH_CLIPREGION ); 1098*cdf0e10cSrcweir rDev.IntersectClipRegion( aClipReg ); 1099*cdf0e10cSrcweir } 1100*cdf0e10cSrcweir 1101*cdf0e10cSrcweir // ---------------------------------------------------------------------------- 1102*cdf0e10cSrcweir // Drawing functions for diagonal frame borders. 1103*cdf0e10cSrcweir 1104*cdf0e10cSrcweir /** Draws a diagonal thin or thick line into the passed output device. 1105*cdf0e10cSrcweir 1106*cdf0e10cSrcweir The clipping region of the output device is modified according to the 1107*cdf0e10cSrcweir passed DiagLineResult struct. A one pixel wide line can be drawn dotted. 1108*cdf0e10cSrcweir */ 1109*cdf0e10cSrcweir void lclDrawDiagLine( 1110*cdf0e10cSrcweir OutputDevice& rDev, const Rectangle& rRect, bool bTLBR, 1111*cdf0e10cSrcweir const DiagLineResult& rResult, long nDiagOffs1, long nDiagOffs2, bool bDotted ) 1112*cdf0e10cSrcweir { 1113*cdf0e10cSrcweir lclPushDiagClipRect( rDev, rRect, rResult ); 1114*cdf0e10cSrcweir LinePoints aLPoints( lclGetDiagLineEnds( rRect, bTLBR, nDiagOffs1 ) ); 1115*cdf0e10cSrcweir if( nDiagOffs1 == nDiagOffs2 ) 1116*cdf0e10cSrcweir lclDrawThinLine( rDev, aLPoints, bDotted ); 1117*cdf0e10cSrcweir else 1118*cdf0e10cSrcweir lclDrawPolygon( rDev, aLPoints, lclGetDiagLineEnds( rRect, bTLBR, nDiagOffs2 ) ); 1119*cdf0e10cSrcweir rDev.Pop(); // clipping region 1120*cdf0e10cSrcweir } 1121*cdf0e10cSrcweir 1122*cdf0e10cSrcweir /** Draws a diagonal frame border into the passed output device. 1123*cdf0e10cSrcweir 1124*cdf0e10cSrcweir The lines of the frame border are drawn interrupted, if the style of the 1125*cdf0e10cSrcweir crossing frame border is double. 1126*cdf0e10cSrcweir 1127*cdf0e10cSrcweir @param rRect 1128*cdf0e10cSrcweir The reference rectangle of the diagonal frame border. 1129*cdf0e10cSrcweir @param bTLBR 1130*cdf0e10cSrcweir The orientation of the diagonal frame border. 1131*cdf0e10cSrcweir @param rBorder 1132*cdf0e10cSrcweir The frame style used to draw the border. 1133*cdf0e10cSrcweir @param rResult 1134*cdf0e10cSrcweir Offsets (sub units) to modify the clipping region of the output device. 1135*cdf0e10cSrcweir @param rCrossStyle 1136*cdf0e10cSrcweir Style of the crossing diagonal frame border. 1137*cdf0e10cSrcweir */ 1138*cdf0e10cSrcweir void lclDrawDiagFrameBorder( 1139*cdf0e10cSrcweir OutputDevice& rDev, const Rectangle& rRect, bool bTLBR, 1140*cdf0e10cSrcweir const Style& rBorder, const DiagBorderResult& rResult, const Style& rCrossStyle, 1141*cdf0e10cSrcweir const Color* pForceColor, bool bDiagDblClip ) 1142*cdf0e10cSrcweir { 1143*cdf0e10cSrcweir DBG_ASSERT( rBorder.Prim(), "svx::frame::lclDrawDiagFrameBorder - line not visible" ); 1144*cdf0e10cSrcweir 1145*cdf0e10cSrcweir bool bClip = bDiagDblClip && rCrossStyle.Secn(); 1146*cdf0e10cSrcweir if( bClip ) 1147*cdf0e10cSrcweir lclPushCrossingClipRegion( rDev, rRect, bTLBR, rCrossStyle ); 1148*cdf0e10cSrcweir 1149*cdf0e10cSrcweir lclSetColorToOutDev( rDev, rBorder, pForceColor ); 1150*cdf0e10cSrcweir lclDrawDiagLine( rDev, rRect, bTLBR, rResult.maPrim, lclGetBeg( rBorder ), lclGetPrimEnd( rBorder ), rBorder.Dotted() ); 1151*cdf0e10cSrcweir if( rBorder.Secn() ) 1152*cdf0e10cSrcweir lclDrawDiagLine( rDev, rRect, bTLBR, rResult.maSecn, lclGetSecnBeg( rBorder ), lclGetEnd( rBorder ), rBorder.Dotted() ); 1153*cdf0e10cSrcweir rDev.Pop(); // colors 1154*cdf0e10cSrcweir 1155*cdf0e10cSrcweir if( bClip ) 1156*cdf0e10cSrcweir rDev.Pop(); // clipping region 1157*cdf0e10cSrcweir } 1158*cdf0e10cSrcweir 1159*cdf0e10cSrcweir /** Draws both diagonal frame borders into the passed output device. 1160*cdf0e10cSrcweir 1161*cdf0e10cSrcweir The lines of each frame border is drawn interrupted, if the style of the 1162*cdf0e10cSrcweir other crossing frame border is double. 1163*cdf0e10cSrcweir 1164*cdf0e10cSrcweir @param rRect 1165*cdf0e10cSrcweir The reference rectangle of the diagonal frame borders. 1166*cdf0e10cSrcweir @param rTLBR 1167*cdf0e10cSrcweir The frame style of the top-left to bottom-right frame border. 1168*cdf0e10cSrcweir @param rBLTR 1169*cdf0e10cSrcweir The frame style of the bottom-left to top-right frame border. 1170*cdf0e10cSrcweir @param rResult 1171*cdf0e10cSrcweir Offsets (sub units) to modify the clipping region of the output device. 1172*cdf0e10cSrcweir */ 1173*cdf0e10cSrcweir void lclDrawDiagFrameBorders( 1174*cdf0e10cSrcweir OutputDevice& rDev, const Rectangle& rRect, 1175*cdf0e10cSrcweir const Style& rTLBR, const Style& rBLTR, const DiagBordersResult& rResult, 1176*cdf0e10cSrcweir const Color* pForceColor, bool bDiagDblClip ) 1177*cdf0e10cSrcweir { 1178*cdf0e10cSrcweir DBG_ASSERT( (rRect.GetWidth() > 1) && (rRect.GetHeight() > 1), "svx::frame::lclDrawDiagFrameBorders - rectangle too small" ); 1179*cdf0e10cSrcweir if( (rRect.GetWidth() > 1) && (rRect.GetHeight() > 1) ) 1180*cdf0e10cSrcweir { 1181*cdf0e10cSrcweir bool bDrawTLBR = rTLBR.Prim() != 0; 1182*cdf0e10cSrcweir bool bDrawBLTR = rBLTR.Prim() != 0; 1183*cdf0e10cSrcweir bool bFirstDrawBLTR = rTLBR.Secn() != 0; 1184*cdf0e10cSrcweir 1185*cdf0e10cSrcweir if( bDrawBLTR && bFirstDrawBLTR ) 1186*cdf0e10cSrcweir lclDrawDiagFrameBorder( rDev, rRect, false, rBLTR, rResult.maBLTR, rTLBR, pForceColor, bDiagDblClip ); 1187*cdf0e10cSrcweir if( bDrawTLBR ) 1188*cdf0e10cSrcweir lclDrawDiagFrameBorder( rDev, rRect, true, rTLBR, rResult.maTLBR, rBLTR, pForceColor, bDiagDblClip ); 1189*cdf0e10cSrcweir if( bDrawBLTR && !bFirstDrawBLTR ) 1190*cdf0e10cSrcweir lclDrawDiagFrameBorder( rDev, rRect, false, rBLTR, rResult.maBLTR, rTLBR, pForceColor, bDiagDblClip ); 1191*cdf0e10cSrcweir } 1192*cdf0e10cSrcweir } 1193*cdf0e10cSrcweir 1194*cdf0e10cSrcweir // ============================================================================ 1195*cdf0e10cSrcweir 1196*cdf0e10cSrcweir } // namespace 1197*cdf0e10cSrcweir 1198*cdf0e10cSrcweir // ============================================================================ 1199*cdf0e10cSrcweir // Classes 1200*cdf0e10cSrcweir // ============================================================================ 1201*cdf0e10cSrcweir 1202*cdf0e10cSrcweir #define SCALEVALUE( value ) lclScaleValue( value, fScale, nMaxWidth ) 1203*cdf0e10cSrcweir 1204*cdf0e10cSrcweir void Style::Clear() 1205*cdf0e10cSrcweir { 1206*cdf0e10cSrcweir Set( Color(), 0, 0, 0 ); 1207*cdf0e10cSrcweir } 1208*cdf0e10cSrcweir 1209*cdf0e10cSrcweir void Style::Set( sal_uInt16 nP, sal_uInt16 nD, sal_uInt16 nS ) 1210*cdf0e10cSrcweir { 1211*cdf0e10cSrcweir /* nP nD nS -> mnPrim mnDist mnSecn 1212*cdf0e10cSrcweir -------------------------------------- 1213*cdf0e10cSrcweir any any 0 nP 0 0 1214*cdf0e10cSrcweir 0 any >0 nS 0 0 1215*cdf0e10cSrcweir >0 0 >0 nP 0 0 1216*cdf0e10cSrcweir >0 >0 >0 nP nD nS 1217*cdf0e10cSrcweir */ 1218*cdf0e10cSrcweir mnPrim = nP ? nP : nS; 1219*cdf0e10cSrcweir mnDist = (nP && nS) ? nD : 0; 1220*cdf0e10cSrcweir mnSecn = (nP && nD) ? nS : 0; 1221*cdf0e10cSrcweir } 1222*cdf0e10cSrcweir 1223*cdf0e10cSrcweir void Style::Set( const Color& rColor, sal_uInt16 nP, sal_uInt16 nD, sal_uInt16 nS ) 1224*cdf0e10cSrcweir { 1225*cdf0e10cSrcweir maColor = rColor; 1226*cdf0e10cSrcweir Set( nP, nD, nS ); 1227*cdf0e10cSrcweir } 1228*cdf0e10cSrcweir 1229*cdf0e10cSrcweir void Style::Set( const SvxBorderLine& rBorder, double fScale, sal_uInt16 nMaxWidth, bool bUseDots ) 1230*cdf0e10cSrcweir { 1231*cdf0e10cSrcweir maColor = rBorder.GetColor(); 1232*cdf0e10cSrcweir 1233*cdf0e10cSrcweir sal_uInt16 nPrim = rBorder.GetOutWidth(); 1234*cdf0e10cSrcweir sal_uInt16 nDist = rBorder.GetDistance(); 1235*cdf0e10cSrcweir sal_uInt16 nSecn = rBorder.GetInWidth(); 1236*cdf0e10cSrcweir 1237*cdf0e10cSrcweir if( !nSecn ) // no or single frame border 1238*cdf0e10cSrcweir { 1239*cdf0e10cSrcweir Set( SCALEVALUE( nPrim ), 0, 0 ); 1240*cdf0e10cSrcweir mbDotted = bUseDots && (0 < nPrim) && (nPrim < 10); 1241*cdf0e10cSrcweir } 1242*cdf0e10cSrcweir else 1243*cdf0e10cSrcweir { 1244*cdf0e10cSrcweir Set( SCALEVALUE( nPrim ), SCALEVALUE( nDist ), SCALEVALUE( nSecn ) ); 1245*cdf0e10cSrcweir mbDotted = false; 1246*cdf0e10cSrcweir // Enlarge the style if distance is too small due to rounding losses. 1247*cdf0e10cSrcweir sal_uInt16 nPixWidth = SCALEVALUE( nPrim + nDist + nSecn ); 1248*cdf0e10cSrcweir if( nPixWidth > GetWidth() ) 1249*cdf0e10cSrcweir mnDist = nPixWidth - mnPrim - mnSecn; 1250*cdf0e10cSrcweir // Shrink the style if it is too thick for the control. 1251*cdf0e10cSrcweir while( GetWidth() > nMaxWidth ) 1252*cdf0e10cSrcweir { 1253*cdf0e10cSrcweir // First decrease space between lines. 1254*cdf0e10cSrcweir if( mnDist ) 1255*cdf0e10cSrcweir --mnDist; 1256*cdf0e10cSrcweir // Still too thick? Decrease the line widths. 1257*cdf0e10cSrcweir if( GetWidth() > nMaxWidth ) 1258*cdf0e10cSrcweir { 1259*cdf0e10cSrcweir if( mnPrim && (mnPrim == mnSecn) ) 1260*cdf0e10cSrcweir { 1261*cdf0e10cSrcweir // Both lines equal - decrease both to keep symmetry. 1262*cdf0e10cSrcweir --mnPrim; 1263*cdf0e10cSrcweir --mnSecn; 1264*cdf0e10cSrcweir } 1265*cdf0e10cSrcweir else 1266*cdf0e10cSrcweir { 1267*cdf0e10cSrcweir // Decrease each line for itself 1268*cdf0e10cSrcweir if( mnPrim ) 1269*cdf0e10cSrcweir --mnPrim; 1270*cdf0e10cSrcweir if( (GetWidth() > nMaxWidth) && mnSecn ) 1271*cdf0e10cSrcweir --mnSecn; 1272*cdf0e10cSrcweir } 1273*cdf0e10cSrcweir } 1274*cdf0e10cSrcweir } 1275*cdf0e10cSrcweir } 1276*cdf0e10cSrcweir } 1277*cdf0e10cSrcweir 1278*cdf0e10cSrcweir void Style::Set( const SvxBorderLine* pBorder, double fScale, sal_uInt16 nMaxWidth, bool bUseDots ) 1279*cdf0e10cSrcweir { 1280*cdf0e10cSrcweir if( pBorder ) 1281*cdf0e10cSrcweir Set( *pBorder, fScale, nMaxWidth, bUseDots ); 1282*cdf0e10cSrcweir else 1283*cdf0e10cSrcweir { 1284*cdf0e10cSrcweir Clear(); 1285*cdf0e10cSrcweir mbDotted = false; 1286*cdf0e10cSrcweir } 1287*cdf0e10cSrcweir } 1288*cdf0e10cSrcweir 1289*cdf0e10cSrcweir Style& Style::ScaleSelf( double fScale, sal_uInt16 nMaxWidth ) 1290*cdf0e10cSrcweir { 1291*cdf0e10cSrcweir Set( SCALEVALUE( mnPrim ), SCALEVALUE( mnDist ), SCALEVALUE( mnSecn ) ); 1292*cdf0e10cSrcweir return *this; 1293*cdf0e10cSrcweir } 1294*cdf0e10cSrcweir 1295*cdf0e10cSrcweir Style Style::Scale( double fScale, sal_uInt16 nMaxWidth ) const 1296*cdf0e10cSrcweir { 1297*cdf0e10cSrcweir return Style( *this ).ScaleSelf( fScale, nMaxWidth ); 1298*cdf0e10cSrcweir } 1299*cdf0e10cSrcweir 1300*cdf0e10cSrcweir Style& Style::MirrorSelf() 1301*cdf0e10cSrcweir { 1302*cdf0e10cSrcweir if( mnSecn ) 1303*cdf0e10cSrcweir std::swap( mnPrim, mnSecn ); 1304*cdf0e10cSrcweir if( meRefMode != REFMODE_CENTERED ) 1305*cdf0e10cSrcweir meRefMode = (meRefMode == REFMODE_BEGIN) ? REFMODE_END : REFMODE_BEGIN; 1306*cdf0e10cSrcweir return *this; 1307*cdf0e10cSrcweir } 1308*cdf0e10cSrcweir 1309*cdf0e10cSrcweir Style Style::Mirror() const 1310*cdf0e10cSrcweir { 1311*cdf0e10cSrcweir return Style( *this ).MirrorSelf(); 1312*cdf0e10cSrcweir } 1313*cdf0e10cSrcweir 1314*cdf0e10cSrcweir bool operator==( const Style& rL, const Style& rR ) 1315*cdf0e10cSrcweir { 1316*cdf0e10cSrcweir return (rL.Prim() == rR.Prim()) && (rL.Dist() == rR.Dist()) && (rL.Secn() == rR.Secn()) && 1317*cdf0e10cSrcweir (rL.GetColor() == rR.GetColor()) && (rL.GetRefMode() == rR.GetRefMode()) && (rL.Dotted() == rR.Dotted()); 1318*cdf0e10cSrcweir } 1319*cdf0e10cSrcweir 1320*cdf0e10cSrcweir bool operator<( const Style& rL, const Style& rR ) 1321*cdf0e10cSrcweir { 1322*cdf0e10cSrcweir // different total widths -> rL<rR, if rL is thinner 1323*cdf0e10cSrcweir sal_uInt16 nLW = rL.GetWidth(); 1324*cdf0e10cSrcweir sal_uInt16 nRW = rR.GetWidth(); 1325*cdf0e10cSrcweir if( nLW != nRW ) return nLW < nRW; 1326*cdf0e10cSrcweir 1327*cdf0e10cSrcweir // one line double, the other single -> rL<rR, if rL is single 1328*cdf0e10cSrcweir if( (rL.Secn() == 0) != (rR.Secn() == 0) ) return rL.Secn() == 0; 1329*cdf0e10cSrcweir 1330*cdf0e10cSrcweir // both lines double with different distances -> rL<rR, if distance of rL greater 1331*cdf0e10cSrcweir if( (rL.Secn() && rR.Secn()) && (rL.Dist() != rR.Dist()) ) return rL.Dist() > rR.Dist(); 1332*cdf0e10cSrcweir 1333*cdf0e10cSrcweir // both lines single and 1 unit thick, only one is dotted -> rL<rR, if rL is dotted 1334*cdf0e10cSrcweir if( (nLW == 1) && (rL.Dotted() != rR.Dotted()) ) return rL.Dotted(); 1335*cdf0e10cSrcweir 1336*cdf0e10cSrcweir // seem to be equal 1337*cdf0e10cSrcweir return false; 1338*cdf0e10cSrcweir } 1339*cdf0e10cSrcweir 1340*cdf0e10cSrcweir #undef SCALEVALUE 1341*cdf0e10cSrcweir 1342*cdf0e10cSrcweir // ============================================================================ 1343*cdf0e10cSrcweir // Various helper functions 1344*cdf0e10cSrcweir // ============================================================================ 1345*cdf0e10cSrcweir 1346*cdf0e10cSrcweir double GetHorDiagAngle( long nWidth, long nHeight ) 1347*cdf0e10cSrcweir { 1348*cdf0e10cSrcweir return atan2( static_cast< double >( Abs( nHeight ) ), static_cast< double >( Abs( nWidth ) ) ); 1349*cdf0e10cSrcweir } 1350*cdf0e10cSrcweir 1351*cdf0e10cSrcweir // ============================================================================ 1352*cdf0e10cSrcweir 1353*cdf0e10cSrcweir long GetTLDiagOffset( long nVerOffs, long nDiagOffs, double fAngle ) 1354*cdf0e10cSrcweir { 1355*cdf0e10cSrcweir return lclD2L( nVerOffs / tan( fAngle ) + nDiagOffs / sin( fAngle ) ); 1356*cdf0e10cSrcweir } 1357*cdf0e10cSrcweir 1358*cdf0e10cSrcweir long GetBLDiagOffset( long nVerOffs, long nDiagOffs, double fAngle ) 1359*cdf0e10cSrcweir { 1360*cdf0e10cSrcweir return lclD2L( -nVerOffs / tan( fAngle ) + nDiagOffs / sin( fAngle ) ); 1361*cdf0e10cSrcweir } 1362*cdf0e10cSrcweir 1363*cdf0e10cSrcweir long GetBRDiagOffset( long nVerOffs, long nDiagOffs, double fAngle ) 1364*cdf0e10cSrcweir { 1365*cdf0e10cSrcweir return -lclD2L( -nVerOffs / tan( fAngle ) - nDiagOffs / sin( fAngle ) ); 1366*cdf0e10cSrcweir } 1367*cdf0e10cSrcweir 1368*cdf0e10cSrcweir long GetTRDiagOffset( long nVerOffs, long nDiagOffs, double fAngle ) 1369*cdf0e10cSrcweir { 1370*cdf0e10cSrcweir return -lclD2L( nVerOffs / tan( fAngle ) - nDiagOffs / sin( fAngle ) ); 1371*cdf0e10cSrcweir } 1372*cdf0e10cSrcweir 1373*cdf0e10cSrcweir // ============================================================================ 1374*cdf0e10cSrcweir 1375*cdf0e10cSrcweir bool CheckFrameBorderConnectable( const Style& rLBorder, const Style& rRBorder, 1376*cdf0e10cSrcweir const Style& rTFromTL, const Style& rTFromT, const Style& rTFromTR, 1377*cdf0e10cSrcweir const Style& rBFromBL, const Style& rBFromB, const Style& rBFromBR ) 1378*cdf0e10cSrcweir { 1379*cdf0e10cSrcweir return // returns 1 AND (2a OR 2b) 1380*cdf0e10cSrcweir // 1) only, if both frame borders are equal 1381*cdf0e10cSrcweir (rLBorder == rRBorder) 1382*cdf0e10cSrcweir && 1383*cdf0e10cSrcweir ( 1384*cdf0e10cSrcweir ( 1385*cdf0e10cSrcweir // 2a) if the borders are not double, at least one of the vertical must not be double 1386*cdf0e10cSrcweir !rLBorder.Secn() && (!rTFromT.Secn() || !rBFromB.Secn()) 1387*cdf0e10cSrcweir ) 1388*cdf0e10cSrcweir || 1389*cdf0e10cSrcweir ( 1390*cdf0e10cSrcweir // 2b) if the borders are double, all other borders must not be double 1391*cdf0e10cSrcweir rLBorder.Secn() && 1392*cdf0e10cSrcweir !rTFromTL.Secn() && !rTFromT.Secn() && !rTFromTR.Secn() && 1393*cdf0e10cSrcweir !rBFromBL.Secn() && !rBFromB.Secn() && !rBFromBR.Secn() 1394*cdf0e10cSrcweir ) 1395*cdf0e10cSrcweir ); 1396*cdf0e10cSrcweir } 1397*cdf0e10cSrcweir 1398*cdf0e10cSrcweir // ============================================================================ 1399*cdf0e10cSrcweir // Drawing functions 1400*cdf0e10cSrcweir // ============================================================================ 1401*cdf0e10cSrcweir 1402*cdf0e10cSrcweir void DrawHorFrameBorder( OutputDevice& rDev, 1403*cdf0e10cSrcweir const Point& rLPos, const Point& rRPos, const Style& rBorder, 1404*cdf0e10cSrcweir const DiagStyle& rLFromTR, const Style& rLFromT, const Style& rLFromL, const Style& rLFromB, const DiagStyle& rLFromBR, 1405*cdf0e10cSrcweir const DiagStyle& rRFromTL, const Style& rRFromT, const Style& rRFromR, const Style& rRFromB, const DiagStyle& rRFromBL, 1406*cdf0e10cSrcweir const Color* pForceColor ) 1407*cdf0e10cSrcweir { 1408*cdf0e10cSrcweir if( rBorder.Prim() ) 1409*cdf0e10cSrcweir { 1410*cdf0e10cSrcweir BorderResult aResult; 1411*cdf0e10cSrcweir lclLinkHorFrameBorder( aResult, rBorder, 1412*cdf0e10cSrcweir rLFromTR, rLFromT, rLFromL, rLFromB, rLFromBR, 1413*cdf0e10cSrcweir rRFromTL, rRFromT, rRFromR, rRFromB, rRFromBL ); 1414*cdf0e10cSrcweir lclDrawHorFrameBorder( rDev, rLPos, rRPos, rBorder, aResult, pForceColor ); 1415*cdf0e10cSrcweir } 1416*cdf0e10cSrcweir } 1417*cdf0e10cSrcweir 1418*cdf0e10cSrcweir void DrawHorFrameBorder( OutputDevice& rDev, 1419*cdf0e10cSrcweir const Point& rLPos, const Point& rRPos, const Style& rBorder, 1420*cdf0e10cSrcweir const Style& rLFromT, const Style& rLFromL, const Style& rLFromB, 1421*cdf0e10cSrcweir const Style& rRFromT, const Style& rRFromR, const Style& rRFromB, 1422*cdf0e10cSrcweir const Color* pForceColor ) 1423*cdf0e10cSrcweir { 1424*cdf0e10cSrcweir /* Recycle complex version of the DrawHorFrameBorder() function with empty diagonals. */ 1425*cdf0e10cSrcweir const DiagStyle aNoStyle; 1426*cdf0e10cSrcweir DrawHorFrameBorder( 1427*cdf0e10cSrcweir rDev, rLPos, rRPos, rBorder, 1428*cdf0e10cSrcweir aNoStyle, rLFromT, rLFromL, rLFromB, aNoStyle, 1429*cdf0e10cSrcweir aNoStyle, rRFromT, rRFromR, rRFromB, aNoStyle, 1430*cdf0e10cSrcweir pForceColor ); 1431*cdf0e10cSrcweir } 1432*cdf0e10cSrcweir 1433*cdf0e10cSrcweir void DrawHorFrameBorder( OutputDevice& rDev, 1434*cdf0e10cSrcweir const Point& rLPos, const Point& rRPos, const Style& rBorder, const Color* pForceColor ) 1435*cdf0e10cSrcweir { 1436*cdf0e10cSrcweir if( rBorder.Prim() ) 1437*cdf0e10cSrcweir lclDrawHorFrameBorder( rDev, rLPos, rRPos, rBorder, BorderResult(), pForceColor ); 1438*cdf0e10cSrcweir } 1439*cdf0e10cSrcweir 1440*cdf0e10cSrcweir // ---------------------------------------------------------------------------- 1441*cdf0e10cSrcweir 1442*cdf0e10cSrcweir void DrawVerFrameBorder( OutputDevice& rDev, 1443*cdf0e10cSrcweir const Point& rTPos, const Point& rBPos, const Style& rBorder, 1444*cdf0e10cSrcweir const DiagStyle& rTFromBL, const Style& rTFromL, const Style& rTFromT, const Style& rTFromR, const DiagStyle& rTFromBR, 1445*cdf0e10cSrcweir const DiagStyle& rBFromTL, const Style& rBFromL, const Style& rBFromB, const Style& rBFromR, const DiagStyle& rBFromTR, 1446*cdf0e10cSrcweir const Color* pForceColor ) 1447*cdf0e10cSrcweir { 1448*cdf0e10cSrcweir if( rBorder.Prim() ) 1449*cdf0e10cSrcweir { 1450*cdf0e10cSrcweir BorderResult aResult; 1451*cdf0e10cSrcweir lclLinkVerFrameBorder( aResult, rBorder, 1452*cdf0e10cSrcweir rTFromBL, rTFromL, rTFromT, rTFromR, rTFromBR, 1453*cdf0e10cSrcweir rBFromTL, rBFromL, rBFromB, rBFromR, rBFromTR ); 1454*cdf0e10cSrcweir lclDrawVerFrameBorder( rDev, rTPos, rBPos, rBorder, aResult, pForceColor ); 1455*cdf0e10cSrcweir } 1456*cdf0e10cSrcweir } 1457*cdf0e10cSrcweir 1458*cdf0e10cSrcweir void DrawVerFrameBorder( OutputDevice& rDev, 1459*cdf0e10cSrcweir const Point& rTPos, const Point& rBPos, const Style& rBorder, 1460*cdf0e10cSrcweir const Style& rTFromL, const Style& rTFromT, const Style& rTFromR, 1461*cdf0e10cSrcweir const Style& rBFromL, const Style& rBFromB, const Style& rBFromR, 1462*cdf0e10cSrcweir const Color* pForceColor ) 1463*cdf0e10cSrcweir { 1464*cdf0e10cSrcweir /* Recycle complex version of the DrawVerFrameBorder() function with empty diagonals. */ 1465*cdf0e10cSrcweir const DiagStyle aNoStyle; 1466*cdf0e10cSrcweir DrawVerFrameBorder( 1467*cdf0e10cSrcweir rDev, rTPos, rBPos, rBorder, 1468*cdf0e10cSrcweir aNoStyle, rTFromL, rTFromT, rTFromR, aNoStyle, 1469*cdf0e10cSrcweir aNoStyle, rBFromL, rBFromB, rBFromR, aNoStyle, 1470*cdf0e10cSrcweir pForceColor ); 1471*cdf0e10cSrcweir } 1472*cdf0e10cSrcweir 1473*cdf0e10cSrcweir void DrawVerFrameBorder( OutputDevice& rDev, 1474*cdf0e10cSrcweir const Point& rTPos, const Point& rBPos, const Style& rBorder, const Color* pForceColor ) 1475*cdf0e10cSrcweir { 1476*cdf0e10cSrcweir if( rBorder.Prim() ) 1477*cdf0e10cSrcweir lclDrawVerFrameBorder( rDev, rTPos, rBPos, rBorder, BorderResult(), pForceColor ); 1478*cdf0e10cSrcweir } 1479*cdf0e10cSrcweir 1480*cdf0e10cSrcweir // ---------------------------------------------------------------------------- 1481*cdf0e10cSrcweir 1482*cdf0e10cSrcweir void DrawVerFrameBorderSlanted( OutputDevice& rDev, 1483*cdf0e10cSrcweir const Point& rTPos, const Point& rBPos, const Style& rBorder, const Color* pForceColor ) 1484*cdf0e10cSrcweir { 1485*cdf0e10cSrcweir DBG_ASSERT( rTPos.Y() < rBPos.Y(), "svx::frame::DrawVerFrameBorderSlanted - wrong order of line ends" ); 1486*cdf0e10cSrcweir if( rBorder.Prim() && (rTPos.Y() < rBPos.Y()) ) 1487*cdf0e10cSrcweir { 1488*cdf0e10cSrcweir if( rTPos.X() == rBPos.X() ) 1489*cdf0e10cSrcweir { 1490*cdf0e10cSrcweir DrawVerFrameBorder( rDev, rTPos, rBPos, rBorder, pForceColor ); 1491*cdf0e10cSrcweir } 1492*cdf0e10cSrcweir else 1493*cdf0e10cSrcweir { 1494*cdf0e10cSrcweir const LineEndResult aRes; 1495*cdf0e10cSrcweir 1496*cdf0e10cSrcweir Style aScaled( rBorder ); 1497*cdf0e10cSrcweir aScaled.ScaleSelf( 1.0 / cos( GetVerDiagAngle( rTPos, rBPos ) ) ); 1498*cdf0e10cSrcweir 1499*cdf0e10cSrcweir lclSetColorToOutDev( rDev, aScaled, pForceColor ); 1500*cdf0e10cSrcweir lclDrawVerLine( rDev, rTPos, aRes, rBPos, aRes, 1501*cdf0e10cSrcweir lclGetBeg( aScaled ), lclGetPrimEnd( aScaled ), aScaled.Dotted() ); 1502*cdf0e10cSrcweir if( aScaled.Secn() ) 1503*cdf0e10cSrcweir lclDrawVerLine( rDev, rTPos, aRes, rBPos, aRes, 1504*cdf0e10cSrcweir lclGetSecnBeg( aScaled ), lclGetEnd( aScaled ), aScaled.Dotted() ); 1505*cdf0e10cSrcweir rDev.Pop(); // colors 1506*cdf0e10cSrcweir } 1507*cdf0e10cSrcweir } 1508*cdf0e10cSrcweir } 1509*cdf0e10cSrcweir 1510*cdf0e10cSrcweir // ============================================================================ 1511*cdf0e10cSrcweir 1512*cdf0e10cSrcweir void DrawDiagFrameBorders( 1513*cdf0e10cSrcweir OutputDevice& rDev, const Rectangle& rRect, const Style& rTLBR, const Style& rBLTR, 1514*cdf0e10cSrcweir const Style& rTLFromB, const Style& rTLFromR, const Style& rBRFromT, const Style& rBRFromL, 1515*cdf0e10cSrcweir const Style& rBLFromT, const Style& rBLFromR, const Style& rTRFromB, const Style& rTRFromL, 1516*cdf0e10cSrcweir const Color* pForceColor, bool bDiagDblClip ) 1517*cdf0e10cSrcweir { 1518*cdf0e10cSrcweir if( rTLBR.Prim() || rBLTR.Prim() ) 1519*cdf0e10cSrcweir { 1520*cdf0e10cSrcweir DiagBordersResult aResult; 1521*cdf0e10cSrcweir lclLinkDiagFrameBorders( aResult, rTLBR, rBLTR, 1522*cdf0e10cSrcweir rTLFromB, rTLFromR, rBRFromT, rBRFromL, rBLFromT, rBLFromR, rTRFromB, rTRFromL ); 1523*cdf0e10cSrcweir lclDrawDiagFrameBorders( rDev, rRect, rTLBR, rBLTR, aResult, pForceColor, bDiagDblClip ); 1524*cdf0e10cSrcweir } 1525*cdf0e10cSrcweir } 1526*cdf0e10cSrcweir 1527*cdf0e10cSrcweir // ============================================================================ 1528*cdf0e10cSrcweir 1529*cdf0e10cSrcweir } // namespace frame 1530*cdf0e10cSrcweir } // namespace svx 1531*cdf0e10cSrcweir 1532