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