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 <algorithm>
23
24 #include <basegfx/color/bcolor.hxx>
25 #include <basegfx/color/bcolortools.hxx>
26
27 #include <editeng/borderline.hxx>
28 #include <editeng/itemtype.hxx>
29 #include <editeng/editrids.hrc>
30 #include <editeng/eerdll.hxx>
31
32 using namespace ::com::sun::star::table::BorderLineStyle;
33
34 // class SvxBorderLine --------------------------------------------------
35
36 namespace {
37
lcl_compute3DColor(Color aMain,int nLight,int nMedium,int nDark)38 Color lcl_compute3DColor( Color aMain, int nLight, int nMedium, int nDark )
39 {
40 basegfx::BColor color = aMain.getBColor( );
41 basegfx::BColor hsl = basegfx::utils::rgb2hsl( color );
42
43 int nCoef = 0;
44 if ( hsl.getZ( ) >= 0.5 )
45 nCoef = nLight;
46 else if ( 0.5 > hsl.getZ() && hsl.getZ() >= 0.25 )
47 nCoef = nMedium;
48 else
49 nCoef = nDark;
50
51 double L = std::min(hsl.getZ() * 255.0 + nCoef, 255.0);
52 hsl.setZ( L / 255.0 );
53 color = basegfx::utils::hsl2rgb( hsl );
54
55 return Color( color );
56 }
57 } // Anonymous namespace
58
59 namespace editeng {
60
darkColor(Color aMain)61 Color SvxBorderLine::darkColor( Color aMain )
62 {
63 return aMain;
64 }
65
lightColor(Color aMain)66 Color SvxBorderLine::lightColor( Color aMain )
67 {
68
69 // Divide Luminance by 2
70 basegfx::BColor color = aMain.getBColor( );
71 basegfx::BColor hsl = basegfx::utils::rgb2hsl( color );
72 hsl.setZ( hsl.getZ() * 0.5 );
73 color = basegfx::utils::hsl2rgb( hsl );
74
75 return Color( color );
76 }
77
78
threeDLightColor(Color aMain)79 Color SvxBorderLine::threeDLightColor( Color aMain )
80 {
81 // These values have been defined in an empirical way
82 return lcl_compute3DColor( aMain, 3, 40, 83 );
83 }
84
threeDDarkColor(Color aMain)85 Color SvxBorderLine::threeDDarkColor( Color aMain )
86 {
87 // These values have been defined in an empirical way
88 return lcl_compute3DColor( aMain, -85, -43, -1 );
89 }
90
threeDMediumColor(Color aMain)91 Color SvxBorderLine::threeDMediumColor( Color aMain )
92 {
93 // These values have been defined in an empirical way
94 return lcl_compute3DColor( aMain, -42, -0, 42 );
95 }
96
SvxBorderLine(const Color * pCol,long nWidth,SvxBorderLineStyle nStyle,Color (* pColorOutFn)(Color),Color (* pColorInFn)(Color))97 SvxBorderLine::SvxBorderLine( const Color *pCol, long nWidth,
98 SvxBorderLineStyle nStyle,
99 Color (*pColorOutFn)( Color ), Color (*pColorInFn)( Color ) )
100 : m_nWidth( nWidth )
101 , m_bMirrorWidths( false )
102 , m_aWidthImpl( SvxBorderLine::getWidthImpl( nStyle ) )
103 , m_nMult( 1 )
104 , m_nDiv( 1 )
105 , m_nStyle( nStyle )
106 , m_bUseLeftTop( false )
107 , m_pColorOutFn( pColorOutFn )
108 , m_pColorInFn( pColorInFn )
109 , m_pColorGapFn( nullptr )
110 {
111 if ( pCol )
112 aColor = *pCol;
113 }
114
115
116 SvxBorderLineStyle
ConvertBorderStyleFromWord(int const nWordLineStyle)117 ConvertBorderStyleFromWord(int const nWordLineStyle)
118 {
119 switch (nWordLineStyle)
120 {
121 // First the single lines
122 case 1:
123 case 2: // thick line
124 case 5: // hairline
125 // and the unsupported special cases which we map to a single line
126 case 20:
127 return SvxBorderLineStyle::SOLID;
128 case 6:
129 return SvxBorderLineStyle::DOTTED;
130 case 7:
131 return SvxBorderLineStyle::DASHED;
132 case 22:
133 return SvxBorderLineStyle::FINE_DASHED;
134 case 8:
135 return SvxBorderLineStyle::DASH_DOT;
136 case 9:
137 return SvxBorderLineStyle::DASH_DOT_DOT;
138 // then the shading beams which we represent by a double line
139 case 23:
140 return SvxBorderLineStyle::DOUBLE;
141 // then the double lines, for which we have good matches
142 case 3:
143 case 10: // Don't have triple so use double
144 case 21: // Don't have double wave: use double instead
145 return SvxBorderLineStyle::DOUBLE;
146 case 11:
147 return SvxBorderLineStyle::THINTHICK_SMALLGAP;
148 case 12:
149 case 13: // Don't have thin thick thin, so use thick thin
150 return SvxBorderLineStyle::THICKTHIN_SMALLGAP;
151 case 14:
152 return SvxBorderLineStyle::THINTHICK_MEDIUMGAP;
153 case 15:
154 case 16: // Don't have thin thick thin, so use thick thin
155 return SvxBorderLineStyle::THICKTHIN_MEDIUMGAP;
156 case 17:
157 return SvxBorderLineStyle::THINTHICK_LARGEGAP;
158 case 18:
159 case 19: // Don't have thin thick thin, so use thick thin
160 return SvxBorderLineStyle::THICKTHIN_LARGEGAP;
161 case 24:
162 return SvxBorderLineStyle::EMBOSSED;
163 case 25:
164 return SvxBorderLineStyle::ENGRAVED;
165 case 26:
166 return SvxBorderLineStyle::OUTSET;
167 case 27:
168 return SvxBorderLineStyle::INSET;
169 default:
170 return SvxBorderLineStyle::NONE;
171 }
172 }
173
174 static const double THINTHICK_SMALLGAP_line2 = 15.0;
175 static const double THINTHICK_SMALLGAP_gap = 15.0;
176 static const double THINTHICK_LARGEGAP_line1 = 30.0;
177 static const double THINTHICK_LARGEGAP_line2 = 15.0;
178 static const double THICKTHIN_SMALLGAP_line1 = 15.0;
179 static const double THICKTHIN_SMALLGAP_gap = 15.0;
180 static const double THICKTHIN_LARGEGAP_line1 = 15.0;
181 static const double THICKTHIN_LARGEGAP_line2 = 30.0;
182 static const double OUTSET_line1 = 15.0;
183 static const double INSET_line2 = 15.0;
184
185 double
ConvertBorderWidthFromWord(SvxBorderLineStyle const eStyle,double const i_fWidth,int const nWordLineStyle)186 ConvertBorderWidthFromWord(SvxBorderLineStyle const eStyle, double const i_fWidth,
187 int const nWordLineStyle)
188 {
189 // fdo#68779: at least for RTF, 0.75pt is the default if width is missing
190 double const fWidth((i_fWidth == 0.0) ? 15.0 : i_fWidth);
191 switch (eStyle)
192 {
193 // Single lines
194 case SvxBorderLineStyle::SOLID:
195 switch (nWordLineStyle)
196 {
197 case 2:
198 return (fWidth * 2.0); // thick
199 case 5: // fdo#55526: map 0 hairline width to > 0
200 return std::max(fWidth, 1.0);
201 default:
202 return fWidth;
203 }
204 break;
205
206 case SvxBorderLineStyle::DOTTED:
207 case SvxBorderLineStyle::DASHED:
208 case SvxBorderLineStyle::DASH_DOT:
209 case SvxBorderLineStyle::DASH_DOT_DOT:
210 return fWidth;
211
212 // Display a minimum effective border width of 1pt
213 case SvxBorderLineStyle::FINE_DASHED:
214 return (fWidth > 0 && fWidth < 20) ? 20 : fWidth;
215
216 // Double lines
217 case SvxBorderLineStyle::DOUBLE:
218 return fWidth * 3.0;
219
220 case SvxBorderLineStyle::THINTHICK_MEDIUMGAP:
221 case SvxBorderLineStyle::THICKTHIN_MEDIUMGAP:
222 case SvxBorderLineStyle::EMBOSSED:
223 case SvxBorderLineStyle::ENGRAVED:
224 return fWidth * 2.0;
225
226 case SvxBorderLineStyle::THINTHICK_SMALLGAP:
227 return fWidth + THINTHICK_SMALLGAP_line2 + THINTHICK_SMALLGAP_gap;
228
229 case SvxBorderLineStyle::THINTHICK_LARGEGAP:
230 return fWidth + THINTHICK_LARGEGAP_line1 + THINTHICK_LARGEGAP_line2;
231
232 case SvxBorderLineStyle::THICKTHIN_SMALLGAP:
233 return fWidth + THICKTHIN_SMALLGAP_line1 + THICKTHIN_SMALLGAP_gap;
234
235 case SvxBorderLineStyle::THICKTHIN_LARGEGAP:
236 return fWidth + THICKTHIN_LARGEGAP_line1 + THICKTHIN_LARGEGAP_line2;
237
238 case SvxBorderLineStyle::OUTSET:
239 return (fWidth * 2.0) + OUTSET_line1;
240
241 case SvxBorderLineStyle::INSET:
242 return (fWidth * 2.0) + INSET_line2;
243
244 default:
245 assert(false); // should only be called for known border style
246 }
247 return 0;
248 }
249
250 double
ConvertBorderWidthToWord(SvxBorderLineStyle const eStyle,double const fWidth)251 ConvertBorderWidthToWord(SvxBorderLineStyle const eStyle, double const fWidth)
252 {
253 if ( !fWidth )
254 return 0;
255
256 switch (eStyle)
257 {
258 // Single lines
259 case SvxBorderLineStyle::SOLID:
260 case SvxBorderLineStyle::DOTTED:
261 case SvxBorderLineStyle::DASHED:
262 case SvxBorderLineStyle::FINE_DASHED:
263 case SvxBorderLineStyle::DASH_DOT:
264 case SvxBorderLineStyle::DASH_DOT_DOT:
265 return fWidth;
266
267 // Double lines
268 case SvxBorderLineStyle::DOUBLE:
269 case SvxBorderLineStyle::DOUBLE_THIN:
270 return std::max(1.0, fWidth / 3.0);
271
272 case SvxBorderLineStyle::THINTHICK_MEDIUMGAP:
273 case SvxBorderLineStyle::THICKTHIN_MEDIUMGAP:
274 case SvxBorderLineStyle::EMBOSSED:
275 case SvxBorderLineStyle::ENGRAVED:
276 return std::max(1.0, fWidth / 2.0);
277
278 case SvxBorderLineStyle::THINTHICK_SMALLGAP:
279 return std::max(1.0, fWidth - THINTHICK_SMALLGAP_line2 - THINTHICK_SMALLGAP_gap);
280
281 case SvxBorderLineStyle::THINTHICK_LARGEGAP:
282 return std::max(1.0, fWidth - THINTHICK_LARGEGAP_line1 - THINTHICK_LARGEGAP_line2);
283
284 case SvxBorderLineStyle::THICKTHIN_SMALLGAP:
285 return std::max(1.0, fWidth - THICKTHIN_SMALLGAP_line1 - THICKTHIN_SMALLGAP_gap);
286
287 case SvxBorderLineStyle::THICKTHIN_LARGEGAP:
288 return std::max(1.0, fWidth - THICKTHIN_LARGEGAP_line1 - THICKTHIN_LARGEGAP_line2);
289
290 case SvxBorderLineStyle::OUTSET:
291 return std::max(1.0, (fWidth - OUTSET_line1) / 2.0);
292
293 case SvxBorderLineStyle::INSET:
294 return std::max(1.0, (fWidth - INSET_line2) / 2.0);
295
296 case SvxBorderLineStyle::NONE:
297 return 0;
298
299 default:
300 assert(false); // should only be called for known border style
301 return 0;
302 }
303 }
304
305 /** Get the BorderWithImpl object corresponding to the given #nStyle, all the
306 units handled by the resulting object are Twips and the
307 BorderWidthImpl::GetLine1() corresponds to the Outer Line.
308 */
getWidthImpl(SvxBorderLineStyle nStyle)309 BorderWidthImpl SvxBorderLine::getWidthImpl( SvxBorderLineStyle nStyle )
310 {
311 BorderWidthImpl aImpl;
312
313 switch ( nStyle )
314 {
315 // No line: no width
316 case SvxBorderLineStyle::NONE:
317 aImpl = BorderWidthImpl( BorderWidthImplFlags::FIXED, 0.0 );
318 break;
319
320 // Single lines
321 case SvxBorderLineStyle::SOLID:
322 case SvxBorderLineStyle::DOTTED:
323 case SvxBorderLineStyle::DASHED:
324 case SvxBorderLineStyle::FINE_DASHED:
325 case SvxBorderLineStyle::DASH_DOT:
326 case SvxBorderLineStyle::DASH_DOT_DOT:
327 aImpl = BorderWidthImpl( BorderWidthImplFlags::CHANGE_LINE1, 1.0 );
328 break;
329
330 // Double lines
331
332 case SvxBorderLineStyle::DOUBLE:
333 aImpl = BorderWidthImpl(
334 BorderWidthImplFlags::CHANGE_LINE1 | BorderWidthImplFlags::CHANGE_LINE2 | BorderWidthImplFlags::CHANGE_DIST,
335 // fdo#46112 fdo#38542 fdo#43249:
336 // non-constant widths must sum to 1
337 1.0/3.0, 1.0/3.0, 1.0/3.0 );
338 break;
339
340 case SvxBorderLineStyle::DOUBLE_THIN:
341 aImpl = BorderWidthImpl(BorderWidthImplFlags::CHANGE_DIST, 10.0, 10.0, 1.0);
342 break;
343
344 case SvxBorderLineStyle::THINTHICK_SMALLGAP:
345 aImpl = BorderWidthImpl( BorderWidthImplFlags::CHANGE_LINE1, 1.0,
346 THINTHICK_SMALLGAP_line2, THINTHICK_SMALLGAP_gap );
347 break;
348
349 case SvxBorderLineStyle::THINTHICK_MEDIUMGAP:
350 aImpl = BorderWidthImpl(
351 BorderWidthImplFlags::CHANGE_LINE1 | BorderWidthImplFlags::CHANGE_LINE2 | BorderWidthImplFlags::CHANGE_DIST,
352 0.5, 0.25, 0.25 );
353 break;
354
355 case SvxBorderLineStyle::THINTHICK_LARGEGAP:
356 aImpl = BorderWidthImpl( BorderWidthImplFlags::CHANGE_DIST,
357 THINTHICK_LARGEGAP_line1, THINTHICK_LARGEGAP_line2, 1.0 );
358 break;
359
360 case SvxBorderLineStyle::THICKTHIN_SMALLGAP:
361 aImpl = BorderWidthImpl( BorderWidthImplFlags::CHANGE_LINE2, THICKTHIN_SMALLGAP_line1,
362 1.0, THICKTHIN_SMALLGAP_gap );
363 break;
364
365 case SvxBorderLineStyle::THICKTHIN_MEDIUMGAP:
366 aImpl = BorderWidthImpl(
367 BorderWidthImplFlags::CHANGE_LINE1 | BorderWidthImplFlags::CHANGE_LINE2 | BorderWidthImplFlags::CHANGE_DIST,
368 0.25, 0.5, 0.25 );
369 break;
370
371 case SvxBorderLineStyle::THICKTHIN_LARGEGAP:
372 aImpl = BorderWidthImpl( BorderWidthImplFlags::CHANGE_DIST, THICKTHIN_LARGEGAP_line1,
373 THICKTHIN_LARGEGAP_line2, 1.0 );
374 break;
375
376 // Engraved / Embossed
377 /*
378 * Word compat: the lines widths are exactly following this rule, should be:
379 * 0.75pt up to 3pt and then 3pt
380 */
381
382 case SvxBorderLineStyle::EMBOSSED:
383 case SvxBorderLineStyle::ENGRAVED:
384 aImpl = BorderWidthImpl(
385 BorderWidthImplFlags::CHANGE_LINE1 | BorderWidthImplFlags::CHANGE_LINE2 | BorderWidthImplFlags::CHANGE_DIST,
386 0.25, 0.25, 0.5 );
387 break;
388
389 // Inset / Outset
390 /*
391 * Word compat: the gap width should be measured relatively to the biggest width for the
392 * row or column.
393 */
394 case SvxBorderLineStyle::OUTSET:
395 aImpl = BorderWidthImpl(
396 BorderWidthImplFlags::CHANGE_LINE2 | BorderWidthImplFlags::CHANGE_DIST,
397 OUTSET_line1, 0.5, 0.5 );
398 break;
399
400 case SvxBorderLineStyle::INSET:
401 aImpl = BorderWidthImpl(
402 BorderWidthImplFlags::CHANGE_LINE1 | BorderWidthImplFlags::CHANGE_DIST,
403 0.5, INSET_line2, 0.5 );
404 break;
405 }
406
407 return aImpl;
408 }
409
ScaleMetrics(long nMult,long nDiv)410 void SvxBorderLine::ScaleMetrics( long nMult, long nDiv )
411 {
412 m_nMult = nMult;
413 m_nDiv = nDiv;
414 }
415
GuessLinesWidths(SvxBorderLineStyle nStyle,sal_uInt16 nOut,sal_uInt16 nIn,sal_uInt16 nDist)416 void SvxBorderLine::GuessLinesWidths( SvxBorderLineStyle nStyle, sal_uInt16 nOut, sal_uInt16 nIn, sal_uInt16 nDist )
417 {
418 if (SvxBorderLineStyle::NONE == nStyle)
419 {
420 nStyle = SvxBorderLineStyle::SOLID;
421 if ( nOut > 0 && nIn > 0 )
422 nStyle = SvxBorderLineStyle::DOUBLE;
423 }
424
425 if ( nStyle == SvxBorderLineStyle::DOUBLE )
426 {
427 static const SvxBorderLineStyle aDoubleStyles[] =
428 {
429 SvxBorderLineStyle::DOUBLE,
430 SvxBorderLineStyle::DOUBLE_THIN,
431 SvxBorderLineStyle::THINTHICK_SMALLGAP,
432 SvxBorderLineStyle::THINTHICK_MEDIUMGAP,
433 SvxBorderLineStyle::THINTHICK_LARGEGAP,
434 SvxBorderLineStyle::THICKTHIN_SMALLGAP,
435 SvxBorderLineStyle::THICKTHIN_MEDIUMGAP,
436 SvxBorderLineStyle::THICKTHIN_LARGEGAP
437 };
438
439 static size_t const len = SAL_N_ELEMENTS(aDoubleStyles);
440 long nWidth = 0;
441 SvxBorderLineStyle nTestStyle(SvxBorderLineStyle::NONE);
442 for (size_t i = 0; i < len && nWidth == 0; ++i)
443 {
444 nTestStyle = aDoubleStyles[i];
445 BorderWidthImpl aWidthImpl = getWidthImpl( nTestStyle );
446 nWidth = aWidthImpl.GuessWidth( nOut, nIn, nDist );
447 }
448
449 // If anything matched, then set it
450 if ( nWidth > 0 )
451 {
452 nStyle = nTestStyle;
453 SetBorderLineStyle(nStyle);
454 m_nWidth = nWidth;
455 }
456 else
457 {
458 // fdo#38542: not a known double, default to something custom...
459 SetBorderLineStyle(nStyle);
460 m_nWidth = nOut + nIn + nDist;
461 if (nOut + nIn + nDist)
462 {
463 m_aWidthImpl = BorderWidthImpl(
464 BorderWidthImplFlags::CHANGE_LINE1 | BorderWidthImplFlags::CHANGE_LINE2 | BorderWidthImplFlags::CHANGE_DIST,
465 static_cast<double>(nOut ) / static_cast<double>(m_nWidth),
466 static_cast<double>(nIn ) / static_cast<double>(m_nWidth),
467 static_cast<double>(nDist) / static_cast<double>(m_nWidth));
468 }
469 }
470 }
471 else
472 {
473 SetBorderLineStyle(nStyle);
474 if (nOut == 0 && nIn > 0)
475 {
476 // If only inner width is given swap inner and outer widths for
477 // single line styles, otherwise GuessWidth() marks this as invalid
478 // and returns a 0 width.
479 switch (nStyle)
480 {
481 case SvxBorderLineStyle::SOLID:
482 case SvxBorderLineStyle::DOTTED:
483 case SvxBorderLineStyle::DASHED:
484 case SvxBorderLineStyle::FINE_DASHED:
485 case SvxBorderLineStyle::DASH_DOT:
486 case SvxBorderLineStyle::DASH_DOT_DOT:
487 std::swap( nOut, nIn);
488 break;
489 default:
490 ; // nothing
491 }
492 }
493 m_nWidth = m_aWidthImpl.GuessWidth( nOut, nIn, nDist );
494 }
495 }
496
GetOutWidth() const497 sal_uInt16 SvxBorderLine::GetOutWidth() const
498 {
499 sal_uInt16 nOut = static_cast<sal_uInt16>(Scale( m_aWidthImpl.GetLine1( m_nWidth ), m_nMult, m_nDiv ));
500 if ( m_bMirrorWidths )
501 nOut = static_cast<sal_uInt16>(Scale( m_aWidthImpl.GetLine2( m_nWidth ), m_nMult, m_nDiv ));
502 return nOut;
503 }
504
GetInWidth() const505 sal_uInt16 SvxBorderLine::GetInWidth() const
506 {
507 sal_uInt16 nIn = static_cast<sal_uInt16>(Scale( m_aWidthImpl.GetLine2( m_nWidth ), m_nMult, m_nDiv ));
508 if ( m_bMirrorWidths )
509 nIn = static_cast<sal_uInt16>(Scale( m_aWidthImpl.GetLine1( m_nWidth ), m_nMult, m_nDiv ));
510 return nIn;
511 }
512
GetDistance() const513 sal_uInt16 SvxBorderLine::GetDistance() const
514 {
515 return static_cast<sal_uInt16>(Scale( m_aWidthImpl.GetGap( m_nWidth ), m_nMult, m_nDiv ));
516 }
517
518
operator ==(const SvxBorderLine & rCmp) const519 bool SvxBorderLine::operator==( const SvxBorderLine& rCmp ) const
520 {
521 return ( ( aColor == rCmp.aColor ) &&
522 ( m_nWidth == rCmp.m_nWidth ) &&
523 ( m_bMirrorWidths == rCmp.m_bMirrorWidths ) &&
524 ( m_aWidthImpl == rCmp.m_aWidthImpl ) &&
525 ( m_nStyle == rCmp.GetBorderLineStyle()) &&
526 ( m_bUseLeftTop == rCmp.m_bUseLeftTop ) &&
527 ( m_pColorOutFn == rCmp.m_pColorOutFn ) &&
528 ( m_pColorInFn == rCmp.m_pColorInFn ) &&
529 ( m_pColorGapFn == rCmp.m_pColorGapFn ) );
530 }
531
SetBorderLineStyle(SvxBorderLineStyle nNew)532 void SvxBorderLine::SetBorderLineStyle( SvxBorderLineStyle nNew )
533 {
534 m_nStyle = nNew;
535 m_aWidthImpl = getWidthImpl( m_nStyle );
536
537 switch ( nNew )
538 {
539 case SvxBorderLineStyle::EMBOSSED:
540 m_pColorOutFn = threeDLightColor;
541 m_pColorInFn = threeDDarkColor;
542 m_pColorGapFn = threeDMediumColor;
543 m_bUseLeftTop = true;
544 break;
545 case SvxBorderLineStyle::ENGRAVED:
546 m_pColorOutFn = threeDDarkColor;
547 m_pColorInFn = threeDLightColor;
548 m_pColorGapFn = threeDMediumColor;
549 m_bUseLeftTop = true;
550 break;
551 case SvxBorderLineStyle::OUTSET:
552 m_pColorOutFn = lightColor;
553 m_pColorInFn = darkColor;
554 m_bUseLeftTop = true;
555 m_pColorGapFn = nullptr;
556 break;
557 case SvxBorderLineStyle::INSET:
558 m_pColorOutFn = darkColor;
559 m_pColorInFn = lightColor;
560 m_bUseLeftTop = true;
561 m_pColorGapFn = nullptr;
562 break;
563 default:
564 m_pColorOutFn = darkColor;
565 m_pColorInFn = darkColor;
566 m_bUseLeftTop = false;
567 m_pColorGapFn = nullptr;
568 break;
569 }
570 }
571
GetColorOut(bool bLeftOrTop) const572 Color SvxBorderLine::GetColorOut( bool bLeftOrTop ) const
573 {
574 Color aResult = aColor;
575
576 if ( m_aWidthImpl.IsDouble() && m_pColorOutFn != nullptr )
577 {
578 if ( !bLeftOrTop && m_bUseLeftTop )
579 aResult = (*m_pColorInFn)( aColor );
580 else
581 aResult = (*m_pColorOutFn)( aColor );
582 }
583
584 return aResult;
585 }
586
GetColorIn(bool bLeftOrTop) const587 Color SvxBorderLine::GetColorIn( bool bLeftOrTop ) const
588 {
589 Color aResult = aColor;
590
591 if ( m_aWidthImpl.IsDouble() && m_pColorInFn != nullptr )
592 {
593 if ( !bLeftOrTop && m_bUseLeftTop )
594 aResult = (*m_pColorOutFn)( aColor );
595 else
596 aResult = (*m_pColorInFn)( aColor );
597 }
598
599 return aResult;
600 }
601
GetColorGap() const602 Color SvxBorderLine::GetColorGap( ) const
603 {
604 Color aResult = aColor;
605
606 if ( m_aWidthImpl.IsDouble() && m_pColorGapFn != nullptr )
607 {
608 aResult = (*m_pColorGapFn)( aColor );
609 }
610
611 return aResult;
612 }
613
SetWidth(long nWidth)614 void SvxBorderLine::SetWidth( long nWidth )
615 {
616 m_nWidth = nWidth;
617 }
618
GetValueString(MapUnit eSrcUnit,MapUnit eDestUnit,const IntlWrapper * pIntl,bool bMetricStr) const619 OUString SvxBorderLine::GetValueString(MapUnit eSrcUnit,
620 MapUnit eDestUnit,
621 const IntlWrapper* pIntl,
622 bool bMetricStr) const
623 {
624 static const char* aStyleIds[] =
625 {
626 RID_SOLID,
627 RID_DOTTED,
628 RID_DASHED,
629 RID_DOUBLE,
630 RID_THINTHICK_SMALLGAP,
631 RID_THINTHICK_MEDIUMGAP,
632 RID_THINTHICK_LARGEGAP,
633 RID_THICKTHIN_SMALLGAP,
634 RID_THICKTHIN_MEDIUMGAP,
635 RID_THICKTHIN_LARGEGAP,
636 RID_EMBOSSED,
637 RID_ENGRAVED,
638 RID_OUTSET,
639 RID_INSET,
640 RID_FINE_DASHED,
641 RID_DOUBLE_THIN,
642 RID_DASH_DOT,
643 RID_DASH_DOT_DOT
644 };
645 OUString aStr = "(" + ::GetColorString( aColor ) + cpDelim;
646
647 if ( static_cast<int>(m_nStyle) < int(SAL_N_ELEMENTS(aStyleIds)) )
648 {
649 const char* pResId = aStyleIds[static_cast<int>(m_nStyle)];
650 aStr += EditResId(pResId);
651 }
652 else
653 {
654 OUString sMetric = EditResId(GetMetricId( eDestUnit ));
655 aStr += GetMetricText( static_cast<long>(GetInWidth()), eSrcUnit, eDestUnit, pIntl );
656 if ( bMetricStr )
657 aStr += sMetric;
658 aStr += cpDelim +
659 GetMetricText( static_cast<long>(GetOutWidth()), eSrcUnit, eDestUnit, pIntl );
660 if ( bMetricStr )
661 aStr += sMetric;
662 aStr += cpDelim +
663 GetMetricText( static_cast<long>(GetDistance()), eSrcUnit, eDestUnit, pIntl );
664 if ( bMetricStr )
665 aStr += sMetric;
666 }
667 aStr += ")";
668 return aStr;
669 }
670
HasPriority(const SvxBorderLine & rOtherLine) const671 bool SvxBorderLine::HasPriority( const SvxBorderLine& rOtherLine ) const
672 {
673 const sal_uInt16 nThisSize = GetScaledWidth();
674 const sal_uInt16 nOtherSize = rOtherLine.GetScaledWidth();
675
676 if ( nThisSize > nOtherSize )
677 {
678 return true;
679 }
680 else if ( nThisSize < nOtherSize )
681 {
682 return false;
683 }
684 else if ( rOtherLine.GetInWidth() && !GetInWidth() )
685 {
686 return true;
687 }
688
689 return false;
690 }
691
operator !=(const SvxBorderLine & rLeft,const SvxBorderLine & rRight)692 bool operator!=( const SvxBorderLine& rLeft, const SvxBorderLine& rRight )
693 {
694 return !(rLeft == rRight);
695 }
696
697 } // namespace editeng
698
699 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
700