/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: */ |