tdf#130857 qt weld: Support mail merge "Server Auth" dialog
[LibreOffice.git] / oox / source / drawingml / color.cxx
blob8ca000cb763e874bcb5833b3b3fcd0becce4a691
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <oox/drawingml/color.hxx>
21 #include <algorithm>
22 #include <frozen/bits/defines.h>
23 #include <frozen/bits/elsa_std.h>
24 #include <frozen/unordered_map.h>
25 #include <math.h>
26 #include <osl/diagnose.h>
27 #include <sal/log.hxx>
28 #include <oox/helper/containerhelper.hxx>
29 #include <oox/helper/graphichelper.hxx>
30 #include <oox/drawingml/drawingmltypes.hxx>
31 #include <oox/token/namespaces.hxx>
32 #include <oox/token/tokens.hxx>
34 namespace oox::drawingml {
36 namespace
39 // predefined colors in DrawingML (map XML token identifiers to RGB values)
40 constexpr frozen::unordered_map<sal_Int32, ::Color, 140> constDmlColors
42 {XML_aliceBlue, ::Color(0xF0F8FF)}, {XML_antiqueWhite, ::Color(0xFAEBD7)},
43 {XML_aqua, ::Color(0x00FFFF)}, {XML_aquamarine, ::Color(0x7FFFD4)},
44 {XML_azure, ::Color(0xF0FFFF)}, {XML_beige, ::Color(0xF5F5DC)},
45 {XML_bisque, ::Color(0xFFE4C4)}, {XML_black, ::Color(0x000000)},
46 {XML_blanchedAlmond, ::Color(0xFFEBCD)}, {XML_blue, ::Color(0x0000FF)},
47 {XML_blueViolet, ::Color(0x8A2BE2)}, {XML_brown, ::Color(0xA52A2A)},
48 {XML_burlyWood, ::Color(0xDEB887)}, {XML_cadetBlue, ::Color(0x5F9EA0)},
49 {XML_chartreuse, ::Color(0x7FFF00)}, {XML_chocolate, ::Color(0xD2691E)},
50 {XML_coral, ::Color(0xFF7F50)}, {XML_cornflowerBlue, ::Color(0x6495ED)},
51 {XML_cornsilk, ::Color(0xFFF8DC)}, {XML_crimson, ::Color(0xDC143C)},
52 {XML_cyan, ::Color(0x00FFFF)}, {XML_deepPink, ::Color(0xFF1493)},
53 {XML_deepSkyBlue, ::Color(0x00BFFF)}, {XML_dimGray, ::Color(0x696969)},
54 {XML_dkBlue, ::Color(0x00008B)}, {XML_dkCyan, ::Color(0x008B8B)},
55 {XML_dkGoldenrod, ::Color(0xB8860B)}, {XML_dkGray, ::Color(0xA9A9A9)},
56 {XML_dkGreen, ::Color(0x006400)}, {XML_dkKhaki, ::Color(0xBDB76B)},
57 {XML_dkMagenta, ::Color(0x8B008B)}, {XML_dkOliveGreen, ::Color(0x556B2F)},
58 {XML_dkOrange, ::Color(0xFF8C00)}, {XML_dkOrchid, ::Color(0x9932CC)},
59 {XML_dkRed, ::Color(0x8B0000)}, {XML_dkSalmon, ::Color(0xE9967A)},
60 {XML_dkSeaGreen, ::Color(0x8FBC8B)}, {XML_dkSlateBlue, ::Color(0x483D8B)},
61 {XML_dkSlateGray, ::Color(0x2F4F4F)}, {XML_dkTurquoise, ::Color(0x00CED1)},
62 {XML_dkViolet, ::Color(0x9400D3)}, {XML_dodgerBlue, ::Color(0x1E90FF)},
63 {XML_firebrick, ::Color(0xB22222)}, {XML_floralWhite, ::Color(0xFFFAF0)},
64 {XML_forestGreen, ::Color(0x228B22)}, {XML_fuchsia, ::Color(0xFF00FF)},
65 {XML_gainsboro, ::Color(0xDCDCDC)}, {XML_ghostWhite, ::Color(0xF8F8FF)},
66 {XML_gold, ::Color(0xFFD700)}, {XML_goldenrod, ::Color(0xDAA520)},
67 {XML_gray, ::Color(0x808080)}, {XML_green, ::Color(0x008000)},
68 {XML_greenYellow, ::Color(0xADFF2F)}, {XML_honeydew, ::Color(0xF0FFF0)},
69 {XML_hotPink, ::Color(0xFF69B4)}, {XML_indianRed, ::Color(0xCD5C5C)},
70 {XML_indigo, ::Color(0x4B0082)}, {XML_ivory, ::Color(0xFFFFF0)},
71 {XML_khaki, ::Color(0xF0E68C)}, {XML_lavender, ::Color(0xE6E6FA)},
72 {XML_lavenderBlush, ::Color(0xFFF0F5)}, {XML_lawnGreen, ::Color(0x7CFC00)},
73 {XML_lemonChiffon, ::Color(0xFFFACD)}, {XML_lime, ::Color(0x00FF00)},
74 {XML_limeGreen, ::Color(0x32CD32)}, {XML_linen, ::Color(0xFAF0E6)},
75 {XML_ltBlue, ::Color(0xADD8E6)}, {XML_ltCoral, ::Color(0xF08080)},
76 {XML_ltCyan, ::Color(0xE0FFFF)}, {XML_ltGoldenrodYellow, ::Color(0xFAFA78)},
77 {XML_ltGray, ::Color(0xD3D3D3)}, {XML_ltGreen, ::Color(0x90EE90)},
78 {XML_ltPink, ::Color(0xFFB6C1)}, {XML_ltSalmon, ::Color(0xFFA07A)},
79 {XML_ltSeaGreen, ::Color(0x20B2AA)}, {XML_ltSkyBlue, ::Color(0x87CEFA)},
80 {XML_ltSlateGray, ::Color(0x778899)}, {XML_ltSteelBlue, ::Color(0xB0C4DE)},
81 {XML_ltYellow, ::Color(0xFFFFE0)}, {XML_magenta, ::Color(0xFF00FF)},
82 {XML_maroon, ::Color(0x800000)}, {XML_medAquamarine, ::Color(0x66CDAA)},
83 {XML_medBlue, ::Color(0x0000CD)}, {XML_medOrchid, ::Color(0xBA55D3)},
84 {XML_medPurple, ::Color(0x9370DB)}, {XML_medSeaGreen, ::Color(0x3CB371)},
85 {XML_medSlateBlue, ::Color(0x7B68EE)}, {XML_medSpringGreen, ::Color(0x00FA9A)},
86 {XML_medTurquoise, ::Color(0x48D1CC)}, {XML_medVioletRed, ::Color(0xC71585)},
87 {XML_midnightBlue, ::Color(0x191970)}, {XML_mintCream, ::Color(0xF5FFFA)},
88 {XML_mistyRose, ::Color(0xFFE4E1)}, {XML_moccasin, ::Color(0xFFE4B5)},
89 {XML_navajoWhite, ::Color(0xFFDEAD)}, {XML_navy, ::Color(0x000080)},
90 {XML_oldLace, ::Color(0xFDF5E6)}, {XML_olive, ::Color(0x808000)},
91 {XML_oliveDrab, ::Color(0x6B8E23)}, {XML_orange, ::Color(0xFFA500)},
92 {XML_orangeRed, ::Color(0xFF4500)}, {XML_orchid, ::Color(0xDA70D6)},
93 {XML_paleGoldenrod, ::Color(0xEEE8AA)}, {XML_paleGreen, ::Color(0x98FB98)},
94 {XML_paleTurquoise, ::Color(0xAFEEEE)}, {XML_paleVioletRed, ::Color(0xDB7093)},
95 {XML_papayaWhip, ::Color(0xFFEFD5)}, {XML_peachPuff, ::Color(0xFFDAB9)},
96 {XML_peru, ::Color(0xCD853F)}, {XML_pink, ::Color(0xFFC0CB)},
97 {XML_plum, ::Color(0xDDA0DD)}, {XML_powderBlue, ::Color(0xB0E0E6)},
98 {XML_purple, ::Color(0x800080)}, {XML_red, ::Color(0xFF0000)},
99 {XML_rosyBrown, ::Color(0xBC8F8F)}, {XML_royalBlue, ::Color(0x4169E1)},
100 {XML_saddleBrown, ::Color(0x8B4513)}, {XML_salmon, ::Color(0xFA8072)},
101 {XML_sandyBrown, ::Color(0xF4A460)}, {XML_seaGreen, ::Color(0x2E8B57)},
102 {XML_seaShell, ::Color(0xFFF5EE)}, {XML_sienna, ::Color(0xA0522D)},
103 {XML_silver, ::Color(0xC0C0C0)}, {XML_skyBlue, ::Color(0x87CEEB)},
104 {XML_slateBlue, ::Color(0x6A5ACD)}, {XML_slateGray, ::Color(0x708090)},
105 {XML_snow, ::Color(0xFFFAFA)}, {XML_springGreen, ::Color(0x00FF7F)},
106 {XML_steelBlue, ::Color(0x4682B4)}, {XML_tan, ::Color(0xD2B48C)},
107 {XML_teal, ::Color(0x008080)}, {XML_thistle, ::Color(0xD8BFD8)},
108 {XML_tomato, ::Color(0xFF6347)}, {XML_turquoise, ::Color(0x40E0D0)},
109 {XML_violet, ::Color(0xEE82EE)}, {XML_wheat, ::Color(0xF5DEB3)},
110 {XML_white, ::Color(0xFFFFFF)}, {XML_whiteSmoke, ::Color(0xF5F5F5)},
111 {XML_yellow, ::Color(0xFFFF00)}, {XML_yellowGreen, ::Color(0x9ACD32)}
114 constexpr ::Color lookupDmlColor(sal_Int32 nToken)
116 auto iterator = constDmlColors.find(nToken);
117 if (iterator == constDmlColors.end())
118 return API_RGB_TRANSPARENT;
119 return iterator->second;
122 constexpr frozen::unordered_map<sal_Int32, ::Color, 16> constVmlColors
124 {XML_aqua, ::Color(0x00FFFF)}, {XML_black, ::Color(0x000000)},
125 {XML_blue, ::Color(0x0000FF)}, {XML_fuchsia, ::Color(0xFF00FF)},
126 {XML_gray, ::Color(0x808080)}, {XML_green, ::Color(0x008000)},
127 {XML_lime, ::Color(0x00FF00)}, {XML_maroon, ::Color(0x800000)},
128 {XML_navy, ::Color(0x000080)}, {XML_olive, ::Color(0x808000)},
129 {XML_purple, ::Color(0x800080)}, {XML_red, ::Color(0xFF0000)},
130 {XML_silver, ::Color(0xC0C0C0)}, {XML_teal, ::Color(0x008080)},
131 {XML_white, ::Color(0xFFFFFF)}, {XML_yellow, ::Color(0xFFFF00)}
134 constexpr ::Color lookupVmlColor(sal_Int32 nToken)
136 auto iterator = constVmlColors.find(nToken);
137 if (iterator == constVmlColors.end())
138 return API_RGB_TRANSPARENT;
139 return iterator->second;
142 constexpr frozen::unordered_map<sal_Int32, ::Color, 16> constHighlightColors
144 // tdf#131841 Predefined color for OOXML highlight.
145 {XML_black, ::Color(0x000000)}, {XML_blue, ::Color(0x0000FF)},
146 {XML_cyan, ::Color(0x00FFFF)}, {XML_darkBlue, ::Color(0x00008B)},
147 {XML_darkCyan, ::Color(0x008B8B)}, {XML_darkGray, ::Color(0xA9A9A9)},
148 {XML_darkGreen, ::Color(0x006400)}, {XML_darkMagenta, ::Color(0x800080)},
149 {XML_darkRed, ::Color(0x8B0000)}, {XML_darkYellow, ::Color(0x808000)},
150 {XML_green, ::Color(0x00FF00)}, {XML_lightGray, ::Color(0xD3D3D3)},
151 {XML_magenta, ::Color(0xFF00FF)}, {XML_red, ::Color(0xFF0000)},
152 {XML_white, ::Color(0xFFFFFF)}, {XML_yellow, ::Color(0xFFFF00)}
155 constexpr ::Color lookupHighlightColor(sal_Int32 nToken)
157 auto iterator = constHighlightColors.find(nToken);
158 if (iterator == constHighlightColors.end())
159 return API_RGB_TRANSPARENT;
160 return iterator->second;
163 const double DEC_GAMMA = 2.3;
164 const double INC_GAMMA = 1.0 / DEC_GAMMA;
166 void lclRgbToRgbComponents( sal_Int32& ornR, sal_Int32& ornG, sal_Int32& ornB, ::Color nRgb )
168 ornR = nRgb.GetRed();
169 ornG = nRgb.GetGreen();
170 ornB = nRgb.GetBlue();
173 sal_Int32 lclRgbComponentsToRgb( sal_Int32 nR, sal_Int32 nG, sal_Int32 nB )
175 return static_cast< sal_Int32 >( (nR << 16) | (nG << 8) | nB );
178 sal_Int32 lclRgbCompToCrgbComp( sal_Int32 nRgbComp )
180 return static_cast< sal_Int32 >( nRgbComp * MAX_PERCENT / 255 );
183 sal_Int32 lclCrgbCompToRgbComp( sal_Int32 nCrgbComp )
185 return static_cast< sal_Int32 >( nCrgbComp * 255 / MAX_PERCENT );
188 sal_Int32 lclGamma( sal_Int32 nComp, double fGamma )
190 return static_cast< sal_Int32 >( pow( static_cast< double >( nComp ) / MAX_PERCENT, fGamma ) * MAX_PERCENT + 0.5 );
193 void lclSetValue( sal_Int32& ornValue, sal_Int32 nNew, sal_Int32 nMax = MAX_PERCENT )
195 OSL_ENSURE( (0 <= nNew) && (nNew <= nMax), "lclSetValue - invalid value" );
196 if( (0 <= nNew) && (nNew <= nMax) )
197 ornValue = nNew;
200 void lclModValue( sal_Int32& ornValue, sal_Int32 nMod, sal_Int32 nMax = MAX_PERCENT )
202 OSL_ENSURE( (0 <= nMod), "lclModValue - invalid modificator" );
203 ornValue = getLimitedValue< sal_Int32, double >( static_cast< double >( ornValue ) * nMod / MAX_PERCENT, 0, nMax );
206 void lclOffValue( sal_Int32& ornValue, sal_Int32 nOff, sal_Int32 nMax = MAX_PERCENT )
208 OSL_ENSURE( (-nMax <= nOff) && (nOff <= nMax), "lclOffValue - invalid offset" );
209 ornValue = getLimitedValue< sal_Int32, sal_Int32 >( ornValue + nOff, 0, nMax );
212 constexpr frozen::unordered_map<std::u16string_view, model::ThemeColorType, 26> constSchemeColorNameToIndex
214 { u"dk1", model::ThemeColorType::Dark1 },
215 { u"lt1", model::ThemeColorType::Light1 },
216 { u"dk2", model::ThemeColorType::Dark2 },
217 { u"lt2", model::ThemeColorType::Light2 },
218 { u"accent1", model::ThemeColorType::Accent1 },
219 { u"accent2", model::ThemeColorType::Accent2 },
220 { u"accent3", model::ThemeColorType::Accent3 },
221 { u"accent4", model::ThemeColorType::Accent4 },
222 { u"accent5", model::ThemeColorType::Accent5 },
223 { u"accent6", model::ThemeColorType::Accent6 },
224 { u"hlink", model::ThemeColorType::Hyperlink },
225 { u"folHlink", model::ThemeColorType::FollowedHyperlink },
226 { u"tx1", model::ThemeColorType::Dark1 },
227 { u"bg1", model::ThemeColorType::Light1 },
228 { u"tx2", model::ThemeColorType::Dark2 },
229 { u"bg2", model::ThemeColorType::Light2 },
230 { u"dark1", model::ThemeColorType::Dark1},
231 { u"light1", model::ThemeColorType::Light1},
232 { u"dark2", model::ThemeColorType::Dark2 },
233 { u"light2", model::ThemeColorType::Light2 },
234 { u"text1", model::ThemeColorType::Dark1 },
235 { u"background1", model::ThemeColorType::Light1 },
236 { u"text2", model::ThemeColorType::Dark2 },
237 { u"background2", model::ThemeColorType::Light2 },
238 { u"hyperlink", model::ThemeColorType::Hyperlink },
239 { u"followedHyperlink", model::ThemeColorType::FollowedHyperlink }
242 constexpr frozen::unordered_map<sal_Int32, model::ThemeColorType, 26> constThemeColorTokenMap
244 { XML_dk1, model::ThemeColorType::Dark1 },
245 { XML_lt1, model::ThemeColorType::Light1 },
246 { XML_dk2, model::ThemeColorType::Dark2 },
247 { XML_lt2, model::ThemeColorType::Light2 },
248 { XML_accent1, model::ThemeColorType::Accent1 },
249 { XML_accent2, model::ThemeColorType::Accent2 },
250 { XML_accent3, model::ThemeColorType::Accent3 },
251 { XML_accent4, model::ThemeColorType::Accent4 },
252 { XML_accent5, model::ThemeColorType::Accent5 },
253 { XML_accent6, model::ThemeColorType::Accent6 },
254 { XML_hlink, model::ThemeColorType::Hyperlink },
255 { XML_folHlink, model::ThemeColorType::FollowedHyperlink },
256 { XML_tx1, model::ThemeColorType::Dark1 },
257 { XML_bg1, model::ThemeColorType::Light1 },
258 { XML_tx2, model::ThemeColorType::Dark2 },
259 { XML_bg2, model::ThemeColorType::Light2 },
260 { XML_dark1, model::ThemeColorType::Dark1 },
261 { XML_light1, model::ThemeColorType::Light1 },
262 { XML_dark2, model::ThemeColorType::Dark2 },
263 { XML_light2, model::ThemeColorType::Light2 },
264 { XML_text1, model::ThemeColorType::Dark1 },
265 { XML_background1, model::ThemeColorType::Light1 },
266 { XML_text2, model::ThemeColorType::Dark2 },
267 { XML_background2, model::ThemeColorType::Light2 },
268 { XML_hyperlink, model::ThemeColorType::Hyperlink },
269 { XML_followedHyperlink, model::ThemeColorType::FollowedHyperlink },
272 } // end anonymous namespace
274 model::ThemeColorType schemeNameToThemeColorType(OUString const& rSchemeName)
276 auto aIterator = constSchemeColorNameToIndex.find(rSchemeName);
277 if (aIterator == constSchemeColorNameToIndex.end())
278 return model::ThemeColorType::Unknown;
279 else
280 return aIterator->second;
283 model::ThemeColorType schemeTokenToThemeColorType(sal_uInt32 nToken)
285 auto aIterator = constThemeColorTokenMap.find(nToken);
286 if (aIterator == constThemeColorTokenMap.end())
287 return model::ThemeColorType::Unknown;
288 else
289 return aIterator->second;
292 Color::Color() :
293 meMode( COLOR_UNUSED ),
294 mnC1( 0 ),
295 mnC2( 0 ),
296 mnC3( 0 ),
297 mnAlpha( MAX_PERCENT ),
298 meThemeColorType( model::ThemeColorType::Unknown )
302 ::Color Color::getDmlPresetColor( sal_Int32 nToken, ::Color nDefaultRgb )
304 /* Do not pass nDefaultRgb to ContainerHelper::getVectorElement(), to be
305 able to catch the existing vector entries without corresponding XML
306 token identifier. */
307 ::Color nRgbValue = lookupDmlColor(nToken);
308 return (sal_Int32(nRgbValue) >= 0) ? nRgbValue : nDefaultRgb;
311 ::Color Color::getVmlPresetColor( sal_Int32 nToken, ::Color nDefaultRgb )
313 /* Do not pass nDefaultRgb to ContainerHelper::getVectorElement(), to be
314 able to catch the existing vector entries without corresponding XML
315 token identifier. */
316 ::Color nRgbValue = lookupVmlColor(nToken);
317 return (sal_Int32(nRgbValue) >= 0) ? nRgbValue : nDefaultRgb;
320 ::Color Color::getHighlightColor(sal_Int32 nToken, ::Color nDefaultRgb)
322 /* Do not pass nDefaultRgb to ContainerHelper::getVectorElement(), to be
323 able to catch the existing vector entries without corresponding XML
324 token identifier. */
325 ::Color nRgbValue = lookupHighlightColor(nToken);
326 return (sal_Int32(nRgbValue) >= 0) ? nRgbValue : nDefaultRgb;
329 void Color::setUnused()
331 meMode = COLOR_UNUSED;
334 void Color::setSrgbClr( ::Color nRgb )
336 setSrgbClr(sal_Int32(nRgb));
339 void Color::setSrgbClr( sal_Int32 nRgb )
341 OSL_ENSURE( (0 <= nRgb) && (nRgb <= 0xFFFFFF), "Color::setSrgbClr - invalid RGB value" );
342 meMode = COLOR_RGB;
343 lclRgbToRgbComponents( mnC1, mnC2, mnC3, ::Color(ColorTransparency, nRgb) );
346 void Color::setScrgbClr( sal_Int32 nR, sal_Int32 nG, sal_Int32 nB )
348 OSL_ENSURE( (0 <= nR) && (nR <= MAX_PERCENT), "Color::setScrgbClr - invalid red value" );
349 OSL_ENSURE( (0 <= nG) && (nG <= MAX_PERCENT), "Color::setScrgbClr - invalid green value" );
350 OSL_ENSURE( (0 <= nB) && (nB <= MAX_PERCENT), "Color::setScrgbClr - invalid blue value" );
351 meMode = COLOR_CRGB;
352 mnC1 = getLimitedValue< sal_Int32, sal_Int32 >( nR, 0, MAX_PERCENT );
353 mnC2 = getLimitedValue< sal_Int32, sal_Int32 >( nG, 0, MAX_PERCENT );
354 mnC3 = getLimitedValue< sal_Int32, sal_Int32 >( nB, 0, MAX_PERCENT );
357 void Color::setHslClr( sal_Int32 nHue, sal_Int32 nSat, sal_Int32 nLum )
359 OSL_ENSURE( (0 <= nHue) && (nHue <= MAX_DEGREE), "Color::setHslClr - invalid hue value" );
360 OSL_ENSURE( (0 <= nSat) && (nSat <= MAX_PERCENT), "Color::setHslClr - invalid saturation value" );
361 OSL_ENSURE( (0 <= nLum) && (nLum <= MAX_PERCENT), "Color::setHslClr - invalid luminance value" );
362 meMode = COLOR_HSL;
363 mnC1 = getLimitedValue< sal_Int32, sal_Int32 >( nHue, 0, MAX_DEGREE );
364 mnC2 = getLimitedValue< sal_Int32, sal_Int32 >( nSat, 0, MAX_PERCENT );
365 mnC3 = getLimitedValue< sal_Int32, sal_Int32 >( nLum, 0, MAX_PERCENT );
368 void Color::setPrstClr( sal_Int32 nToken )
370 ::Color nRgbValue = getDmlPresetColor( nToken, API_RGB_TRANSPARENT );
371 OSL_ENSURE( sal_Int32(nRgbValue) >= 0, "Color::setPrstClr - invalid preset color token" );
372 if( sal_Int32(nRgbValue) >= 0 )
373 setSrgbClr( nRgbValue );
376 void Color::setHighlight(sal_Int32 nToken)
378 ::Color nRgbValue = getHighlightColor(nToken, API_RGB_TRANSPARENT);
379 OSL_ENSURE( sal_Int32(nRgbValue) >= 0, "Color::setPrstClr - invalid preset color token" );
380 if ( sal_Int32(nRgbValue) >= 0 )
381 setSrgbClr( nRgbValue );
384 void Color::setSchemeClr( sal_Int32 nToken )
386 OSL_ENSURE( nToken != XML_TOKEN_INVALID, "Color::setSchemeClr - invalid color token" );
387 meMode = (nToken == XML_phClr) ? COLOR_PH : COLOR_SCHEME;
388 mnC1 = nToken;
389 if (meMode == COLOR_SCHEME)
390 meThemeColorType = schemeTokenToThemeColorType(nToken);
393 void Color::setPaletteClr( sal_Int32 nPaletteIdx )
395 OSL_ENSURE( nPaletteIdx >= 0, "Color::setPaletteClr - invalid palette index" );
396 meMode = COLOR_PALETTE;
397 mnC1 = nPaletteIdx;
400 void Color::setSysClr( sal_Int32 nToken, sal_Int32 nLastRgb )
402 OSL_ENSURE( (-1 <= nLastRgb) && (nLastRgb <= 0xFFFFFF), "Color::setSysClr - invalid RGB value" );
403 meMode = COLOR_SYSTEM;
404 mnC1 = nToken;
405 mnC2 = nLastRgb;
408 void Color::addTransformation( sal_Int32 nElement, sal_Int32 nValue )
410 /* Execute alpha transformations directly, store other transformations in
411 a vector, they may depend on a scheme base color which will be resolved
412 in Color::getColor(). */
413 sal_Int32 nToken = getBaseToken( nElement );
414 switch( nToken )
416 case XML_alpha: lclSetValue( mnAlpha, nValue ); break;
417 case XML_alphaMod: lclModValue( mnAlpha, nValue ); break;
418 case XML_alphaOff: lclOffValue( mnAlpha, nValue ); break;
419 default: maTransforms.emplace_back( nToken, nValue );
421 sal_Int32 nSize = maInteropTransformations.getLength();
422 maInteropTransformations.realloc(nSize + 1);
423 auto pInteropTransformations = maInteropTransformations.getArray();
424 pInteropTransformations[nSize].Name = getColorTransformationName( nToken );
425 pInteropTransformations[nSize].Value <<= nValue;
428 void Color::addChartTintTransformation( double fTint )
430 sal_Int32 nValue = getLimitedValue< sal_Int32, double >( fTint * MAX_PERCENT + 0.5, -MAX_PERCENT, MAX_PERCENT );
431 if( nValue < 0 )
432 maTransforms.emplace_back( XML_shade, nValue + MAX_PERCENT );
433 else if( nValue > 0 )
434 maTransforms.emplace_back( XML_tint, MAX_PERCENT - nValue );
437 void Color::addExcelTintTransformation(double fTint)
439 sal_Int32 nValue = std::round(std::abs(fTint) * 100'000.0);
440 if (fTint > 0.0)
442 maTransforms.emplace_back(XML_lumMod, 100'000 - nValue);
443 maTransforms.emplace_back(XML_lumOff, nValue);
445 else if (fTint < 0.0)
447 maTransforms.emplace_back(XML_lumMod, 100'000 - nValue);
451 void Color::clearTransformations()
453 maTransforms.clear();
454 maInteropTransformations.realloc(0);
455 clearTransparence();
458 constexpr frozen::unordered_map<std::u16string_view, sal_Int32, 12> constColorMapTokenMap
459 = { { u"bg1", XML_bg1 }, { u"tx1", XML_tx1 }, { u"bg2", XML_bg2 },
460 { u"tx2", XML_tx2 }, { u"accent1", XML_accent1 }, { u"accent2", XML_accent2 },
461 { u"accent3", XML_accent3 }, { u"accent4", XML_accent4 }, { u"accent5", XML_accent5 },
462 { u"accent6", XML_accent6 }, { u"hlink", XML_hlink }, { u"folHlink", XML_folHlink } };
464 sal_Int32 Color::getColorMapToken(std::u16string_view sName)
466 auto aIterator = constColorMapTokenMap.find(sName);
467 if (aIterator == constColorMapTokenMap.end())
468 return XML_TOKEN_INVALID;
469 else
470 return aIterator->second;
473 OUString Color::getColorTransformationName( sal_Int32 nElement )
475 switch( nElement )
477 case XML_red: return u"red"_ustr;
478 case XML_redMod: return u"redMod"_ustr;
479 case XML_redOff: return u"redOff"_ustr;
480 case XML_green: return u"green"_ustr;
481 case XML_greenMod: return u"greenMod"_ustr;
482 case XML_greenOff: return u"greenOff"_ustr;
483 case XML_blue: return u"blue"_ustr;
484 case XML_blueMod: return u"blueMod"_ustr;
485 case XML_blueOff: return u"blueOff"_ustr;
486 case XML_alpha: return u"alpha"_ustr;
487 case XML_alphaMod: return u"alphaMod"_ustr;
488 case XML_alphaOff: return u"alphaOff"_ustr;
489 case XML_hue: return u"hue"_ustr;
490 case XML_hueMod: return u"hueMod"_ustr;
491 case XML_hueOff: return u"hueOff"_ustr;
492 case XML_sat: return u"sat"_ustr;
493 case XML_satMod: return u"satMod"_ustr;
494 case XML_satOff: return u"satOff"_ustr;
495 case XML_lum: return u"lum"_ustr;
496 case XML_lumMod: return u"lumMod"_ustr;
497 case XML_lumOff: return u"lumOff"_ustr;
498 case XML_shade: return u"shade"_ustr;
499 case XML_tint: return u"tint"_ustr;
500 case XML_gray: return u"gray"_ustr;
501 case XML_comp: return u"comp"_ustr;
502 case XML_inv: return u"inv"_ustr;
503 case XML_gamma: return u"gamma"_ustr;
504 case XML_invGamma: return u"invGamma"_ustr;
506 SAL_WARN( "oox.drawingml", "Color::getColorTransformationName - unexpected transformation type" );
507 return OUString();
510 sal_Int32 Color::getColorTransformationToken( std::u16string_view sName )
512 if( sName == u"red" )
513 return XML_red;
514 else if( sName == u"redMod" )
515 return XML_redMod;
516 else if( sName == u"redOff" )
517 return XML_redOff;
518 else if( sName == u"green" )
519 return XML_green;
520 else if( sName == u"greenMod" )
521 return XML_greenMod;
522 else if( sName == u"greenOff" )
523 return XML_greenOff;
524 else if( sName == u"blue" )
525 return XML_blue;
526 else if( sName == u"blueMod" )
527 return XML_blueMod;
528 else if( sName == u"blueOff" )
529 return XML_blueOff;
530 else if( sName == u"alpha" )
531 return XML_alpha;
532 else if( sName == u"alphaMod" )
533 return XML_alphaMod;
534 else if( sName == u"alphaOff" )
535 return XML_alphaOff;
536 else if( sName == u"hue" )
537 return XML_hue;
538 else if( sName == u"hueMod" )
539 return XML_hueMod;
540 else if( sName == u"hueOff" )
541 return XML_hueOff;
542 else if( sName == u"sat" )
543 return XML_sat;
544 else if( sName == u"satMod" )
545 return XML_satMod;
546 else if( sName == u"satOff" )
547 return XML_satOff;
548 else if( sName == u"lum" )
549 return XML_lum;
550 else if( sName == u"lumMod" )
551 return XML_lumMod;
552 else if( sName == u"lumOff" )
553 return XML_lumOff;
554 else if( sName == u"shade" )
555 return XML_shade;
556 else if( sName == u"tint" )
557 return XML_tint;
558 else if( sName == u"gray" )
559 return XML_gray;
560 else if( sName == u"comp" )
561 return XML_comp;
562 else if( sName == u"inv" )
563 return XML_inv;
564 else if( sName == u"gamma" )
565 return XML_gamma;
566 else if( sName == u"invGamma" )
567 return XML_invGamma;
569 SAL_WARN( "oox.drawingml", "Color::getColorTransformationToken - unexpected transformation type" );
570 return XML_TOKEN_INVALID;
573 bool Color::equals(const Color& rOther, const GraphicHelper& rGraphicHelper, ::Color nPhClr) const
575 if (getColor(rGraphicHelper, nPhClr) != rOther.getColor(rGraphicHelper, nPhClr))
576 return false;
578 return getTransparency() == rOther.getTransparency();
581 void Color::clearTransparence()
583 mnAlpha = MAX_PERCENT;
586 sal_Int16 Color::getTintOrShade() const
588 for(auto const& aTransform : maTransforms)
590 switch(aTransform.mnToken)
592 case XML_tint:
593 // from 1000th percent to 100th percent...
594 return aTransform.mnValue/10;
595 case XML_shade:
596 // from 1000th percent to 100th percent...
597 return -aTransform.mnValue/10;
600 return 0;
603 sal_Int16 Color::getLumMod() const
605 for (const auto& rTransform : maTransforms)
607 if (rTransform.mnToken != XML_lumMod)
609 continue;
612 // From 1000th percent to 100th percent.
613 return rTransform.mnValue / 10;
616 return 10000;
619 sal_Int16 Color::getLumOff() const
621 for (const auto& rTransform : maTransforms)
623 if (rTransform.mnToken != XML_lumOff)
625 continue;
628 // From 1000th percent to 100th percent.
629 return rTransform.mnValue / 10;
632 return 0;
635 model::ComplexColor Color::getComplexColor() const
637 auto aComplexColor = model::ComplexColor::Theme(model::convertToThemeColorType(getSchemeColorIndex()));
639 if (getTintOrShade() > 0)
641 aComplexColor.addTransformation({model::TransformationType::Tint, getTintOrShade()});
643 else if (getTintOrShade() < 0)
645 sal_Int16 nShade = o3tl::narrowing<sal_Int16>(-getTintOrShade());
646 aComplexColor.addTransformation({model::TransformationType::Shade, nShade});
649 if (getLumMod() != 10000)
650 aComplexColor.addTransformation({model::TransformationType::LumMod, getLumMod()});
652 if (getLumOff() != 0)
653 aComplexColor.addTransformation({model::TransformationType::LumOff, getLumOff()});
655 return aComplexColor;
658 ::Color Color::getColor( const GraphicHelper& rGraphicHelper, ::Color nPhClr ) const
660 const sal_Int32 nTempC1 = mnC1;
661 const sal_Int32 nTempC2 = mnC2;
662 const sal_Int32 nTempC3 = mnC3;
663 const ColorMode eTempMode = meMode;
665 switch( meMode )
667 case COLOR_UNUSED: mnC1 = sal_Int32(API_RGB_TRANSPARENT); break;
669 case COLOR_RGB: break; // nothing to do
670 case COLOR_CRGB: break; // nothing to do
671 case COLOR_HSL: break; // nothing to do
673 case COLOR_SCHEME: setResolvedRgb( rGraphicHelper.getSchemeColor( mnC1 ) ); break;
674 case COLOR_PALETTE: setResolvedRgb( rGraphicHelper.getPaletteColor( mnC1 ) ); break;
675 case COLOR_SYSTEM: setResolvedRgb( rGraphicHelper.getSystemColor( mnC1, ::Color(ColorTransparency, mnC2) ) ); break;
676 case COLOR_PH: setResolvedRgb( nPhClr ); break;
678 case COLOR_FINAL: return ::Color(ColorTransparency, mnC1);
681 // if color is UNUSED or turns to UNUSED in setResolvedRgb, do not perform transformations
682 if( meMode != COLOR_UNUSED )
684 for (auto const& transform : maTransforms)
686 switch( transform.mnToken )
688 case XML_red: toCrgb(); lclSetValue( mnC1, transform.mnValue ); break;
689 case XML_redMod: toCrgb(); lclModValue( mnC1, transform.mnValue ); break;
690 case XML_redOff: toCrgb(); lclOffValue( mnC1, transform.mnValue ); break;
691 case XML_green: toCrgb(); lclSetValue( mnC2, transform.mnValue ); break;
692 case XML_greenMod: toCrgb(); lclModValue( mnC2, transform.mnValue ); break;
693 case XML_greenOff: toCrgb(); lclOffValue( mnC2, transform.mnValue ); break;
694 case XML_blue: toCrgb(); lclSetValue( mnC3, transform.mnValue ); break;
695 case XML_blueMod: toCrgb(); lclModValue( mnC3, transform.mnValue ); break;
696 case XML_blueOff: toCrgb(); lclOffValue( mnC3, transform.mnValue ); break;
698 case XML_hue: toHsl(); lclSetValue( mnC1, transform.mnValue, MAX_DEGREE ); break;
699 case XML_hueMod: toHsl(); lclModValue( mnC1, transform.mnValue, MAX_DEGREE ); break;
700 case XML_hueOff: toHsl(); lclOffValue( mnC1, transform.mnValue, MAX_DEGREE ); break;
701 case XML_sat: toHsl(); lclSetValue( mnC2, transform.mnValue ); break;
702 case XML_satMod: toHsl(); lclModValue( mnC2, transform.mnValue ); break;
703 case XML_satOff: toHsl(); lclOffValue( mnC2, transform.mnValue ); break;
705 case XML_lum:
706 toHsl();
707 lclSetValue( mnC3, transform.mnValue );
708 // if color changes to black or white, it will stay gray if luminance changes again
709 if( (mnC3 == 0) || (mnC3 == MAX_PERCENT) ) mnC2 = 0;
710 break;
711 case XML_lumMod:
712 toHsl();
713 lclModValue( mnC3, transform.mnValue );
714 // if color changes to black or white, it will stay gray if luminance changes again
715 if( (mnC3 == 0) || (mnC3 == MAX_PERCENT) ) mnC2 = 0;
716 break;
717 case XML_lumOff:
718 toHsl();
719 lclOffValue( mnC3, transform.mnValue );
720 // if color changes to black or white, it will stay gray if luminance changes again
721 if( (mnC3 == 0) || (mnC3 == MAX_PERCENT) ) mnC2 = 0;
722 break;
724 case XML_shade:
725 // shade: 0% = black, 100% = original color
726 toCrgb();
727 OSL_ENSURE( (0 <= transform.mnValue) && (transform.mnValue <= MAX_PERCENT), "Color::getColor - invalid shade value" );
728 if( (0 <= transform.mnValue) && (transform.mnValue <= MAX_PERCENT) )
730 double fFactor = static_cast< double >( transform.mnValue ) / MAX_PERCENT;
731 mnC1 = static_cast< sal_Int32 >( mnC1 * fFactor );
732 mnC2 = static_cast< sal_Int32 >( mnC2 * fFactor );
733 mnC3 = static_cast< sal_Int32 >( mnC3 * fFactor );
735 break;
736 case XML_tint:
737 // tint: 0% = white, 100% = original color
738 toCrgb();
739 OSL_ENSURE( (0 <= transform.mnValue) && (transform.mnValue <= MAX_PERCENT), "Color::getColor - invalid tint value" );
740 if( (0 <= transform.mnValue) && (transform.mnValue <= MAX_PERCENT) )
742 double fFactor = static_cast< double >( transform.mnValue ) / MAX_PERCENT;
743 mnC1 = static_cast< sal_Int32 >( MAX_PERCENT - (MAX_PERCENT - mnC1) * fFactor );
744 mnC2 = static_cast< sal_Int32 >( MAX_PERCENT - (MAX_PERCENT - mnC2) * fFactor );
745 mnC3 = static_cast< sal_Int32 >( MAX_PERCENT - (MAX_PERCENT - mnC3) * fFactor );
747 break;
749 case XML_gray:
750 // change color to gray, weighted RGB: 22% red, 72% green, 6% blue
751 toRgb();
752 mnC1 = mnC2 = mnC3 = (mnC1 * 22 + mnC2 * 72 + mnC3 * 6) / 100;
753 break;
755 case XML_comp:
756 // comp: rotate hue by 180 degrees, do not change lum/sat
757 toHsl();
758 mnC1 = (mnC1 + (180 * PER_DEGREE)) % MAX_DEGREE;
759 break;
760 case XML_inv:
761 // invert percentual RGB values
762 toCrgb();
763 mnC1 = MAX_PERCENT - mnC1;
764 mnC2 = MAX_PERCENT - mnC2;
765 mnC3 = MAX_PERCENT - mnC3;
766 break;
768 case XML_gamma:
769 // increase gamma of color
770 toCrgb();
771 mnC1 = lclGamma( mnC1, INC_GAMMA );
772 mnC2 = lclGamma( mnC2, INC_GAMMA );
773 mnC3 = lclGamma( mnC3, INC_GAMMA );
774 break;
775 case XML_invGamma:
776 // decrease gamma of color
777 toCrgb();
778 mnC1 = lclGamma( mnC1, DEC_GAMMA );
779 mnC2 = lclGamma( mnC2, DEC_GAMMA );
780 mnC3 = lclGamma( mnC3, DEC_GAMMA );
781 break;
785 // store resulting RGB value in mnC1
786 toRgb();
787 mnC1 = lclRgbComponentsToRgb( mnC1, mnC2, mnC3 );
789 else // if( meMode != COLOR_UNUSED )
791 mnC1 = sal_Int32(API_RGB_TRANSPARENT);
794 sal_Int32 nRet = mnC1;
795 // Restore the original values when the color depends on one of the input
796 // parameters (rGraphicHelper or nPhClr)
797 if( eTempMode >= COLOR_SCHEME && eTempMode <= COLOR_PH )
799 mnC1 = nTempC1;
800 mnC2 = nTempC2;
801 mnC3 = nTempC3;
802 meMode = eTempMode;
804 else
806 meMode = COLOR_FINAL;
808 if( meMode == COLOR_FINAL )
809 maTransforms.clear();
810 return ::Color(ColorTransparency, nRet);
813 bool Color::hasTransparency() const
815 return mnAlpha < MAX_PERCENT;
818 sal_Int16 Color::getTransparency() const
820 return sal_Int16(std::round( (1.0 * (MAX_PERCENT - mnAlpha)) / PER_PERCENT) );
823 sal_Int16 Color::getSchemeColorIndex() const
825 auto eThemeType = schemeNameToThemeColorType(msSchemeName);
826 return sal_Int16(eThemeType);
829 model::ComplexColor Color::createComplexColor(const GraphicHelper& /*rGraphicHelper*/, sal_Int16 nPhClrTheme) const
831 model::ComplexColor aNewComplexColor;
832 if (meMode == COLOR_PH)
834 auto eTheme = model::convertToThemeColorType(nPhClrTheme);
835 aNewComplexColor.setThemeColor(eTheme);
837 else if (meMode == COLOR_SCHEME)
839 auto eTheme = getThemeColorType();
840 aNewComplexColor.setThemeColor(eTheme);
842 else if (meMode == COLOR_RGB)
844 ::Color aColor(ColorTransparency, lclRgbComponentsToRgb(mnC1, mnC2, mnC3));
845 aNewComplexColor = model::ComplexColor::createRGB(aColor);
847 else
849 // TODO - Add other options
850 return aNewComplexColor;
853 for(auto const& aTransform : maTransforms)
855 sal_Int16 nValue = sal_Int16(aTransform.mnValue / 10);
857 switch (aTransform.mnToken)
859 case XML_lumMod:
860 if (nValue != 10'000)
861 aNewComplexColor.addTransformation({model::TransformationType::LumMod, nValue});
862 break;
863 case XML_lumOff:
864 if (nValue != 0)
865 aNewComplexColor.addTransformation({model::TransformationType::LumOff, nValue});
866 break;
867 case XML_tint:
868 if (nValue != 0)
869 aNewComplexColor.addTransformation({model::TransformationType::Tint, nValue});
870 break;
871 case XML_shade:
872 if (nValue != 0)
873 aNewComplexColor.addTransformation({model::TransformationType::Shade, nValue});
874 break;
878 return aNewComplexColor;
881 // private --------------------------------------------------------------------
883 void Color::setResolvedRgb( ::Color nRgb ) const
885 meMode = (sal_Int32(nRgb) < 0) ? COLOR_UNUSED : COLOR_RGB;
886 lclRgbToRgbComponents( mnC1, mnC2, mnC3, nRgb );
889 void Color::toRgb() const
891 switch( meMode )
893 case COLOR_RGB:
894 // nothing to do
895 break;
896 case COLOR_CRGB:
897 meMode = COLOR_RGB;
898 mnC1 = lclCrgbCompToRgbComp( lclGamma( mnC1, INC_GAMMA ) );
899 mnC2 = lclCrgbCompToRgbComp( lclGamma( mnC2, INC_GAMMA ) );
900 mnC3 = lclCrgbCompToRgbComp( lclGamma( mnC3, INC_GAMMA ) );
901 break;
902 case COLOR_HSL:
904 meMode = COLOR_RGB;
905 double fR = 0.0, fG = 0.0, fB = 0.0;
906 if( (mnC2 == 0) || (mnC3 == MAX_PERCENT) )
908 fR = fG = fB = static_cast< double >( mnC3 ) / MAX_PERCENT;
910 else if( mnC3 > 0 )
912 // base color from hue
913 double fHue = static_cast< double >( mnC1 ) / MAX_DEGREE * 6.0; // interval [0.0, 6.0)
914 if( fHue <= 1.0 ) { fR = 1.0; fG = fHue; } // red...yellow
915 else if( fHue <= 2.0 ) { fR = 2.0 - fHue; fG = 1.0; } // yellow...green
916 else if( fHue <= 3.0 ) { fG = 1.0; fB = fHue - 2.0; } // green...cyan
917 else if( fHue <= 4.0 ) { fG = 4.0 - fHue; fB = 1.0; } // cyan...blue
918 else if( fHue <= 5.0 ) { fR = fHue - 4.0; fB = 1.0; } // blue...magenta
919 else { fR = 1.0; fB = 6.0 - fHue; } // magenta...red
921 // apply saturation
922 double fSat = static_cast< double >( mnC2 ) / MAX_PERCENT;
923 fR = (fR - 0.5) * fSat + 0.5;
924 fG = (fG - 0.5) * fSat + 0.5;
925 fB = (fB - 0.5) * fSat + 0.5;
927 // apply luminance
928 double fLum = 2.0 * static_cast< double >( mnC3 ) / MAX_PERCENT - 1.0; // interval [-1.0, 1.0]
929 if( fLum < 0.0 )
931 double fShade = fLum + 1.0; // interval [0.0, 1.0] (black...full color)
932 fR *= fShade;
933 fG *= fShade;
934 fB *= fShade;
936 else if( fLum > 0.0 )
938 double fTint = 1.0 - fLum; // interval [0.0, 1.0] (white...full color)
939 fR = 1.0 - ((1.0 - fR) * fTint);
940 fG = 1.0 - ((1.0 - fG) * fTint);
941 fB = 1.0 - ((1.0 - fB) * fTint);
944 mnC1 = static_cast< sal_Int32 >( fR * 255.0 + 0.5 );
945 mnC2 = static_cast< sal_Int32 >( fG * 255.0 + 0.5 );
946 mnC3 = static_cast< sal_Int32 >( fB * 255.0 + 0.5 );
948 break;
949 default:
950 OSL_FAIL( "Color::toRgb - unexpected color mode" );
954 void Color::toCrgb() const
956 switch( meMode )
958 case COLOR_HSL:
959 toRgb();
960 [[fallthrough]];
961 case COLOR_RGB:
962 meMode = COLOR_CRGB;
963 mnC1 = lclGamma( lclRgbCompToCrgbComp( mnC1 ), DEC_GAMMA );
964 mnC2 = lclGamma( lclRgbCompToCrgbComp( mnC2 ), DEC_GAMMA );
965 mnC3 = lclGamma( lclRgbCompToCrgbComp( mnC3 ), DEC_GAMMA );
966 break;
967 case COLOR_CRGB:
968 // nothing to do
969 break;
970 default:
971 OSL_FAIL( "Color::toCrgb - unexpected color mode" );
975 void Color::toHsl() const
977 switch( meMode )
979 case COLOR_CRGB:
980 toRgb();
981 [[fallthrough]];
982 case COLOR_RGB:
984 meMode = COLOR_HSL;
985 double fR = static_cast< double >( mnC1 ) / 255.0; // red [0.0, 1.0]
986 double fG = static_cast< double >( mnC2 ) / 255.0; // green [0.0, 1.0]
987 double fB = static_cast< double >( mnC3 ) / 255.0; // blue [0.0, 1.0]
988 double fMin = ::std::min( ::std::min( fR, fG ), fB );
989 double fMax = ::std::max( ::std::max( fR, fG ), fB );
990 double fD = fMax - fMin;
992 using ::rtl::math::approxEqual;
994 // hue: 0deg = red, 120deg = green, 240deg = blue
995 if( fD == 0.0 ) // black/gray/white
996 mnC1 = 0;
997 else if( approxEqual(fMax, fR, 64) ) // magenta...red...yellow
998 mnC1 = static_cast< sal_Int32 >( ((fG - fB) / fD * 60.0 + 360.0) * PER_DEGREE + 0.5 ) % MAX_DEGREE;
999 else if( approxEqual(fMax, fG, 64) ) // yellow...green...cyan
1000 mnC1 = static_cast< sal_Int32 >( ((fB - fR) / fD * 60.0 + 120.0) * PER_DEGREE + 0.5 );
1001 else // cyan...blue...magenta
1002 mnC1 = static_cast< sal_Int32 >( ((fR - fG) / fD * 60.0 + 240.0) * PER_DEGREE + 0.5 );
1004 // luminance: 0% = black, 50% = full color, 100% = white
1005 mnC3 = static_cast< sal_Int32 >( (fMin + fMax) / 2.0 * MAX_PERCENT + 0.5 );
1007 // saturation: 0% = gray, 100% = full color
1008 if( (mnC3 == 0) || (mnC3 == MAX_PERCENT) ) // black/white
1009 mnC2 = 0;
1010 else if( mnC3 <= 50 * PER_PERCENT ) // dark...full color
1011 mnC2 = static_cast< sal_Int32 >( fD / (fMin + fMax) * MAX_PERCENT + 0.5 );
1012 else // full color...light
1013 mnC2 = static_cast< sal_Int32 >( fD / (2.0 - fMax - fMin) * MAX_PERCENT + 0.5 );
1015 break;
1016 case COLOR_HSL:
1017 // nothing to do
1018 break;
1019 default:
1020 OSL_FAIL( "Color::toHsl - unexpected color mode" );
1024 } // namespace oox
1026 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */