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