update dev300-m58
[ooovba.git] / oox / source / drawingml / color.cxx
blobc269379b5adcae9a4ce7d931decc9076ad4fa985
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 $
10 * $Revision: 1.7 $
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"
34 #include "tokens.hxx"
35 #include <algorithm>
36 #include <math.h>
38 namespace oox {
39 namespace drawingml {
41 // ============================================================================
43 namespace {
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 )
56 switch( 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;
207 ornB = nRgb & 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) )
234 ornValue = nNew;
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 );
249 } // namespace
251 // ----------------------------------------------------------------------------
253 Color::Color() :
254 meMode( COLOR_UNUSED ),
255 mnC1( 0 ),
256 mnC2( 0 ),
257 mnC3( 0 ),
258 mnAlpha( MAX_PERCENT )
262 Color::~Color()
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" );
274 meMode = COLOR_RGB;
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" );
283 meMode = COLOR_CRGB;
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" );
294 meMode = COLOR_HSL;
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;
309 mnC1 = nToken;
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;
316 mnC1 = nToken;
317 mnC2 = nLastRgb;
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 );
326 switch( nToken )
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 );
338 if( nValue < 0 )
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. */
363 bool bIsPh = false;
365 switch( meMode )
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
374 case COLOR_SCHEME:
375 meMode = COLOR_RGB;
376 lclRgbToRgbComponents( mnC1, mnC2, mnC3, rFilter.getSchemeClr( mnC1 ) );
377 break;
378 case COLOR_PH:
379 meMode = COLOR_RGB;
380 lclRgbToRgbComponents( mnC1, mnC2, mnC3, nPhClr );
381 bIsPh = true;
382 break;
383 case COLOR_SYSTEM:
384 meMode = COLOR_RGB;
385 lclRgbToRgbComponents( mnC1, mnC2, mnC3, rFilter.getSystemColor( mnC1, mnC2 ) );
386 break;
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;
410 case XML_lum:
411 toHsl();
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;
415 break;
416 case XML_lumMod:
417 toHsl();
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;
421 break;
422 case XML_lumOff:
423 toHsl();
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;
427 break;
429 case XML_shade:
430 // shade: 0% = black, 100% = original color
431 toCrgb();
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 );
440 break;
441 case XML_tint:
442 // tint: 0% = white, 100% = original color
443 toCrgb();
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 );
452 break;
453 case XLS_TOKEN( tint ):
454 // Excel tint: move luminance relative to current value
455 toHsl();
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;
469 break;
471 case XML_gray:
472 // change color to gray, weighted RGB: 22% red, 72% green, 6% blue
473 toRgb();
474 mnC1 = mnC2 = mnC3 = (mnC1 * 22 + mnC2 * 72 + mnC3 * 6) / 100;
475 break;
477 case XML_comp:
478 // comp: rotate hue by 180 degrees, do not change lum/sat
479 toHsl();
480 (mnC1 += 180 * PER_DEGREE) %= MAX_DEGREE;
481 break;
482 case XML_inv:
483 // invert percentual RGB values
484 toCrgb();
485 mnC1 = MAX_PERCENT - mnC1;
486 mnC2 = MAX_PERCENT - mnC2;
487 mnC3 = MAX_PERCENT - mnC3;
488 break;
490 case XML_gamma:
491 // increase gamma of color
492 toCrgb();
493 mnC1 = lclGamma( mnC1, INC_GAMMA );
494 mnC2 = lclGamma( mnC2, INC_GAMMA );
495 mnC3 = lclGamma( mnC3, INC_GAMMA );
496 break;
497 case XML_invGamma:
498 // decrease gamma of color
499 toCrgb();
500 mnC1 = lclGamma( mnC1, DEC_GAMMA );
501 mnC2 = lclGamma( mnC2, DEC_GAMMA );
502 mnC3 = lclGamma( mnC3, DEC_GAMMA );
503 break;
507 toRgb();
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
528 switch( meMode )
530 case COLOR_RGB:
531 // nothing to do
532 break;
533 case COLOR_CRGB:
534 meMode = COLOR_RGB;
535 mnC1 = lclCrgbCompToRgbComp( lclGamma( mnC1, INC_GAMMA ) );
536 mnC2 = lclCrgbCompToRgbComp( lclGamma( mnC2, INC_GAMMA ) );
537 mnC3 = lclCrgbCompToRgbComp( lclGamma( mnC3, INC_GAMMA ) );
538 break;
539 case COLOR_HSL:
541 meMode = COLOR_RGB;
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;
547 else if( mnC3 > 0 )
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
558 // apply saturation
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;
564 // apply luminance
565 double fLum = 2.0 * static_cast< double >( mnC3 ) / MAX_PERCENT - 1.0; // interval [-1.0, 1.0]
566 if( fLum < 0.0 )
568 double fShade = fLum + 1.0; // interval [0.0, 1.0] (black...full color)
569 fR *= fShade;
570 fG *= fShade;
571 fB *= fShade;
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 );
585 break;
586 default:
587 OSL_ENSURE( false, "Color::toRgb - unexpected color mode" );
591 void Color::toCrgb() const
593 switch( meMode )
595 case COLOR_HSL:
596 toRgb();
597 // run through!
598 case COLOR_RGB:
599 meMode = COLOR_CRGB;
600 mnC1 = lclGamma( lclRgbCompToCrgbComp( mnC1 ), DEC_GAMMA );
601 mnC2 = lclGamma( lclRgbCompToCrgbComp( mnC2 ), DEC_GAMMA );
602 mnC3 = lclGamma( lclRgbCompToCrgbComp( mnC3 ), DEC_GAMMA );
603 break;
604 case COLOR_CRGB:
605 // nothing to do
606 break;
607 default:
608 OSL_ENSURE( false, "Color::toCrgb - unexpected color mode" );
612 void Color::toHsl() const
614 switch( meMode )
616 case COLOR_CRGB:
617 toRgb();
618 // run through!
619 case COLOR_RGB:
621 meMode = COLOR_HSL;
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
631 mnC1 = 0;
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
644 mnC2 = 0;
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 );
650 break;
651 case COLOR_HSL:
652 // nothing to do
653 break;
654 default:
655 OSL_ENSURE( false, "Color::toHsl - unexpected color mode" );
659 // ============================================================================
661 } // namespace drawingml
662 } // namespace oox