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