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