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