Coverage Report

Created: 2026-03-31 11:00

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