1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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"
23 #include <osl/diagnose.h>
24 #include "oox/helper/containerhelper.hxx"
25 #include "oox/helper/graphichelper.hxx"
26 #include "oox/drawingml/drawingmltypes.hxx"
27 #include "oox/token/namespaces.hxx"
28 #include "oox/token/tokens.hxx"
35 /** Global storage for predefined color values used in OOXML file formats. */
36 struct PresetColorsPool
38 typedef ::std::vector
< sal_Int32
> ColorVector
;
40 ColorVector maDmlColors
; /// Predefined colors in DrawingML, indexed by XML token.
41 ColorVector maVmlColors
; /// Predefined colors in VML, indexed by XML token.
43 explicit PresetColorsPool();
46 PresetColorsPool::PresetColorsPool() :
47 maDmlColors( static_cast< size_t >( XML_TOKEN_COUNT
), API_RGB_TRANSPARENT
),
48 maVmlColors( static_cast< size_t >( XML_TOKEN_COUNT
), API_RGB_TRANSPARENT
)
50 // predefined colors in DrawingML (map XML token identifiers to RGB values)
51 static const sal_Int32 spnDmlColors
[] =
53 XML_aliceBlue
, 0xF0F8FF, XML_antiqueWhite
, 0xFAEBD7,
54 XML_aqua
, 0x00FFFF, XML_aquamarine
, 0x7FFFD4,
55 XML_azure
, 0xF0FFFF, XML_beige
, 0xF5F5DC,
56 XML_bisque
, 0xFFE4C4, XML_black
, 0x000000,
57 XML_blanchedAlmond
, 0xFFEBCD, XML_blue
, 0x0000FF,
58 XML_blueViolet
, 0x8A2BE2, XML_brown
, 0xA52A2A,
59 XML_burlyWood
, 0xDEB887, XML_cadetBlue
, 0x5F9EA0,
60 XML_chartreuse
, 0x7FFF00, XML_chocolate
, 0xD2691E,
61 XML_coral
, 0xFF7F50, XML_cornflowerBlue
, 0x6495ED,
62 XML_cornsilk
, 0xFFF8DC, XML_crimson
, 0xDC143C,
63 XML_cyan
, 0x00FFFF, XML_deepPink
, 0xFF1493,
64 XML_deepSkyBlue
, 0x00BFFF, XML_dimGray
, 0x696969,
65 XML_dkBlue
, 0x00008B, XML_dkCyan
, 0x008B8B,
66 XML_dkGoldenrod
, 0xB8860B, XML_dkGray
, 0xA9A9A9,
67 XML_dkGreen
, 0x006400, XML_dkKhaki
, 0xBDB76B,
68 XML_dkMagenta
, 0x8B008B, XML_dkOliveGreen
, 0x556B2F,
69 XML_dkOrange
, 0xFF8C00, XML_dkOrchid
, 0x9932CC,
70 XML_dkRed
, 0x8B0000, XML_dkSalmon
, 0xE9967A,
71 XML_dkSeaGreen
, 0x8FBC8B, XML_dkSlateBlue
, 0x483D8B,
72 XML_dkSlateGray
, 0x2F4F4F, XML_dkTurquoise
, 0x00CED1,
73 XML_dkViolet
, 0x9400D3, XML_dodgerBlue
, 0x1E90FF,
74 XML_firebrick
, 0xB22222, XML_floralWhite
, 0xFFFAF0,
75 XML_forestGreen
, 0x228B22, XML_fuchsia
, 0xFF00FF,
76 XML_gainsboro
, 0xDCDCDC, XML_ghostWhite
, 0xF8F8FF,
77 XML_gold
, 0xFFD700, XML_goldenrod
, 0xDAA520,
78 XML_gray
, 0x808080, XML_green
, 0x008000,
79 XML_greenYellow
, 0xADFF2F, XML_honeydew
, 0xF0FFF0,
80 XML_hotPink
, 0xFF69B4, XML_indianRed
, 0xCD5C5C,
81 XML_indigo
, 0x4B0082, XML_ivory
, 0xFFFFF0,
82 XML_khaki
, 0xF0E68C, XML_lavender
, 0xE6E6FA,
83 XML_lavenderBlush
, 0xFFF0F5, XML_lawnGreen
, 0x7CFC00,
84 XML_lemonChiffon
, 0xFFFACD, XML_lime
, 0x00FF00,
85 XML_limeGreen
, 0x32CD32, XML_linen
, 0xFAF0E6,
86 XML_ltBlue
, 0xADD8E6, XML_ltCoral
, 0xF08080,
87 XML_ltCyan
, 0xE0FFFF, XML_ltGoldenrodYellow
, 0xFAFA78,
88 XML_ltGray
, 0xD3D3D3, XML_ltGreen
, 0x90EE90,
89 XML_ltPink
, 0xFFB6C1, XML_ltSalmon
, 0xFFA07A,
90 XML_ltSeaGreen
, 0x20B2AA, XML_ltSkyBlue
, 0x87CEFA,
91 XML_ltSlateGray
, 0x778899, XML_ltSteelBlue
, 0xB0C4DE,
92 XML_ltYellow
, 0xFFFFE0, XML_magenta
, 0xFF00FF,
93 XML_maroon
, 0x800000, XML_medAquamarine
, 0x66CDAA,
94 XML_medBlue
, 0x0000CD, XML_medOrchid
, 0xBA55D3,
95 XML_medPurple
, 0x9370DB, XML_medSeaGreen
, 0x3CB371,
96 XML_medSlateBlue
, 0x7B68EE, XML_medSpringGreen
, 0x00FA9A,
97 XML_medTurquoise
, 0x48D1CC, XML_medVioletRed
, 0xC71585,
98 XML_midnightBlue
, 0x191970, XML_mintCream
, 0xF5FFFA,
99 XML_mistyRose
, 0xFFE4E1, XML_moccasin
, 0xFFE4B5,
100 XML_navajoWhite
, 0xFFDEAD, XML_navy
, 0x000080,
101 XML_oldLace
, 0xFDF5E6, XML_olive
, 0x808000,
102 XML_oliveDrab
, 0x6B8E23, XML_orange
, 0xFFA500,
103 XML_orangeRed
, 0xFF4500, XML_orchid
, 0xDA70D6,
104 XML_paleGoldenrod
, 0xEEE8AA, XML_paleGreen
, 0x98FB98,
105 XML_paleTurquoise
, 0xAFEEEE, XML_paleVioletRed
, 0xDB7093,
106 XML_papayaWhip
, 0xFFEFD5, XML_peachPuff
, 0xFFDAB9,
107 XML_peru
, 0xCD853F, XML_pink
, 0xFFC0CB,
108 XML_plum
, 0xDDA0DD, XML_powderBlue
, 0xB0E0E6,
109 XML_purple
, 0x800080, XML_red
, 0xFF0000,
110 XML_rosyBrown
, 0xBC8F8F, XML_royalBlue
, 0x4169E1,
111 XML_saddleBrown
, 0x8B4513, XML_salmon
, 0xFA8072,
112 XML_sandyBrown
, 0xF4A460, XML_seaGreen
, 0x2E8B57,
113 XML_seaShell
, 0xFFF5EE, XML_sienna
, 0xA0522D,
114 XML_silver
, 0xC0C0C0, XML_skyBlue
, 0x87CEEB,
115 XML_slateBlue
, 0x6A5ACD, XML_slateGray
, 0x708090,
116 XML_snow
, 0xFFFAFA, XML_springGreen
, 0x00FF7F,
117 XML_steelBlue
, 0x4682B4, XML_tan
, 0xD2B48C,
118 XML_teal
, 0x008080, XML_thistle
, 0xD8BFD8,
119 XML_tomato
, 0xFF6347, XML_turquoise
, 0x40E0D0,
120 XML_violet
, 0xEE82EE, XML_wheat
, 0xF5DEB3,
121 XML_white
, 0xFFFFFF, XML_whiteSmoke
, 0xF5F5F5,
122 XML_yellow
, 0xFFFF00, XML_yellowGreen
, 0x9ACD32
124 for( const sal_Int32
* pnEntry
= spnDmlColors
; pnEntry
< STATIC_ARRAY_END( spnDmlColors
); pnEntry
+= 2 )
125 maDmlColors
[ static_cast< size_t >( pnEntry
[ 0 ] ) ] = pnEntry
[ 1 ];
127 // predefined colors in VML (map XML token identifiers to RGB values)
128 static const sal_Int32 spnVmlColors
[] =
130 XML_aqua
, 0x00FFFF, XML_black
, 0x000000,
131 XML_blue
, 0x0000FF, XML_fuchsia
, 0xFF00FF,
132 XML_gray
, 0x808080, XML_green
, 0x008000,
133 XML_lime
, 0x00FF00, XML_maroon
, 0x800000,
134 XML_navy
, 0x000080, XML_olive
, 0x808000,
135 XML_purple
, 0x800080, XML_red
, 0xFF0000,
136 XML_silver
, 0xC0C0C0, XML_teal
, 0x008080,
137 XML_white
, 0xFFFFFF, XML_yellow
, 0xFFFF00
139 for( const sal_Int32
* pnEntry
= spnVmlColors
; pnEntry
< STATIC_ARRAY_END( spnVmlColors
); pnEntry
+= 2 )
140 maVmlColors
[ static_cast< size_t >( pnEntry
[ 0 ] ) ] = pnEntry
[ 1 ];
143 struct StaticPresetColorsPool
: public ::rtl::Static
< PresetColorsPool
, StaticPresetColorsPool
> {};
145 const double DEC_GAMMA
= 2.3;
146 const double INC_GAMMA
= 1.0 / DEC_GAMMA
;
148 inline void lclRgbToRgbComponents( sal_Int32
& ornR
, sal_Int32
& ornG
, sal_Int32
& ornB
, sal_Int32 nRgb
)
150 ornR
= (nRgb
>> 16) & 0xFF;
151 ornG
= (nRgb
>> 8) & 0xFF;
155 inline sal_Int32
lclRgbComponentsToRgb( sal_Int32 nR
, sal_Int32 nG
, sal_Int32 nB
)
157 return static_cast< sal_Int32
>( (nR
<< 16) | (nG
<< 8) | nB
);
160 inline sal_Int32
lclRgbCompToCrgbComp( sal_Int32 nRgbComp
)
162 return static_cast< sal_Int32
>( nRgbComp
* MAX_PERCENT
/ 255 );
165 inline sal_Int32
lclCrgbCompToRgbComp( sal_Int32 nCrgbComp
)
167 return static_cast< sal_Int32
>( nCrgbComp
* 255 / MAX_PERCENT
);
170 inline sal_Int32
lclGamma( sal_Int32 nComp
, double fGamma
)
172 return static_cast< sal_Int32
>( pow( static_cast< double >( nComp
) / MAX_PERCENT
, fGamma
) * MAX_PERCENT
+ 0.5 );
175 void lclSetValue( sal_Int32
& ornValue
, sal_Int32 nNew
, sal_Int32 nMax
= MAX_PERCENT
)
177 OSL_ENSURE( (0 <= nNew
) && (nNew
<= nMax
), "lclSetValue - invalid value" );
178 if( (0 <= nNew
) && (nNew
<= nMax
) )
182 void lclModValue( sal_Int32
& ornValue
, sal_Int32 nMod
, sal_Int32 nMax
= MAX_PERCENT
)
184 OSL_ENSURE( (0 <= nMod
), "lclModValue - invalid modificator" );
185 ornValue
= getLimitedValue
< sal_Int32
, double >( static_cast< double >( ornValue
) * nMod
/ MAX_PERCENT
, 0, nMax
);
188 void lclOffValue( sal_Int32
& ornValue
, sal_Int32 nOff
, sal_Int32 nMax
= MAX_PERCENT
)
190 OSL_ENSURE( (-nMax
<= nOff
) && (nOff
<= nMax
), "lclOffValue - invalid offset" );
191 ornValue
= getLimitedValue
< sal_Int32
, sal_Int32
>( ornValue
+ nOff
, 0, nMax
);
197 meMode( COLOR_UNUSED
),
201 mnAlpha( MAX_PERCENT
)
209 sal_Int32
Color::getDmlPresetColor( sal_Int32 nToken
, sal_Int32 nDefaultRgb
)
211 /* Do not pass nDefaultRgb to ContainerHelper::getVectorElement(), to be
212 able to catch the existing vector entries without corresponding XML
214 sal_Int32 nRgbValue
= ContainerHelper::getVectorElement( StaticPresetColorsPool::get().maDmlColors
, nToken
, API_RGB_TRANSPARENT
);
215 return (nRgbValue
>= 0) ? nRgbValue
: nDefaultRgb
;
218 sal_Int32
Color::getVmlPresetColor( sal_Int32 nToken
, sal_Int32 nDefaultRgb
)
220 /* Do not pass nDefaultRgb to ContainerHelper::getVectorElement(), to be
221 able to catch the existing vector entries without corresponding XML
223 sal_Int32 nRgbValue
= ContainerHelper::getVectorElement( StaticPresetColorsPool::get().maVmlColors
, nToken
, API_RGB_TRANSPARENT
);
224 return (nRgbValue
>= 0) ? nRgbValue
: nDefaultRgb
;
227 void Color::setUnused()
229 meMode
= COLOR_UNUSED
;
232 void Color::setSrgbClr( sal_Int32 nRgb
)
234 OSL_ENSURE( (0 <= nRgb
) && (nRgb
<= 0xFFFFFF), "Color::setSrgbClr - invalid RGB value" );
236 lclRgbToRgbComponents( mnC1
, mnC2
, mnC3
, nRgb
);
239 void Color::setScrgbClr( sal_Int32 nR
, sal_Int32 nG
, sal_Int32 nB
)
241 OSL_ENSURE( (0 <= nR
) && (nR
<= MAX_PERCENT
), "Color::setScrgbClr - invalid red value" );
242 OSL_ENSURE( (0 <= nG
) && (nG
<= MAX_PERCENT
), "Color::setScrgbClr - invalid green value" );
243 OSL_ENSURE( (0 <= nB
) && (nB
<= MAX_PERCENT
), "Color::setScrgbClr - invalid blue value" );
245 mnC1
= getLimitedValue
< sal_Int32
, sal_Int32
>( nR
, 0, MAX_PERCENT
);
246 mnC2
= getLimitedValue
< sal_Int32
, sal_Int32
>( nG
, 0, MAX_PERCENT
);
247 mnC3
= getLimitedValue
< sal_Int32
, sal_Int32
>( nB
, 0, MAX_PERCENT
);
250 void Color::setHslClr( sal_Int32 nHue
, sal_Int32 nSat
, sal_Int32 nLum
)
252 OSL_ENSURE( (0 <= nHue
) && (nHue
<= MAX_DEGREE
), "Color::setHslClr - invalid hue value" );
253 OSL_ENSURE( (0 <= nSat
) && (nSat
<= MAX_PERCENT
), "Color::setHslClr - invalid saturation value" );
254 OSL_ENSURE( (0 <= nLum
) && (nLum
<= MAX_PERCENT
), "Color::setHslClr - invalid luminance value" );
256 mnC1
= getLimitedValue
< sal_Int32
, sal_Int32
>( nHue
, 0, MAX_DEGREE
);
257 mnC2
= getLimitedValue
< sal_Int32
, sal_Int32
>( nSat
, 0, MAX_PERCENT
);
258 mnC3
= getLimitedValue
< sal_Int32
, sal_Int32
>( nLum
, 0, MAX_PERCENT
);
261 void Color::setPrstClr( sal_Int32 nToken
)
263 sal_Int32 nRgbValue
= getDmlPresetColor( nToken
, API_RGB_TRANSPARENT
);
264 OSL_ENSURE( nRgbValue
>= 0, "Color::setPrstClr - invalid preset color token" );
266 setSrgbClr( nRgbValue
);
269 void Color::setSchemeClr( sal_Int32 nToken
)
271 OSL_ENSURE( nToken
!= XML_TOKEN_INVALID
, "Color::setSchemeClr - invalid color token" );
272 meMode
= (nToken
== XML_phClr
) ? COLOR_PH
: COLOR_SCHEME
;
276 void Color::setPaletteClr( sal_Int32 nPaletteIdx
)
278 OSL_ENSURE( nPaletteIdx
>= 0, "Color::setPaletteClr - invalid palette index" );
279 meMode
= COLOR_PALETTE
;
283 void Color::setSysClr( sal_Int32 nToken
, sal_Int32 nLastRgb
)
285 OSL_ENSURE( (-1 <= nLastRgb
) && (nLastRgb
<= 0xFFFFFF), "Color::setSysClr - invalid RGB value" );
286 meMode
= COLOR_SYSTEM
;
291 void Color::addTransformation( sal_Int32 nElement
, sal_Int32 nValue
)
293 /* Execute alpha transformations directly, store other transformations in
294 a vector, they may depend on a scheme base color which will be resolved
295 in Color::getColor(). */
296 sal_Int32 nToken
= getBaseToken( nElement
);
299 case XML_alpha
: lclSetValue( mnAlpha
, nValue
); break;
300 case XML_alphaMod
: lclModValue( mnAlpha
, nValue
); break;
301 case XML_alphaOff
: lclOffValue( mnAlpha
, nValue
); break;
302 default: maTransforms
.push_back( Transformation( nToken
, nValue
) );
304 sal_Int32 nSize
= maInteropTransformations
.getLength();
305 maInteropTransformations
.realloc(nSize
+ 1);
306 maInteropTransformations
[nSize
].Name
= getColorTransformationName( nToken
);
307 maInteropTransformations
[nSize
].Value
= ::com::sun::star::uno::Any( nValue
);
310 void Color::addChartTintTransformation( double fTint
)
312 sal_Int32 nValue
= getLimitedValue
< sal_Int32
, double >( fTint
* MAX_PERCENT
+ 0.5, -MAX_PERCENT
, MAX_PERCENT
);
314 maTransforms
.push_back( Transformation( XML_shade
, nValue
+ MAX_PERCENT
) );
315 else if( nValue
> 0 )
316 maTransforms
.push_back( Transformation( XML_tint
, MAX_PERCENT
- nValue
) );
319 void Color::addExcelTintTransformation( double fTint
)
321 sal_Int32 nValue
= getLimitedValue
< sal_Int32
, double >( fTint
* MAX_PERCENT
+ 0.5, -MAX_PERCENT
, MAX_PERCENT
);
322 maTransforms
.push_back( Transformation( XLS_TOKEN( tint
), nValue
) );
325 void Color::clearTransformations()
327 maTransforms
.clear();
328 maInteropTransformations
.realloc(0);
332 OUString
Color::getColorTransformationName( sal_Int32 nElement
)
336 case XML_red
: return OUString( "red" );
337 case XML_redMod
: return OUString( "redMod" );
338 case XML_redOff
: return OUString( "redOff" );
339 case XML_green
: return OUString( "green" );
340 case XML_greenMod
: return OUString( "greenMod" );
341 case XML_greenOff
: return OUString( "greenOff" );
342 case XML_blue
: return OUString( "blue" );
343 case XML_blueMod
: return OUString( "blueMod" );
344 case XML_blueOff
: return OUString( "blueOff" );
345 case XML_alpha
: return OUString( "alpha" );
346 case XML_alphaMod
: return OUString( "alphaMod" );
347 case XML_alphaOff
: return OUString( "alphaOff" );
348 case XML_hue
: return OUString( "hue" );
349 case XML_hueMod
: return OUString( "hueMod" );
350 case XML_hueOff
: return OUString( "hueOff" );
351 case XML_sat
: return OUString( "sat" );
352 case XML_satMod
: return OUString( "satMod" );
353 case XML_satOff
: return OUString( "satOff" );
354 case XML_lum
: return OUString( "lum" );
355 case XML_lumMod
: return OUString( "lumMod" );
356 case XML_lumOff
: return OUString( "lumOff" );
357 case XML_shade
: return OUString( "shade" );
358 case XML_tint
: return OUString( "tint" );
359 case XML_gray
: return OUString( "gray" );
360 case XML_comp
: return OUString( "comp" );
361 case XML_inv
: return OUString( "inv" );
362 case XML_gamma
: return OUString( "gamma" );
363 case XML_invGamma
: return OUString( "invGamma" );
365 SAL_WARN( "oox.drawingml", "Color::getColorTransformationName - unexpected transformation type" );
369 sal_Int32
Color::getColorTransformationToken( const OUString
& sName
)
373 else if( sName
== "redMod" )
375 else if( sName
== "redOff" )
377 else if( sName
== "green" )
379 else if( sName
== "greenMod" )
381 else if( sName
== "greenOff" )
383 else if( sName
== "blue" )
385 else if( sName
== "blueMod" )
387 else if( sName
== "blueOff" )
389 else if( sName
== "alpha" )
391 else if( sName
== "alphaMod" )
393 else if( sName
== "alphaOff" )
395 else if( sName
== "hue" )
397 else if( sName
== "hueMod" )
399 else if( sName
== "hueOff" )
401 else if( sName
== "sat" )
403 else if( sName
== "satMod" )
405 else if( sName
== "satOff" )
407 else if( sName
== "lum" )
409 else if( sName
== "lumMod" )
411 else if( sName
== "lumOff" )
413 else if( sName
== "shade" )
415 else if( sName
== "tint" )
417 else if( sName
== "gray" )
419 else if( sName
== "comp" )
421 else if( sName
== "inv" )
423 else if( sName
== "gamma" )
425 else if( sName
== "invGamma" )
428 SAL_WARN( "oox.drawingml", "Color::getColorTransformationToken - unexpected transformation type" );
429 return XML_TOKEN_INVALID
;
432 void Color::clearTransparence()
434 mnAlpha
= MAX_PERCENT
;
437 sal_Int32
Color::getColor( const GraphicHelper
& rGraphicHelper
, sal_Int32 nPhClr
) const
439 const sal_Int32 nTempC1
= mnC1
;
440 const sal_Int32 nTempC2
= mnC2
;
441 const sal_Int32 nTempC3
= mnC3
;
442 const ColorMode eTempMode
= meMode
;
446 case COLOR_UNUSED
: mnC1
= API_RGB_TRANSPARENT
; break;
448 case COLOR_RGB
: break; // nothing to do
449 case COLOR_CRGB
: break; // nothing to do
450 case COLOR_HSL
: break; // nothing to do
452 case COLOR_SCHEME
: setResolvedRgb( rGraphicHelper
.getSchemeColor( mnC1
) ); break;
453 case COLOR_PALETTE
: setResolvedRgb( rGraphicHelper
.getPaletteColor( mnC1
) ); break;
454 case COLOR_SYSTEM
: setResolvedRgb( rGraphicHelper
.getSystemColor( mnC1
, mnC2
) ); break;
455 case COLOR_PH
: setResolvedRgb( nPhClr
); break;
457 case COLOR_FINAL
: return mnC1
;
460 // if color is UNUSED or turns to UNUSED in setResolvedRgb, do not perform transformations
461 if( meMode
!= COLOR_UNUSED
)
463 for( TransformVec::const_iterator aIt
= maTransforms
.begin(), aEnd
= maTransforms
.end(); aIt
!= aEnd
; ++aIt
)
465 switch( aIt
->mnToken
)
467 case XML_red
: toCrgb(); lclSetValue( mnC1
, aIt
->mnValue
); break;
468 case XML_redMod
: toCrgb(); lclModValue( mnC1
, aIt
->mnValue
); break;
469 case XML_redOff
: toCrgb(); lclOffValue( mnC1
, aIt
->mnValue
); break;
470 case XML_green
: toCrgb(); lclSetValue( mnC2
, aIt
->mnValue
); break;
471 case XML_greenMod
: toCrgb(); lclModValue( mnC2
, aIt
->mnValue
); break;
472 case XML_greenOff
: toCrgb(); lclOffValue( mnC2
, aIt
->mnValue
); break;
473 case XML_blue
: toCrgb(); lclSetValue( mnC3
, aIt
->mnValue
); break;
474 case XML_blueMod
: toCrgb(); lclModValue( mnC3
, aIt
->mnValue
); break;
475 case XML_blueOff
: toCrgb(); lclOffValue( mnC3
, aIt
->mnValue
); break;
477 case XML_hue
: toHsl(); lclSetValue( mnC1
, aIt
->mnValue
, MAX_DEGREE
); break;
478 case XML_hueMod
: toHsl(); lclModValue( mnC1
, aIt
->mnValue
, MAX_DEGREE
); break;
479 case XML_hueOff
: toHsl(); lclOffValue( mnC1
, aIt
->mnValue
, MAX_DEGREE
); break;
480 case XML_sat
: toHsl(); lclSetValue( mnC2
, aIt
->mnValue
); break;
481 case XML_satMod
: toHsl(); lclModValue( mnC2
, aIt
->mnValue
); break;
482 case XML_satOff
: toHsl(); lclOffValue( mnC2
, aIt
->mnValue
); break;
486 lclSetValue( mnC3
, aIt
->mnValue
);
487 // if color changes to black or white, it will stay gray if luminance changes again
488 if( (mnC3
== 0) || (mnC3
== MAX_PERCENT
) ) mnC2
= 0;
492 lclModValue( mnC3
, aIt
->mnValue
);
493 // if color changes to black or white, it will stay gray if luminance changes again
494 if( (mnC3
== 0) || (mnC3
== MAX_PERCENT
) ) mnC2
= 0;
498 lclOffValue( mnC3
, aIt
->mnValue
);
499 // if color changes to black or white, it will stay gray if luminance changes again
500 if( (mnC3
== 0) || (mnC3
== MAX_PERCENT
) ) mnC2
= 0;
504 // shade: 0% = black, 100% = original color
506 OSL_ENSURE( (0 <= aIt
->mnValue
) && (aIt
->mnValue
<= MAX_PERCENT
), "Color::getColor - invalid shade value" );
507 if( (0 <= aIt
->mnValue
) && (aIt
->mnValue
<= MAX_PERCENT
) )
509 double fFactor
= static_cast< double >( aIt
->mnValue
) / MAX_PERCENT
;
510 mnC1
= static_cast< sal_Int32
>( mnC1
* fFactor
);
511 mnC2
= static_cast< sal_Int32
>( mnC2
* fFactor
);
512 mnC3
= static_cast< sal_Int32
>( mnC3
* fFactor
);
516 // tint: 0% = white, 100% = original color
518 OSL_ENSURE( (0 <= aIt
->mnValue
) && (aIt
->mnValue
<= MAX_PERCENT
), "Color::getColor - invalid tint value" );
519 if( (0 <= aIt
->mnValue
) && (aIt
->mnValue
<= MAX_PERCENT
) )
521 double fFactor
= static_cast< double >( aIt
->mnValue
) / MAX_PERCENT
;
522 mnC1
= static_cast< sal_Int32
>( MAX_PERCENT
- (MAX_PERCENT
- mnC1
) * fFactor
);
523 mnC2
= static_cast< sal_Int32
>( MAX_PERCENT
- (MAX_PERCENT
- mnC2
) * fFactor
);
524 mnC3
= static_cast< sal_Int32
>( MAX_PERCENT
- (MAX_PERCENT
- mnC3
) * fFactor
);
527 case XLS_TOKEN( tint
):
528 // Excel tint: move luminance relative to current value
530 OSL_ENSURE( (-MAX_PERCENT
<= aIt
->mnValue
) && (aIt
->mnValue
<= MAX_PERCENT
), "Color::getColor - invalid tint value" );
531 if( (-MAX_PERCENT
<= aIt
->mnValue
) && (aIt
->mnValue
< 0) )
533 // negative: luminance towards 0% (black)
534 lclModValue( mnC3
, aIt
->mnValue
+ MAX_PERCENT
);
536 else if( (0 < aIt
->mnValue
) && (aIt
->mnValue
<= MAX_PERCENT
) )
538 // positive: luminance towards 100% (white)
539 mnC3
= MAX_PERCENT
- mnC3
;
540 lclModValue( mnC3
, MAX_PERCENT
- aIt
->mnValue
);
541 mnC3
= MAX_PERCENT
- mnC3
;
546 // change color to gray, weighted RGB: 22% red, 72% green, 6% blue
548 mnC1
= mnC2
= mnC3
= (mnC1
* 22 + mnC2
* 72 + mnC3
* 6) / 100;
552 // comp: rotate hue by 180 degrees, do not change lum/sat
554 (mnC1
+= 180 * PER_DEGREE
) %= MAX_DEGREE
;
557 // invert percentual RGB values
559 mnC1
= MAX_PERCENT
- mnC1
;
560 mnC2
= MAX_PERCENT
- mnC2
;
561 mnC3
= MAX_PERCENT
- mnC3
;
565 // increase gamma of color
567 mnC1
= lclGamma( mnC1
, INC_GAMMA
);
568 mnC2
= lclGamma( mnC2
, INC_GAMMA
);
569 mnC3
= lclGamma( mnC3
, INC_GAMMA
);
572 // decrease gamma of color
574 mnC1
= lclGamma( mnC1
, DEC_GAMMA
);
575 mnC2
= lclGamma( mnC2
, DEC_GAMMA
);
576 mnC3
= lclGamma( mnC3
, DEC_GAMMA
);
581 // store resulting RGB value in mnC1
583 mnC1
= lclRgbComponentsToRgb( mnC1
, mnC2
, mnC3
);
585 else // if( meMode != COLOR_UNUSED )
587 mnC1
= API_RGB_TRANSPARENT
;
590 sal_Int32 nRet
= mnC1
;
591 // Restore the original values when the color depends on one of the input
592 // parameters (rGraphicHelper or nPhClr)
593 if( eTempMode
>= COLOR_SCHEME
&& eTempMode
<= COLOR_PH
)
602 meMode
= COLOR_FINAL
;
604 if( meMode
== COLOR_FINAL
)
605 maTransforms
.clear();
609 bool Color::hasTransparency() const
611 return mnAlpha
< MAX_PERCENT
;
614 sal_Int16
Color::getTransparency() const
616 return static_cast< sal_Int16
>( (MAX_PERCENT
- mnAlpha
) / PER_PERCENT
);
619 // private --------------------------------------------------------------------
621 void Color::setResolvedRgb( sal_Int32 nRgb
) const
623 meMode
= (nRgb
< 0) ? COLOR_UNUSED
: COLOR_RGB
;
624 lclRgbToRgbComponents( mnC1
, mnC2
, mnC3
, nRgb
);
627 void Color::toRgb() const
636 mnC1
= lclCrgbCompToRgbComp( lclGamma( mnC1
, INC_GAMMA
) );
637 mnC2
= lclCrgbCompToRgbComp( lclGamma( mnC2
, INC_GAMMA
) );
638 mnC3
= lclCrgbCompToRgbComp( lclGamma( mnC3
, INC_GAMMA
) );
643 double fR
= 0.0, fG
= 0.0, fB
= 0.0;
644 if( (mnC2
== 0) || (mnC3
== MAX_PERCENT
) )
646 fR
= fG
= fB
= static_cast< double >( mnC3
) / MAX_PERCENT
;
650 // base color from hue
651 double fHue
= static_cast< double >( mnC1
) / MAX_DEGREE
* 6.0; // interval [0.0, 6.0)
652 if( fHue
<= 1.0 ) { fR
= 1.0; fG
= fHue
; } // red...yellow
653 else if( fHue
<= 2.0 ) { fR
= 2.0 - fHue
; fG
= 1.0; } // yellow...green
654 else if( fHue
<= 3.0 ) { fG
= 1.0; fB
= fHue
- 2.0; } // green...cyan
655 else if( fHue
<= 4.0 ) { fG
= 4.0 - fHue
; fB
= 1.0; } // cyan...blue
656 else if( fHue
<= 5.0 ) { fR
= fHue
- 4.0; fB
= 1.0; } // blue...magenta
657 else { fR
= 1.0; fB
= 6.0 - fHue
; } // magenta...red
660 double fSat
= static_cast< double >( mnC2
) / MAX_PERCENT
;
661 fR
= (fR
- 0.5) * fSat
+ 0.5;
662 fG
= (fG
- 0.5) * fSat
+ 0.5;
663 fB
= (fB
- 0.5) * fSat
+ 0.5;
666 double fLum
= 2.0 * static_cast< double >( mnC3
) / MAX_PERCENT
- 1.0; // interval [-1.0, 1.0]
669 double fShade
= fLum
+ 1.0; // interval [0.0, 1.0] (black...full color)
674 else if( fLum
> 0.0 )
676 double fTint
= 1.0 - fLum
; // interval [0.0, 1.0] (white...full color)
677 fR
= 1.0 - ((1.0 - fR
) * fTint
);
678 fG
= 1.0 - ((1.0 - fG
) * fTint
);
679 fB
= 1.0 - ((1.0 - fB
) * fTint
);
682 mnC1
= static_cast< sal_Int32
>( fR
* 255.0 + 0.5 );
683 mnC2
= static_cast< sal_Int32
>( fG
* 255.0 + 0.5 );
684 mnC3
= static_cast< sal_Int32
>( fB
* 255.0 + 0.5 );
688 OSL_FAIL( "Color::toRgb - unexpected color mode" );
692 void Color::toCrgb() const
701 mnC1
= lclGamma( lclRgbCompToCrgbComp( mnC1
), DEC_GAMMA
);
702 mnC2
= lclGamma( lclRgbCompToCrgbComp( mnC2
), DEC_GAMMA
);
703 mnC3
= lclGamma( lclRgbCompToCrgbComp( mnC3
), DEC_GAMMA
);
709 OSL_FAIL( "Color::toCrgb - unexpected color mode" );
713 void Color::toHsl() const
723 double fR
= static_cast< double >( mnC1
) / 255.0; // red [0.0, 1.0]
724 double fG
= static_cast< double >( mnC2
) / 255.0; // green [0.0, 1.0]
725 double fB
= static_cast< double >( mnC3
) / 255.0; // blue [0.0, 1.0]
726 double fMin
= ::std::min( ::std::min( fR
, fG
), fB
);
727 double fMax
= ::std::max( ::std::max( fR
, fG
), fB
);
728 double fD
= fMax
- fMin
;
730 using ::rtl::math::approxEqual
;
732 // hue: 0deg = red, 120deg = green, 240deg = blue
733 if( fD
== 0.0 ) // black/gray/white
735 else if( approxEqual(fMax
, fR
, 64) ) // magenta...red...yellow
736 mnC1
= static_cast< sal_Int32
>( ((fG
- fB
) / fD
* 60.0 + 360.0) * PER_DEGREE
+ 0.5 ) % MAX_DEGREE
;
737 else if( approxEqual(fMax
, fG
, 64) ) // yellow...green...cyan
738 mnC1
= static_cast< sal_Int32
>( ((fB
- fR
) / fD
* 60.0 + 120.0) * PER_DEGREE
+ 0.5 );
739 else // cyan...blue...magenta
740 mnC1
= static_cast< sal_Int32
>( ((fR
- fG
) / fD
* 60.0 + 240.0) * PER_DEGREE
+ 0.5 );
742 // luminance: 0% = black, 50% = full color, 100% = white
743 mnC3
= static_cast< sal_Int32
>( (fMin
+ fMax
) / 2.0 * MAX_PERCENT
+ 0.5 );
745 // saturation: 0% = gray, 100% = full color
746 if( (mnC3
== 0) || (mnC3
== MAX_PERCENT
) ) // black/white
748 else if( mnC3
<= 50 * PER_PERCENT
) // dark...full color
749 mnC2
= static_cast< sal_Int32
>( fD
/ (fMin
+ fMax
) * MAX_PERCENT
+ 0.5 );
750 else // full color...light
751 mnC2
= static_cast< sal_Int32
>( fD
/ (2.0 - fMax
- fMin
) * MAX_PERCENT
+ 0.5 );
758 OSL_FAIL( "Color::toHsl - unexpected color mode" );
762 } // namespace drawingml
765 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */