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