1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: color.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 #include "oox/drawingml/color.hxx"
32 #include "oox/core/namespaces.hxx"
33 #include "oox/core/xmlfilterbase.hxx"
41 // ============================================================================
45 const sal_Int32 PER_PERCENT
= 1000;
46 const sal_Int32 MAX_PERCENT
= 100 * PER_PERCENT
;
48 const sal_Int32 PER_DEGREE
= 60000;
49 const sal_Int32 MAX_DEGREE
= 360 * PER_DEGREE
;
51 const double DEC_GAMMA
= 2.3;
52 const double INC_GAMMA
= 1.0 / DEC_GAMMA
;
54 sal_Int32
lclGetPresetColor( sal_Int32 nToken
)
58 case XML_aliceBlue
: return 0xF0F8FF;
59 case XML_antiqueWhite
: return 0xFAEBD7;
60 case XML_aqua
: return 0x00FFFF;
61 case XML_aquamarine
: return 0x7FFFD4;
62 case XML_azure
: return 0xF0FFFF;
63 case XML_beige
: return 0xF5F5DC;
64 case XML_bisque
: return 0xFFE4C4;
65 case XML_black
: return 0x000000;
66 case XML_blanchedAlmond
: return 0xFFEBCD;
67 case XML_blue
: return 0x0000FF;
68 case XML_blueViolet
: return 0x8A2BE2;
69 case XML_brown
: return 0xA52A2A;
70 case XML_burlyWood
: return 0xDEB887;
71 case XML_cadetBlue
: return 0x5F9EA0;
72 case XML_chartreuse
: return 0x7FFF00;
73 case XML_chocolate
: return 0xD2691E;
74 case XML_coral
: return 0xFF7F50;
75 case XML_cornflowerBlue
: return 0x6495ED;
76 case XML_cornsilk
: return 0xFFF8DC;
77 case XML_crimson
: return 0xDC143C;
78 case XML_cyan
: return 0x00FFFF;
79 case XML_deepPink
: return 0xFF1493;
80 case XML_deepSkyBlue
: return 0x00BFFF;
81 case XML_dimGray
: return 0x696969;
82 case XML_dkBlue
: return 0x00008B;
83 case XML_dkCyan
: return 0x008B8B;
84 case XML_dkGoldenrod
: return 0xB8860B;
85 case XML_dkGray
: return 0xA9A9A9;
86 case XML_dkGreen
: return 0x006400;
87 case XML_dkKhaki
: return 0xBDB76B;
88 case XML_dkMagenta
: return 0x8B008B;
89 case XML_dkOliveGreen
: return 0x556B2F;
90 case XML_dkOrange
: return 0xFF8C00;
91 case XML_dkOrchid
: return 0x9932CC;
92 case XML_dkRed
: return 0x8B0000;
93 case XML_dkSalmon
: return 0xE9967A;
94 case XML_dkSeaGreen
: return 0x8FBC8B;
95 case XML_dkSlateBlue
: return 0x483D8B;
96 case XML_dkSlateGray
: return 0x2F4F4F;
97 case XML_dkTurquoise
: return 0x00CED1;
98 case XML_dkViolet
: return 0x9400D3;
99 case XML_dodgerBlue
: return 0x1E90FF;
100 case XML_firebrick
: return 0xB22222;
101 case XML_floralWhite
: return 0xFFFAF0;
102 case XML_forestGreen
: return 0x228B22;
103 case XML_fuchsia
: return 0xFF00FF;
104 case XML_gainsboro
: return 0xDCDCDC;
105 case XML_ghostWhite
: return 0xF8F8FF;
106 case XML_gold
: return 0xFFD700;
107 case XML_goldenrod
: return 0xDAA520;
108 case XML_gray
: return 0x808080;
109 case XML_green
: return 0x008000;
110 case XML_greenYellow
: return 0xADFF2F;
111 case XML_honeydew
: return 0xF0FFF0;
112 case XML_hotPink
: return 0xFF69B4;
113 case XML_indianRed
: return 0xCD5C5C;
114 case XML_indigo
: return 0x4B0082;
115 case XML_ivory
: return 0xFFFFF0;
116 case XML_khaki
: return 0xF0E68C;
117 case XML_lavender
: return 0xE6E6FA;
118 case XML_lavenderBlush
: return 0xFFF0F5;
119 case XML_lawnGreen
: return 0x7CFC00;
120 case XML_lemonChiffon
: return 0xFFFACD;
121 case XML_lime
: return 0x00FF00;
122 case XML_limeGreen
: return 0x32CD32;
123 case XML_linen
: return 0xFAF0E6;
124 case XML_ltBlue
: return 0xADD8E6;
125 case XML_ltCoral
: return 0xF08080;
126 case XML_ltCyan
: return 0xE0FFFF;
127 case XML_ltGoldenrodYellow
: return 0xFAFA78;
128 case XML_ltGray
: return 0xD3D3D3;
129 case XML_ltGreen
: return 0x90EE90;
130 case XML_ltPink
: return 0xFFB6C1;
131 case XML_ltSalmon
: return 0xFFA07A;
132 case XML_ltSeaGreen
: return 0x20B2AA;
133 case XML_ltSkyBlue
: return 0x87CEFA;
134 case XML_ltSlateGray
: return 0x778899;
135 case XML_ltSteelBlue
: return 0xB0C4DE;
136 case XML_ltYellow
: return 0xFFFFE0;
137 case XML_magenta
: return 0xFF00FF;
138 case XML_maroon
: return 0x800000;
139 case XML_medAquamarine
: return 0x66CDAA;
140 case XML_medBlue
: return 0x0000CD;
141 case XML_medOrchid
: return 0xBA55D3;
142 case XML_medPurple
: return 0x9370DB;
143 case XML_medSeaGreen
: return 0x3CB371;
144 case XML_medSlateBlue
: return 0x7B68EE;
145 case XML_medSpringGreen
: return 0x00FA9A;
146 case XML_medTurquoise
: return 0x48D1CC;
147 case XML_medVioletRed
: return 0xC71585;
148 case XML_midnightBlue
: return 0x191970;
149 case XML_mintCream
: return 0xF5FFFA;
150 case XML_mistyRose
: return 0xFFE4E1;
151 case XML_moccasin
: return 0xFFE4B5;
152 case XML_navajoWhite
: return 0xFFDEAD;
153 case XML_navy
: return 0x000080;
154 case XML_oldLace
: return 0xFDF5E6;
155 case XML_olive
: return 0x808000;
156 case XML_oliveDrab
: return 0x6B8E23;
157 case XML_orange
: return 0xFFA500;
158 case XML_orangeRed
: return 0xFF4500;
159 case XML_orchid
: return 0xDA70D6;
160 case XML_paleGoldenrod
: return 0xEEE8AA;
161 case XML_paleGreen
: return 0x98FB98;
162 case XML_paleTurquoise
: return 0xAFEEEE;
163 case XML_paleVioletRed
: return 0xDB7093;
164 case XML_papayaWhip
: return 0xFFEFD5;
165 case XML_peachPuff
: return 0xFFDAB9;
166 case XML_peru
: return 0xCD853F;
167 case XML_pink
: return 0xFFC0CB;
168 case XML_plum
: return 0xDDA0DD;
169 case XML_powderBlue
: return 0xB0E0E6;
170 case XML_purple
: return 0x800080;
171 case XML_red
: return 0xFF0000;
172 case XML_rosyBrown
: return 0xBC8F8F;
173 case XML_royalBlue
: return 0x4169E1;
174 case XML_saddleBrown
: return 0x8B4513;
175 case XML_salmon
: return 0xFA8072;
176 case XML_sandyBrown
: return 0xF4A460;
177 case XML_seaGreen
: return 0x2E8B57;
178 case XML_seaShell
: return 0xFFF5EE;
179 case XML_sienna
: return 0xA0522D;
180 case XML_silver
: return 0xC0C0C0;
181 case XML_skyBlue
: return 0x87CEEB;
182 case XML_slateBlue
: return 0x6A5ACD;
183 case XML_slateGray
: return 0x708090;
184 case XML_snow
: return 0xFFFAFA;
185 case XML_springGreen
: return 0x00FF7F;
186 case XML_steelBlue
: return 0x4682B4;
187 case XML_tan
: return 0xD2B48C;
188 case XML_teal
: return 0x008080;
189 case XML_thistle
: return 0xD8BFD8;
190 case XML_tomato
: return 0xFF6347;
191 case XML_turquoise
: return 0x40E0D0;
192 case XML_violet
: return 0xEE82EE;
193 case XML_wheat
: return 0xF5DEB3;
194 case XML_white
: return 0xFFFFFF;
195 case XML_whiteSmoke
: return 0xF5F5F5;
196 case XML_yellow
: return 0xFFFF00;
197 case XML_yellowGreen
: return 0x9ACD32;
199 OSL_ENSURE( false, "lclGetPresetColor - invalid preset color token" );
200 return API_RGB_BLACK
;
203 inline void lclRgbToRgbComponents( sal_Int32
& ornR
, sal_Int32
& ornG
, sal_Int32
& ornB
, sal_Int32 nRgb
)
205 ornR
= (nRgb
>> 16) & 0xFF;
206 ornG
= (nRgb
>> 8) & 0xFF;
210 inline sal_Int32
lclRgbComponentsToRgb( sal_Int32 nR
, sal_Int32 nG
, sal_Int32 nB
)
212 return static_cast< sal_Int32
>( (nR
<< 16) | (nG
<< 8) | nB
);
215 inline sal_Int32
lclRgbCompToCrgbComp( sal_Int32 nRgbComp
)
217 return static_cast< sal_Int32
>( nRgbComp
* MAX_PERCENT
/ 255 );
220 inline sal_Int32
lclCrgbCompToRgbComp( sal_Int32 nCrgbComp
)
222 return static_cast< sal_Int32
>( nCrgbComp
* 255 / MAX_PERCENT
);
225 inline sal_Int32
lclGamma( sal_Int32 nComp
, double fGamma
)
227 return static_cast< sal_Int32
>( pow( static_cast< double >( nComp
) / MAX_PERCENT
, fGamma
) * MAX_PERCENT
+ 0.5 );
230 void lclSetValue( sal_Int32
& ornValue
, sal_Int32 nNew
, sal_Int32 nMax
= MAX_PERCENT
)
232 OSL_ENSURE( (0 <= nNew
) && (nNew
<= nMax
), "lclSetValue - invalid value" );
233 if( (0 <= nNew
) && (nNew
<= nMax
) )
237 void lclModValue( sal_Int32
& ornValue
, sal_Int32 nMod
, sal_Int32 nMax
= MAX_PERCENT
)
239 OSL_ENSURE( (0 <= nMod
), "lclModValue - invalid modificator" );
240 ornValue
= getLimitedValue
< sal_Int32
, double >( static_cast< double >( ornValue
) * nMod
/ MAX_PERCENT
, 0, nMax
);
243 void lclOffValue( sal_Int32
& ornValue
, sal_Int32 nOff
, sal_Int32 nMax
= MAX_PERCENT
)
245 OSL_ENSURE( (-nMax
<= nOff
) && (nOff
<= nMax
), "lclOffValue - invalid offset" );
246 ornValue
= getLimitedValue
< sal_Int32
, sal_Int32
>( ornValue
+ nOff
, 0, nMax
);
251 // ----------------------------------------------------------------------------
254 meMode( COLOR_UNUSED
),
258 mnAlpha( MAX_PERCENT
)
266 void Color::setUnused()
268 meMode
= COLOR_UNUSED
;
271 void Color::setSrgbClr( sal_Int32 nRgb
)
273 OSL_ENSURE( (0 <= nRgb
) && (nRgb
<= 0xFFFFFF), "Color::setSrgbClr - invalid RGB value" );
275 lclRgbToRgbComponents( mnC1
, mnC2
, mnC3
, nRgb
);
278 void Color::setScrgbClr( sal_Int32 nR
, sal_Int32 nG
, sal_Int32 nB
)
280 OSL_ENSURE( (0 <= nR
) && (nR
<= MAX_PERCENT
), "Color::setScrgbClr - invalid red value" );
281 OSL_ENSURE( (0 <= nG
) && (nG
<= MAX_PERCENT
), "Color::setScrgbClr - invalid green value" );
282 OSL_ENSURE( (0 <= nB
) && (nB
<= MAX_PERCENT
), "Color::setScrgbClr - invalid blue value" );
284 mnC1
= getLimitedValue
< sal_Int32
, sal_Int32
>( nR
, 0, MAX_PERCENT
);
285 mnC2
= getLimitedValue
< sal_Int32
, sal_Int32
>( nG
, 0, MAX_PERCENT
);
286 mnC3
= getLimitedValue
< sal_Int32
, sal_Int32
>( nB
, 0, MAX_PERCENT
);
289 void Color::setHslClr( sal_Int32 nHue
, sal_Int32 nSat
, sal_Int32 nLum
)
291 OSL_ENSURE( (0 <= nHue
) && (nHue
<= MAX_DEGREE
), "Color::setHslClr - invalid hue value" );
292 OSL_ENSURE( (0 <= nSat
) && (nSat
<= MAX_PERCENT
), "Color::setHslClr - invalid saturation value" );
293 OSL_ENSURE( (0 <= nLum
) && (nLum
<= MAX_PERCENT
), "Color::setHslClr - invalid luminance value" );
295 mnC1
= getLimitedValue
< sal_Int32
, sal_Int32
>( nHue
, 0, MAX_DEGREE
);
296 mnC2
= getLimitedValue
< sal_Int32
, sal_Int32
>( nSat
, 0, MAX_PERCENT
);
297 mnC3
= getLimitedValue
< sal_Int32
, sal_Int32
>( nLum
, 0, MAX_PERCENT
);
300 void Color::setPrstClr( sal_Int32 nToken
)
302 setSrgbClr( lclGetPresetColor( nToken
) );
305 void Color::setSchemeClr( sal_Int32 nToken
)
307 OSL_ENSURE( nToken
!= XML_TOKEN_INVALID
, "Color::setSchemeClr - invalid color token" );
308 meMode
= (nToken
== XML_phClr
) ? COLOR_PH
: COLOR_SCHEME
;
312 void Color::setSysClr( sal_Int32 nToken
, sal_Int32 nLastRgb
)
314 OSL_ENSURE( (-1 <= nLastRgb
) && (nLastRgb
<= 0xFFFFFF), "Color::setSysClr - invalid RGB value" );
315 meMode
= COLOR_SYSTEM
;
320 void Color::addTransformation( sal_Int32 nElement
, sal_Int32 nValue
)
322 /* Execute alpha transformations directly, store other transformations in
323 a vector, they may depend on a scheme base color which will be resolved
324 in Color::getColor(). */
325 sal_Int32 nToken
= getToken( nElement
);
328 case XML_alpha
: lclSetValue( mnAlpha
, nValue
); break;
329 case XML_alphaMod
: lclModValue( mnAlpha
, nValue
); break;
330 case XML_alphaOff
: lclOffValue( mnAlpha
, nValue
); break;
331 default: maTransforms
.push_back( Transformation( nToken
, nValue
) );
335 void Color::addChartTintTransformation( double fTint
)
337 sal_Int32 nValue
= getLimitedValue
< sal_Int32
, double >( fTint
* MAX_PERCENT
+ 0.5, -MAX_PERCENT
, MAX_PERCENT
);
339 maTransforms
.push_back( Transformation( XML_shade
, nValue
+ MAX_PERCENT
) );
340 else if( nValue
> 0 )
341 maTransforms
.push_back( Transformation( XML_tint
, MAX_PERCENT
- nValue
) );
344 void Color::addExcelTintTransformation( double fTint
)
346 sal_Int32 nValue
= getLimitedValue
< sal_Int32
, double >( fTint
* MAX_PERCENT
+ 0.5, -MAX_PERCENT
, MAX_PERCENT
);
347 maTransforms
.push_back( Transformation( NMSP_XLS
| XML_tint
, nValue
) );
350 void Color::clearTransparence()
352 mnAlpha
= MAX_PERCENT
;
355 sal_Int32
Color::getColor( const ::oox::core::XmlFilterBase
& rFilter
, sal_Int32 nPhClr
) const
357 /* Special handling for theme style list placeholder colors (state
358 COLOR_PH), Color::getColor() may be called with different placeholder
359 colors in the nPhClr parameter. Therefore, the resolved color will not
360 be stored in this object, thus the state COLOR_FINAL will not be
361 reached and the transformation container will not be cleared, but the
362 original COLOR_PH state will be restored instead. */
367 case COLOR_UNUSED
: return -1;
368 case COLOR_FINAL
: return mnC1
;
370 case COLOR_RGB
: break; // nothing to do
371 case COLOR_CRGB
: break; // nothing to do
372 case COLOR_HSL
: break; // nothing to do
376 lclRgbToRgbComponents( mnC1
, mnC2
, mnC3
, rFilter
.getSchemeClr( mnC1
) );
380 lclRgbToRgbComponents( mnC1
, mnC2
, mnC3
, nPhClr
);
385 lclRgbToRgbComponents( mnC1
, mnC2
, mnC3
, rFilter
.getSystemColor( mnC1
, mnC2
) );
389 for( TransformVec::const_iterator aIt
= maTransforms
.begin(), aEnd
= maTransforms
.end(); aIt
!= aEnd
; ++aIt
)
391 switch( aIt
->mnToken
)
393 case XML_red
: toCrgb(); lclSetValue( mnC1
, aIt
->mnValue
); break;
394 case XML_redMod
: toCrgb(); lclModValue( mnC1
, aIt
->mnValue
); break;
395 case XML_redOff
: toCrgb(); lclOffValue( mnC1
, aIt
->mnValue
); break;
396 case XML_green
: toCrgb(); lclSetValue( mnC2
, aIt
->mnValue
); break;
397 case XML_greenMod
: toCrgb(); lclModValue( mnC2
, aIt
->mnValue
); break;
398 case XML_greenOff
: toCrgb(); lclOffValue( mnC2
, aIt
->mnValue
); break;
399 case XML_blue
: toCrgb(); lclSetValue( mnC3
, aIt
->mnValue
); break;
400 case XML_blueMod
: toCrgb(); lclModValue( mnC3
, aIt
->mnValue
); break;
401 case XML_blueOff
: toCrgb(); lclOffValue( mnC3
, aIt
->mnValue
); break;
403 case XML_hue
: toHsl(); lclSetValue( mnC1
, aIt
->mnValue
, MAX_DEGREE
); break;
404 case XML_hueMod
: toHsl(); lclModValue( mnC1
, aIt
->mnValue
, MAX_DEGREE
); break;
405 case XML_hueOff
: toHsl(); lclOffValue( mnC1
, aIt
->mnValue
, MAX_DEGREE
); break;
406 case XML_sat
: toHsl(); lclSetValue( mnC2
, aIt
->mnValue
); break;
407 case XML_satMod
: toHsl(); lclModValue( mnC2
, aIt
->mnValue
); break;
408 case XML_satOff
: toHsl(); lclOffValue( mnC2
, aIt
->mnValue
); break;
412 lclSetValue( mnC3
, aIt
->mnValue
);
413 // if color changes to black or white, it will stay gray if luminance changes again
414 if( (mnC3
== 0) || (mnC3
== MAX_PERCENT
) ) mnC2
= 0;
418 lclModValue( mnC3
, aIt
->mnValue
);
419 // if color changes to black or white, it will stay gray if luminance changes again
420 if( (mnC3
== 0) || (mnC3
== MAX_PERCENT
) ) mnC2
= 0;
424 lclOffValue( mnC3
, aIt
->mnValue
);
425 // if color changes to black or white, it will stay gray if luminance changes again
426 if( (mnC3
== 0) || (mnC3
== MAX_PERCENT
) ) mnC2
= 0;
430 // shade: 0% = black, 100% = original color
432 OSL_ENSURE( (0 <= aIt
->mnValue
) && (aIt
->mnValue
<= MAX_PERCENT
), "Color::getColor - invalid shade value" );
433 if( (0 <= aIt
->mnValue
) && (aIt
->mnValue
<= MAX_PERCENT
) )
435 double fFactor
= static_cast< double >( aIt
->mnValue
) / MAX_PERCENT
;
436 mnC1
= static_cast< sal_Int32
>( mnC1
* fFactor
);
437 mnC2
= static_cast< sal_Int32
>( mnC2
* fFactor
);
438 mnC3
= static_cast< sal_Int32
>( mnC3
* fFactor
);
442 // tint: 0% = white, 100% = original color
444 OSL_ENSURE( (0 <= aIt
->mnValue
) && (aIt
->mnValue
<= MAX_PERCENT
), "Color::getColor - invalid tint value" );
445 if( (0 <= aIt
->mnValue
) && (aIt
->mnValue
<= MAX_PERCENT
) )
447 double fFactor
= static_cast< double >( aIt
->mnValue
) / MAX_PERCENT
;
448 mnC1
= static_cast< sal_Int32
>( MAX_PERCENT
- (MAX_PERCENT
- mnC1
) * fFactor
);
449 mnC2
= static_cast< sal_Int32
>( MAX_PERCENT
- (MAX_PERCENT
- mnC2
) * fFactor
);
450 mnC3
= static_cast< sal_Int32
>( MAX_PERCENT
- (MAX_PERCENT
- mnC3
) * fFactor
);
453 case XLS_TOKEN( tint
):
454 // Excel tint: move luminance relative to current value
456 OSL_ENSURE( (-MAX_PERCENT
<= aIt
->mnValue
) && (aIt
->mnValue
<= MAX_PERCENT
), "Color::getColor - invalid tint value" );
457 if( (-MAX_PERCENT
<= aIt
->mnValue
) && (aIt
->mnValue
< 0) )
459 // negative: luminance towards 0% (black)
460 lclModValue( mnC3
, aIt
->mnValue
+ MAX_PERCENT
);
462 else if( (0 < aIt
->mnValue
) && (aIt
->mnValue
<= MAX_PERCENT
) )
464 // positive: luminance towards 100% (white)
465 mnC3
= MAX_PERCENT
- mnC3
;
466 lclModValue( mnC3
, MAX_PERCENT
- aIt
->mnValue
);
467 mnC3
= MAX_PERCENT
- mnC3
;
472 // change color to gray, weighted RGB: 22% red, 72% green, 6% blue
474 mnC1
= mnC2
= mnC3
= (mnC1
* 22 + mnC2
* 72 + mnC3
* 6) / 100;
478 // comp: rotate hue by 180 degrees, do not change lum/sat
480 (mnC1
+= 180 * PER_DEGREE
) %= MAX_DEGREE
;
483 // invert percentual RGB values
485 mnC1
= MAX_PERCENT
- mnC1
;
486 mnC2
= MAX_PERCENT
- mnC2
;
487 mnC3
= MAX_PERCENT
- mnC3
;
491 // increase gamma of color
493 mnC1
= lclGamma( mnC1
, INC_GAMMA
);
494 mnC2
= lclGamma( mnC2
, INC_GAMMA
);
495 mnC3
= lclGamma( mnC3
, INC_GAMMA
);
498 // decrease gamma of color
500 mnC1
= lclGamma( mnC1
, DEC_GAMMA
);
501 mnC2
= lclGamma( mnC2
, DEC_GAMMA
);
502 mnC3
= lclGamma( mnC3
, DEC_GAMMA
);
508 meMode
= bIsPh
? COLOR_PH
: COLOR_FINAL
;
509 if( meMode
== COLOR_FINAL
)
510 maTransforms
.clear();
511 return mnC1
= lclRgbComponentsToRgb( mnC1
, mnC2
, mnC3
);
514 bool Color::hasTransparence() const
516 return mnAlpha
< MAX_PERCENT
;
519 sal_Int16
Color::getTransparence() const
521 return static_cast< sal_Int16
>( (MAX_PERCENT
- mnAlpha
) / PER_PERCENT
);
524 // private --------------------------------------------------------------------
526 void Color::toRgb() const
535 mnC1
= lclCrgbCompToRgbComp( lclGamma( mnC1
, INC_GAMMA
) );
536 mnC2
= lclCrgbCompToRgbComp( lclGamma( mnC2
, INC_GAMMA
) );
537 mnC3
= lclCrgbCompToRgbComp( lclGamma( mnC3
, INC_GAMMA
) );
542 double fR
= 0.0, fG
= 0.0, fB
= 0.0;
543 if( (mnC2
== 0) || (mnC3
== MAX_PERCENT
) )
545 fR
= fG
= fB
= static_cast< double >( mnC3
) / MAX_PERCENT
;
549 // base color from hue
550 double fHue
= static_cast< double >( mnC1
) / MAX_DEGREE
* 6.0; // interval [0.0, 6.0)
551 if( fHue
<= 1.0 ) { fR
= 1.0; fG
= fHue
; } // red...yellow
552 else if( fHue
<= 2.0 ) { fR
= 2.0 - fHue
; fG
= 1.0; } // yellow...green
553 else if( fHue
<= 3.0 ) { fG
= 1.0; fB
= fHue
- 2.0; } // green...cyan
554 else if( fHue
<= 4.0 ) { fG
= 4.0 - fHue
; fB
= 1.0; } // cyan...blue
555 else if( fHue
<= 5.0 ) { fR
= fHue
- 4.0; fB
= 1.0; } // blue...magenta
556 else { fR
= 1.0; fB
= 6.0 - fHue
; } // magenta...red
559 double fSat
= static_cast< double >( mnC2
) / MAX_PERCENT
;
560 fR
= (fR
- 0.5) * fSat
+ 0.5;
561 fG
= (fG
- 0.5) * fSat
+ 0.5;
562 fB
= (fB
- 0.5) * fSat
+ 0.5;
565 double fLum
= 2.0 * static_cast< double >( mnC3
) / MAX_PERCENT
- 1.0; // interval [-1.0, 1.0]
568 double fShade
= fLum
+ 1.0; // interval [0.0, 1.0] (black...full color)
573 else if( fLum
> 0.0 )
575 double fTint
= 1.0 - fLum
; // interval [0.0, 1.0] (white...full color)
576 fR
= 1.0 - ((1.0 - fR
) * fTint
);
577 fG
= 1.0 - ((1.0 - fG
) * fTint
);
578 fB
= 1.0 - ((1.0 - fB
) * fTint
);
581 mnC1
= static_cast< sal_Int32
>( fR
* 255.0 + 0.5 );
582 mnC2
= static_cast< sal_Int32
>( fG
* 255.0 + 0.5 );
583 mnC3
= static_cast< sal_Int32
>( fB
* 255.0 + 0.5 );
587 OSL_ENSURE( false, "Color::toRgb - unexpected color mode" );
591 void Color::toCrgb() const
600 mnC1
= lclGamma( lclRgbCompToCrgbComp( mnC1
), DEC_GAMMA
);
601 mnC2
= lclGamma( lclRgbCompToCrgbComp( mnC2
), DEC_GAMMA
);
602 mnC3
= lclGamma( lclRgbCompToCrgbComp( mnC3
), DEC_GAMMA
);
608 OSL_ENSURE( false, "Color::toCrgb - unexpected color mode" );
612 void Color::toHsl() const
622 double fR
= static_cast< double >( mnC1
) / 255.0; // red [0.0, 1.0]
623 double fG
= static_cast< double >( mnC2
) / 255.0; // green [0.0, 1.0]
624 double fB
= static_cast< double >( mnC3
) / 255.0; // blue [0.0, 1.0]
625 double fMin
= ::std::min( ::std::min( fR
, fG
), fB
);
626 double fMax
= ::std::max( ::std::max( fR
, fG
), fB
);
627 double fD
= fMax
- fMin
;
629 // hue: 0deg = red, 120deg = green, 240deg = blue
630 if( fD
== 0.0 ) // black/gray/white
632 else if( fMax
== fR
) // magenta...red...yellow
633 mnC1
= static_cast< sal_Int32
>( ((fG
- fB
) / fD
* 60.0 + 360.0) * PER_DEGREE
+ 0.5 ) % MAX_DEGREE
;
634 else if( fMax
== fG
) // yellow...green...cyan
635 mnC1
= static_cast< sal_Int32
>( ((fB
- fR
) / fD
* 60.0 + 120.0) * PER_DEGREE
+ 0.5 );
636 else // cyan...blue...magenta
637 mnC1
= static_cast< sal_Int32
>( ((fR
- fG
) / fD
* 60.0 + 240.0) * PER_DEGREE
+ 0.5 );
639 // luminance: 0% = black, 50% = full color, 100% = white
640 mnC3
= static_cast< sal_Int32
>( (fMin
+ fMax
) / 2.0 * MAX_PERCENT
+ 0.5 );
642 // saturation: 0% = gray, 100% = full color
643 if( (mnC3
== 0) || (mnC3
== MAX_PERCENT
) ) // black/white
645 else if( mnC3
<= 50 * PER_PERCENT
) // dark...full color
646 mnC2
= static_cast< sal_Int32
>( fD
/ (fMin
+ fMax
) * MAX_PERCENT
+ 0.5 );
647 else // full color...light
648 mnC2
= static_cast< sal_Int32
>( fD
/ (2.0 - fMax
- fMin
) * MAX_PERCENT
+ 0.5 );
655 OSL_ENSURE( false, "Color::toHsl - unexpected color mode" );
659 // ============================================================================
661 } // namespace drawingml