xref: /AOO41X/main/svx/source/dialog/framelink.cxx (revision 2baf5de748612d949b2478a28d89d4081ce59ad5)
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