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