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