xref: /AOO41X/main/oox/source/drawingml/color.cxx (revision ca5ec2004b000a7d9aaa8381be8ac2853e3b1dc7)
1*ca5ec200SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*ca5ec200SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*ca5ec200SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*ca5ec200SAndrew Rist  * distributed with this work for additional information
6*ca5ec200SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*ca5ec200SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*ca5ec200SAndrew Rist  * "License"); you may not use this file except in compliance
9*ca5ec200SAndrew Rist  * with the License.  You may obtain a copy of the License at
10cdf0e10cSrcweir  *
11*ca5ec200SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir  *
13*ca5ec200SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*ca5ec200SAndrew Rist  * software distributed under the License is distributed on an
15*ca5ec200SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*ca5ec200SAndrew Rist  * KIND, either express or implied.  See the License for the
17*ca5ec200SAndrew Rist  * specific language governing permissions and limitations
18*ca5ec200SAndrew Rist  * under the License.
19cdf0e10cSrcweir  *
20*ca5ec200SAndrew Rist  *************************************************************/
21*ca5ec200SAndrew Rist 
22*ca5ec200SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir #include "oox/drawingml/color.hxx"
25cdf0e10cSrcweir #include <algorithm>
26cdf0e10cSrcweir #include <math.h>
27cdf0e10cSrcweir #include "oox/helper/containerhelper.hxx"
28cdf0e10cSrcweir #include "oox/helper/graphichelper.hxx"
29cdf0e10cSrcweir #include "oox/drawingml/drawingmltypes.hxx"
30cdf0e10cSrcweir #include "oox/token/namespaces.hxx"
31cdf0e10cSrcweir #include "oox/token/tokens.hxx"
32cdf0e10cSrcweir 
33cdf0e10cSrcweir using ::rtl::OUString;
34cdf0e10cSrcweir 
35cdf0e10cSrcweir namespace oox {
36cdf0e10cSrcweir namespace drawingml {
37cdf0e10cSrcweir 
38cdf0e10cSrcweir // ============================================================================
39cdf0e10cSrcweir 
40cdf0e10cSrcweir namespace {
41cdf0e10cSrcweir 
42cdf0e10cSrcweir /** Global storage for predefined color values used in OOXML file formats. */
43cdf0e10cSrcweir struct PresetColorsPool
44cdf0e10cSrcweir {
45cdf0e10cSrcweir     typedef ::std::vector< sal_Int32 > ColorVector;
46cdf0e10cSrcweir 
47cdf0e10cSrcweir     ColorVector         maDmlColors;        /// Predefined colors in DrawingML, indexed by XML token.
48cdf0e10cSrcweir     ColorVector         maVmlColors;        /// Predefined colors in VML, indexed by XML token.
49cdf0e10cSrcweir 
50cdf0e10cSrcweir     explicit            PresetColorsPool();
51cdf0e10cSrcweir };
52cdf0e10cSrcweir 
53cdf0e10cSrcweir // ----------------------------------------------------------------------------
54cdf0e10cSrcweir 
PresetColorsPool()55cdf0e10cSrcweir PresetColorsPool::PresetColorsPool() :
56cdf0e10cSrcweir     maDmlColors( static_cast< size_t >( XML_TOKEN_COUNT ), API_RGB_TRANSPARENT ),
57cdf0e10cSrcweir     maVmlColors( static_cast< size_t >( XML_TOKEN_COUNT ), API_RGB_TRANSPARENT )
58cdf0e10cSrcweir {
59cdf0e10cSrcweir     // predefined colors in DrawingML (map XML token identifiers to RGB values)
60cdf0e10cSrcweir     static const sal_Int32 spnDmlColors[] =
61cdf0e10cSrcweir     {
62cdf0e10cSrcweir         XML_aliceBlue,         0xF0F8FF,    XML_antiqueWhite,      0xFAEBD7,
63cdf0e10cSrcweir         XML_aqua,              0x00FFFF,    XML_aquamarine,        0x7FFFD4,
64cdf0e10cSrcweir         XML_azure,             0xF0FFFF,    XML_beige,             0xF5F5DC,
65cdf0e10cSrcweir         XML_bisque,            0xFFE4C4,    XML_black,             0x000000,
66cdf0e10cSrcweir         XML_blanchedAlmond,    0xFFEBCD,    XML_blue,              0x0000FF,
67cdf0e10cSrcweir         XML_blueViolet,        0x8A2BE2,    XML_brown,             0xA52A2A,
68cdf0e10cSrcweir         XML_burlyWood,         0xDEB887,    XML_cadetBlue,         0x5F9EA0,
69cdf0e10cSrcweir         XML_chartreuse,        0x7FFF00,    XML_chocolate,         0xD2691E,
70cdf0e10cSrcweir         XML_coral,             0xFF7F50,    XML_cornflowerBlue,    0x6495ED,
71cdf0e10cSrcweir         XML_cornsilk,          0xFFF8DC,    XML_crimson,           0xDC143C,
72cdf0e10cSrcweir         XML_cyan,              0x00FFFF,    XML_deepPink,          0xFF1493,
73cdf0e10cSrcweir         XML_deepSkyBlue,       0x00BFFF,    XML_dimGray,           0x696969,
74cdf0e10cSrcweir         XML_dkBlue,            0x00008B,    XML_dkCyan,            0x008B8B,
75cdf0e10cSrcweir         XML_dkGoldenrod,       0xB8860B,    XML_dkGray,            0xA9A9A9,
76cdf0e10cSrcweir         XML_dkGreen,           0x006400,    XML_dkKhaki,           0xBDB76B,
77cdf0e10cSrcweir         XML_dkMagenta,         0x8B008B,    XML_dkOliveGreen,      0x556B2F,
78cdf0e10cSrcweir         XML_dkOrange,          0xFF8C00,    XML_dkOrchid,          0x9932CC,
79cdf0e10cSrcweir         XML_dkRed,             0x8B0000,    XML_dkSalmon,          0xE9967A,
80cdf0e10cSrcweir         XML_dkSeaGreen,        0x8FBC8B,    XML_dkSlateBlue,       0x483D8B,
81cdf0e10cSrcweir         XML_dkSlateGray,       0x2F4F4F,    XML_dkTurquoise,       0x00CED1,
82cdf0e10cSrcweir         XML_dkViolet,          0x9400D3,    XML_dodgerBlue,        0x1E90FF,
83cdf0e10cSrcweir         XML_firebrick,         0xB22222,    XML_floralWhite,       0xFFFAF0,
84cdf0e10cSrcweir         XML_forestGreen,       0x228B22,    XML_fuchsia,           0xFF00FF,
85cdf0e10cSrcweir         XML_gainsboro,         0xDCDCDC,    XML_ghostWhite,        0xF8F8FF,
86cdf0e10cSrcweir         XML_gold,              0xFFD700,    XML_goldenrod,         0xDAA520,
87cdf0e10cSrcweir         XML_gray,              0x808080,    XML_green,             0x008000,
88cdf0e10cSrcweir         XML_greenYellow,       0xADFF2F,    XML_honeydew,          0xF0FFF0,
89cdf0e10cSrcweir         XML_hotPink,           0xFF69B4,    XML_indianRed,         0xCD5C5C,
90cdf0e10cSrcweir         XML_indigo,            0x4B0082,    XML_ivory,             0xFFFFF0,
91cdf0e10cSrcweir         XML_khaki,             0xF0E68C,    XML_lavender,          0xE6E6FA,
92cdf0e10cSrcweir         XML_lavenderBlush,     0xFFF0F5,    XML_lawnGreen,         0x7CFC00,
93cdf0e10cSrcweir         XML_lemonChiffon,      0xFFFACD,    XML_lime,              0x00FF00,
94cdf0e10cSrcweir         XML_limeGreen,         0x32CD32,    XML_linen,             0xFAF0E6,
95cdf0e10cSrcweir         XML_ltBlue,            0xADD8E6,    XML_ltCoral,           0xF08080,
96cdf0e10cSrcweir         XML_ltCyan,            0xE0FFFF,    XML_ltGoldenrodYellow, 0xFAFA78,
97cdf0e10cSrcweir         XML_ltGray,            0xD3D3D3,    XML_ltGreen,           0x90EE90,
98cdf0e10cSrcweir         XML_ltPink,            0xFFB6C1,    XML_ltSalmon,          0xFFA07A,
99cdf0e10cSrcweir         XML_ltSeaGreen,        0x20B2AA,    XML_ltSkyBlue,         0x87CEFA,
100cdf0e10cSrcweir         XML_ltSlateGray,       0x778899,    XML_ltSteelBlue,       0xB0C4DE,
101cdf0e10cSrcweir         XML_ltYellow,          0xFFFFE0,    XML_magenta,           0xFF00FF,
102cdf0e10cSrcweir         XML_maroon,            0x800000,    XML_medAquamarine,     0x66CDAA,
103cdf0e10cSrcweir         XML_medBlue,           0x0000CD,    XML_medOrchid,         0xBA55D3,
104cdf0e10cSrcweir         XML_medPurple,         0x9370DB,    XML_medSeaGreen,       0x3CB371,
105cdf0e10cSrcweir         XML_medSlateBlue,      0x7B68EE,    XML_medSpringGreen,    0x00FA9A,
106cdf0e10cSrcweir         XML_medTurquoise,      0x48D1CC,    XML_medVioletRed,      0xC71585,
107cdf0e10cSrcweir         XML_midnightBlue,      0x191970,    XML_mintCream,         0xF5FFFA,
108cdf0e10cSrcweir         XML_mistyRose,         0xFFE4E1,    XML_moccasin,          0xFFE4B5,
109cdf0e10cSrcweir         XML_navajoWhite,       0xFFDEAD,    XML_navy,              0x000080,
110cdf0e10cSrcweir         XML_oldLace,           0xFDF5E6,    XML_olive,             0x808000,
111cdf0e10cSrcweir         XML_oliveDrab,         0x6B8E23,    XML_orange,            0xFFA500,
112cdf0e10cSrcweir         XML_orangeRed,         0xFF4500,    XML_orchid,            0xDA70D6,
113cdf0e10cSrcweir         XML_paleGoldenrod,     0xEEE8AA,    XML_paleGreen,         0x98FB98,
114cdf0e10cSrcweir         XML_paleTurquoise,     0xAFEEEE,    XML_paleVioletRed,     0xDB7093,
115cdf0e10cSrcweir         XML_papayaWhip,        0xFFEFD5,    XML_peachPuff,         0xFFDAB9,
116cdf0e10cSrcweir         XML_peru,              0xCD853F,    XML_pink,              0xFFC0CB,
117cdf0e10cSrcweir         XML_plum,              0xDDA0DD,    XML_powderBlue,        0xB0E0E6,
118cdf0e10cSrcweir         XML_purple,            0x800080,    XML_red,               0xFF0000,
119cdf0e10cSrcweir         XML_rosyBrown,         0xBC8F8F,    XML_royalBlue,         0x4169E1,
120cdf0e10cSrcweir         XML_saddleBrown,       0x8B4513,    XML_salmon,            0xFA8072,
121cdf0e10cSrcweir         XML_sandyBrown,        0xF4A460,    XML_seaGreen,          0x2E8B57,
122cdf0e10cSrcweir         XML_seaShell,          0xFFF5EE,    XML_sienna,            0xA0522D,
123cdf0e10cSrcweir         XML_silver,            0xC0C0C0,    XML_skyBlue,           0x87CEEB,
124cdf0e10cSrcweir         XML_slateBlue,         0x6A5ACD,    XML_slateGray,         0x708090,
125cdf0e10cSrcweir         XML_snow,              0xFFFAFA,    XML_springGreen,       0x00FF7F,
126cdf0e10cSrcweir         XML_steelBlue,         0x4682B4,    XML_tan,               0xD2B48C,
127cdf0e10cSrcweir         XML_teal,              0x008080,    XML_thistle,           0xD8BFD8,
128cdf0e10cSrcweir         XML_tomato,            0xFF6347,    XML_turquoise,         0x40E0D0,
129cdf0e10cSrcweir         XML_violet,            0xEE82EE,    XML_wheat,             0xF5DEB3,
130cdf0e10cSrcweir         XML_white,             0xFFFFFF,    XML_whiteSmoke,        0xF5F5F5,
131cdf0e10cSrcweir         XML_yellow,            0xFFFF00,    XML_yellowGreen,       0x9ACD32
132cdf0e10cSrcweir     };
133cdf0e10cSrcweir     for( const sal_Int32* pnEntry = spnDmlColors; pnEntry < STATIC_ARRAY_END( spnDmlColors ); pnEntry += 2 )
134cdf0e10cSrcweir         maDmlColors[ static_cast< size_t >( pnEntry[ 0 ] ) ] = pnEntry[ 1 ];
135cdf0e10cSrcweir 
136cdf0e10cSrcweir     // predefined colors in VML (map XML token identifiers to RGB values)
137cdf0e10cSrcweir     static const sal_Int32 spnVmlColors[] =
138cdf0e10cSrcweir     {
139cdf0e10cSrcweir         XML_aqua,              0x00FFFF,    XML_black,             0x000000,
140cdf0e10cSrcweir         XML_blue,              0x0000FF,    XML_fuchsia,           0xFF00FF,
141cdf0e10cSrcweir         XML_gray,              0x808080,    XML_green,             0x008000,
142cdf0e10cSrcweir         XML_lime,              0x00FF00,    XML_maroon,            0x800000,
143cdf0e10cSrcweir         XML_navy,              0x000080,    XML_olive,             0x808000,
144cdf0e10cSrcweir         XML_purple,            0x800080,    XML_red,               0xFF0000,
145cdf0e10cSrcweir         XML_silver,            0xC0C0C0,    XML_teal,              0x008080,
146cdf0e10cSrcweir         XML_white,             0xFFFFFF,    XML_yellow,            0xFFFF00
147cdf0e10cSrcweir     };
148cdf0e10cSrcweir     for( const sal_Int32* pnEntry = spnVmlColors; pnEntry < STATIC_ARRAY_END( spnVmlColors ); pnEntry += 2 )
149cdf0e10cSrcweir         maVmlColors[ static_cast< size_t >( pnEntry[ 0 ] ) ] = pnEntry[ 1 ];
150cdf0e10cSrcweir }
151cdf0e10cSrcweir 
152cdf0e10cSrcweir // ----------------------------------------------------------------------------
153cdf0e10cSrcweir 
154cdf0e10cSrcweir struct StaticPresetColorsPool : public ::rtl::Static< PresetColorsPool, StaticPresetColorsPool > {};
155cdf0e10cSrcweir 
156cdf0e10cSrcweir // ----------------------------------------------------------------------------
157cdf0e10cSrcweir 
158cdf0e10cSrcweir const double DEC_GAMMA          = 2.3;
159cdf0e10cSrcweir const double INC_GAMMA          = 1.0 / DEC_GAMMA;
160cdf0e10cSrcweir 
161cdf0e10cSrcweir // ----------------------------------------------------------------------------
162cdf0e10cSrcweir 
lclRgbToRgbComponents(sal_Int32 & ornR,sal_Int32 & ornG,sal_Int32 & ornB,sal_Int32 nRgb)163cdf0e10cSrcweir inline void lclRgbToRgbComponents( sal_Int32& ornR, sal_Int32& ornG, sal_Int32& ornB, sal_Int32 nRgb )
164cdf0e10cSrcweir {
165cdf0e10cSrcweir     ornR = (nRgb >> 16) & 0xFF;
166cdf0e10cSrcweir     ornG = (nRgb >> 8) & 0xFF;
167cdf0e10cSrcweir     ornB = nRgb & 0xFF;
168cdf0e10cSrcweir }
169cdf0e10cSrcweir 
lclRgbComponentsToRgb(sal_Int32 nR,sal_Int32 nG,sal_Int32 nB)170cdf0e10cSrcweir inline sal_Int32 lclRgbComponentsToRgb( sal_Int32 nR, sal_Int32 nG, sal_Int32 nB )
171cdf0e10cSrcweir {
172cdf0e10cSrcweir     return static_cast< sal_Int32 >( (nR << 16) | (nG << 8) | nB );
173cdf0e10cSrcweir }
174cdf0e10cSrcweir 
lclRgbCompToCrgbComp(sal_Int32 nRgbComp)175cdf0e10cSrcweir inline sal_Int32 lclRgbCompToCrgbComp( sal_Int32 nRgbComp )
176cdf0e10cSrcweir {
177cdf0e10cSrcweir     return static_cast< sal_Int32 >( nRgbComp * MAX_PERCENT / 255 );
178cdf0e10cSrcweir }
179cdf0e10cSrcweir 
lclCrgbCompToRgbComp(sal_Int32 nCrgbComp)180cdf0e10cSrcweir inline sal_Int32 lclCrgbCompToRgbComp( sal_Int32 nCrgbComp )
181cdf0e10cSrcweir {
182cdf0e10cSrcweir     return static_cast< sal_Int32 >( nCrgbComp * 255 / MAX_PERCENT );
183cdf0e10cSrcweir }
184cdf0e10cSrcweir 
lclGamma(sal_Int32 nComp,double fGamma)185cdf0e10cSrcweir inline sal_Int32 lclGamma( sal_Int32 nComp, double fGamma )
186cdf0e10cSrcweir {
187cdf0e10cSrcweir     return static_cast< sal_Int32 >( pow( static_cast< double >( nComp ) / MAX_PERCENT, fGamma ) * MAX_PERCENT + 0.5 );
188cdf0e10cSrcweir }
189cdf0e10cSrcweir 
lclSetValue(sal_Int32 & ornValue,sal_Int32 nNew,sal_Int32 nMax=MAX_PERCENT)190cdf0e10cSrcweir void lclSetValue( sal_Int32& ornValue, sal_Int32 nNew, sal_Int32 nMax = MAX_PERCENT )
191cdf0e10cSrcweir {
192cdf0e10cSrcweir     OSL_ENSURE( (0 <= nNew) && (nNew <= nMax), "lclSetValue - invalid value" );
193cdf0e10cSrcweir     if( (0 <= nNew) && (nNew <= nMax) )
194cdf0e10cSrcweir         ornValue = nNew;
195cdf0e10cSrcweir }
196cdf0e10cSrcweir 
lclModValue(sal_Int32 & ornValue,sal_Int32 nMod,sal_Int32 nMax=MAX_PERCENT)197cdf0e10cSrcweir void lclModValue( sal_Int32& ornValue, sal_Int32 nMod, sal_Int32 nMax = MAX_PERCENT )
198cdf0e10cSrcweir {
199cdf0e10cSrcweir     OSL_ENSURE( (0 <= nMod), "lclModValue - invalid modificator" );
200cdf0e10cSrcweir     ornValue = getLimitedValue< sal_Int32, double >( static_cast< double >( ornValue ) * nMod / MAX_PERCENT, 0, nMax );
201cdf0e10cSrcweir }
202cdf0e10cSrcweir 
lclOffValue(sal_Int32 & ornValue,sal_Int32 nOff,sal_Int32 nMax=MAX_PERCENT)203cdf0e10cSrcweir void lclOffValue( sal_Int32& ornValue, sal_Int32 nOff, sal_Int32 nMax = MAX_PERCENT )
204cdf0e10cSrcweir {
205cdf0e10cSrcweir     OSL_ENSURE( (-nMax <= nOff) && (nOff <= nMax), "lclOffValue - invalid offset" );
206cdf0e10cSrcweir     ornValue = getLimitedValue< sal_Int32, sal_Int32 >( ornValue + nOff, 0, nMax );
207cdf0e10cSrcweir }
208cdf0e10cSrcweir 
209cdf0e10cSrcweir } // namespace
210cdf0e10cSrcweir 
211cdf0e10cSrcweir // ============================================================================
212cdf0e10cSrcweir 
Color()213cdf0e10cSrcweir Color::Color() :
214cdf0e10cSrcweir     meMode( COLOR_UNUSED ),
215cdf0e10cSrcweir     mnC1( 0 ),
216cdf0e10cSrcweir     mnC2( 0 ),
217cdf0e10cSrcweir     mnC3( 0 ),
218cdf0e10cSrcweir     mnAlpha( MAX_PERCENT )
219cdf0e10cSrcweir {
220cdf0e10cSrcweir }
221cdf0e10cSrcweir 
~Color()222cdf0e10cSrcweir Color::~Color()
223cdf0e10cSrcweir {
224cdf0e10cSrcweir }
225cdf0e10cSrcweir 
getDmlPresetColor(sal_Int32 nToken,sal_Int32 nDefaultRgb)226cdf0e10cSrcweir /*static*/ sal_Int32 Color::getDmlPresetColor( sal_Int32 nToken, sal_Int32 nDefaultRgb )
227cdf0e10cSrcweir {
228cdf0e10cSrcweir     /*  Do not pass nDefaultRgb to ContainerHelper::getVectorElement(), to be
229cdf0e10cSrcweir         able to catch the existing vector entries without corresponding XML
230cdf0e10cSrcweir         token identifier. */
231cdf0e10cSrcweir     sal_Int32 nRgbValue = ContainerHelper::getVectorElement( StaticPresetColorsPool::get().maDmlColors, nToken, API_RGB_TRANSPARENT );
232cdf0e10cSrcweir     return (nRgbValue >= 0) ? nRgbValue : nDefaultRgb;
233cdf0e10cSrcweir }
234cdf0e10cSrcweir 
getVmlPresetColor(sal_Int32 nToken,sal_Int32 nDefaultRgb)235cdf0e10cSrcweir /*static*/ sal_Int32 Color::getVmlPresetColor( sal_Int32 nToken, sal_Int32 nDefaultRgb )
236cdf0e10cSrcweir {
237cdf0e10cSrcweir     /*  Do not pass nDefaultRgb to ContainerHelper::getVectorElement(), to be
238cdf0e10cSrcweir         able to catch the existing vector entries without corresponding XML
239cdf0e10cSrcweir         token identifier. */
240cdf0e10cSrcweir     sal_Int32 nRgbValue = ContainerHelper::getVectorElement( StaticPresetColorsPool::get().maVmlColors, nToken, API_RGB_TRANSPARENT );
241cdf0e10cSrcweir     return (nRgbValue >= 0) ? nRgbValue : nDefaultRgb;
242cdf0e10cSrcweir }
243cdf0e10cSrcweir 
setUnused()244cdf0e10cSrcweir void Color::setUnused()
245cdf0e10cSrcweir {
246cdf0e10cSrcweir     meMode = COLOR_UNUSED;
247cdf0e10cSrcweir }
248cdf0e10cSrcweir 
setSrgbClr(sal_Int32 nRgb)249cdf0e10cSrcweir void Color::setSrgbClr( sal_Int32 nRgb )
250cdf0e10cSrcweir {
251cdf0e10cSrcweir     OSL_ENSURE( (0 <= nRgb) && (nRgb <= 0xFFFFFF), "Color::setSrgbClr - invalid RGB value" );
252cdf0e10cSrcweir     meMode = COLOR_RGB;
253cdf0e10cSrcweir     lclRgbToRgbComponents( mnC1, mnC2, mnC3, nRgb );
254cdf0e10cSrcweir }
255cdf0e10cSrcweir 
setScrgbClr(sal_Int32 nR,sal_Int32 nG,sal_Int32 nB)256cdf0e10cSrcweir void Color::setScrgbClr( sal_Int32 nR, sal_Int32 nG, sal_Int32 nB )
257cdf0e10cSrcweir {
258cdf0e10cSrcweir     OSL_ENSURE( (0 <= nR) && (nR <= MAX_PERCENT), "Color::setScrgbClr - invalid red value" );
259cdf0e10cSrcweir     OSL_ENSURE( (0 <= nG) && (nG <= MAX_PERCENT), "Color::setScrgbClr - invalid green value" );
260cdf0e10cSrcweir     OSL_ENSURE( (0 <= nB) && (nB <= MAX_PERCENT), "Color::setScrgbClr - invalid blue value" );
261cdf0e10cSrcweir     meMode = COLOR_CRGB;
262cdf0e10cSrcweir     mnC1 = getLimitedValue< sal_Int32, sal_Int32 >( nR, 0, MAX_PERCENT );
263cdf0e10cSrcweir     mnC2 = getLimitedValue< sal_Int32, sal_Int32 >( nG, 0, MAX_PERCENT );
264cdf0e10cSrcweir     mnC3 = getLimitedValue< sal_Int32, sal_Int32 >( nB, 0, MAX_PERCENT );
265cdf0e10cSrcweir }
266cdf0e10cSrcweir 
setHslClr(sal_Int32 nHue,sal_Int32 nSat,sal_Int32 nLum)267cdf0e10cSrcweir void Color::setHslClr( sal_Int32 nHue, sal_Int32 nSat, sal_Int32 nLum )
268cdf0e10cSrcweir {
269cdf0e10cSrcweir     OSL_ENSURE( (0 <= nHue) && (nHue <= MAX_DEGREE), "Color::setHslClr - invalid hue value" );
270cdf0e10cSrcweir     OSL_ENSURE( (0 <= nSat) && (nSat <= MAX_PERCENT), "Color::setHslClr - invalid saturation value" );
271cdf0e10cSrcweir     OSL_ENSURE( (0 <= nLum) && (nLum <= MAX_PERCENT), "Color::setHslClr - invalid luminance value" );
272cdf0e10cSrcweir     meMode = COLOR_HSL;
273cdf0e10cSrcweir     mnC1 = getLimitedValue< sal_Int32, sal_Int32 >( nHue, 0, MAX_DEGREE );
274cdf0e10cSrcweir     mnC2 = getLimitedValue< sal_Int32, sal_Int32 >( nSat, 0, MAX_PERCENT );
275cdf0e10cSrcweir     mnC3 = getLimitedValue< sal_Int32, sal_Int32 >( nLum, 0, MAX_PERCENT );
276cdf0e10cSrcweir }
277cdf0e10cSrcweir 
setPrstClr(sal_Int32 nToken)278cdf0e10cSrcweir void Color::setPrstClr( sal_Int32 nToken )
279cdf0e10cSrcweir {
280cdf0e10cSrcweir     sal_Int32 nRgbValue = getDmlPresetColor( nToken, API_RGB_TRANSPARENT );
281cdf0e10cSrcweir     OSL_ENSURE( nRgbValue >= 0, "Color::setPrstClr - invalid preset color token" );
282cdf0e10cSrcweir     if( nRgbValue >= 0 )
283cdf0e10cSrcweir         setSrgbClr( nRgbValue );
284cdf0e10cSrcweir }
285cdf0e10cSrcweir 
setSchemeClr(sal_Int32 nToken)286cdf0e10cSrcweir void Color::setSchemeClr( sal_Int32 nToken )
287cdf0e10cSrcweir {
288cdf0e10cSrcweir     OSL_ENSURE( nToken != XML_TOKEN_INVALID, "Color::setSchemeClr - invalid color token" );
289cdf0e10cSrcweir     meMode = (nToken == XML_phClr) ? COLOR_PH : COLOR_SCHEME;
290cdf0e10cSrcweir     mnC1 = nToken;
291cdf0e10cSrcweir }
292cdf0e10cSrcweir 
setPaletteClr(sal_Int32 nPaletteIdx)293cdf0e10cSrcweir void Color::setPaletteClr( sal_Int32 nPaletteIdx )
294cdf0e10cSrcweir {
295cdf0e10cSrcweir     OSL_ENSURE( nPaletteIdx >= 0, "Color::setPaletteClr - invalid palette index" );
296cdf0e10cSrcweir     meMode = COLOR_PALETTE;
297cdf0e10cSrcweir     mnC1 = nPaletteIdx;
298cdf0e10cSrcweir }
299cdf0e10cSrcweir 
setSysClr(sal_Int32 nToken,sal_Int32 nLastRgb)300cdf0e10cSrcweir void Color::setSysClr( sal_Int32 nToken, sal_Int32 nLastRgb )
301cdf0e10cSrcweir {
302cdf0e10cSrcweir     OSL_ENSURE( (-1 <= nLastRgb) && (nLastRgb <= 0xFFFFFF), "Color::setSysClr - invalid RGB value" );
303cdf0e10cSrcweir     meMode = COLOR_SYSTEM;
304cdf0e10cSrcweir     mnC1 = nToken;
305cdf0e10cSrcweir     mnC2 = nLastRgb;
306cdf0e10cSrcweir }
307cdf0e10cSrcweir 
addTransformation(sal_Int32 nElement,sal_Int32 nValue)308cdf0e10cSrcweir void Color::addTransformation( sal_Int32 nElement, sal_Int32 nValue )
309cdf0e10cSrcweir {
310cdf0e10cSrcweir     /*  Execute alpha transformations directly, store other transformations in
311cdf0e10cSrcweir         a vector, they may depend on a scheme base color which will be resolved
312cdf0e10cSrcweir         in Color::getColor(). */
313cdf0e10cSrcweir     sal_Int32 nToken = getBaseToken( nElement );
314cdf0e10cSrcweir     switch( nToken )
315cdf0e10cSrcweir     {
316cdf0e10cSrcweir         case XML_alpha:     lclSetValue( mnAlpha, nValue ); break;
317cdf0e10cSrcweir         case XML_alphaMod:  lclModValue( mnAlpha, nValue ); break;
318cdf0e10cSrcweir         case XML_alphaOff:  lclOffValue( mnAlpha, nValue ); break;
319cdf0e10cSrcweir         default:            maTransforms.push_back( Transformation( nToken, nValue ) );
320cdf0e10cSrcweir     }
321cdf0e10cSrcweir }
322cdf0e10cSrcweir 
addChartTintTransformation(double fTint)323cdf0e10cSrcweir void Color::addChartTintTransformation( double fTint )
324cdf0e10cSrcweir {
325cdf0e10cSrcweir     sal_Int32 nValue = getLimitedValue< sal_Int32, double >( fTint * MAX_PERCENT + 0.5, -MAX_PERCENT, MAX_PERCENT );
326cdf0e10cSrcweir     if( nValue < 0 )
327cdf0e10cSrcweir         maTransforms.push_back( Transformation( XML_shade, nValue + MAX_PERCENT ) );
328cdf0e10cSrcweir     else if( nValue > 0 )
329cdf0e10cSrcweir         maTransforms.push_back( Transformation( XML_tint, MAX_PERCENT - nValue ) );
330cdf0e10cSrcweir }
331cdf0e10cSrcweir 
addExcelTintTransformation(double fTint)332cdf0e10cSrcweir void Color::addExcelTintTransformation( double fTint )
333cdf0e10cSrcweir {
334cdf0e10cSrcweir     sal_Int32 nValue = getLimitedValue< sal_Int32, double >( fTint * MAX_PERCENT + 0.5, -MAX_PERCENT, MAX_PERCENT );
335cdf0e10cSrcweir     maTransforms.push_back( Transformation( XLS_TOKEN( tint ), nValue ) );
336cdf0e10cSrcweir }
337cdf0e10cSrcweir 
clearTransformations()338cdf0e10cSrcweir void Color::clearTransformations()
339cdf0e10cSrcweir {
340cdf0e10cSrcweir     maTransforms.clear();
341cdf0e10cSrcweir     clearTransparence();
342cdf0e10cSrcweir }
343cdf0e10cSrcweir 
clearTransparence()344cdf0e10cSrcweir void Color::clearTransparence()
345cdf0e10cSrcweir {
346cdf0e10cSrcweir     mnAlpha = MAX_PERCENT;
347cdf0e10cSrcweir }
348cdf0e10cSrcweir 
getColor(const GraphicHelper & rGraphicHelper,sal_Int32 nPhClr) const349cdf0e10cSrcweir sal_Int32 Color::getColor( const GraphicHelper& rGraphicHelper, sal_Int32 nPhClr ) const
350cdf0e10cSrcweir {
351cdf0e10cSrcweir     /*  Special handling for theme style list placeholder colors (state
352cdf0e10cSrcweir         COLOR_PH), Color::getColor() may be called with different placeholder
353cdf0e10cSrcweir         colors in the nPhClr parameter. Therefore, the resolved color will not
354cdf0e10cSrcweir         be stored in this object, thus the state COLOR_FINAL will not be
355cdf0e10cSrcweir         reached and the transformation container will not be cleared, but the
356cdf0e10cSrcweir         original COLOR_PH state will be restored instead. */
357cdf0e10cSrcweir     bool bIsPh = false;
358cdf0e10cSrcweir 
359cdf0e10cSrcweir     switch( meMode )
360cdf0e10cSrcweir     {
361cdf0e10cSrcweir         case COLOR_UNUSED:  mnC1 = API_RGB_TRANSPARENT; break;
362cdf0e10cSrcweir 
363cdf0e10cSrcweir         case COLOR_RGB:     break;  // nothing to do
364cdf0e10cSrcweir         case COLOR_CRGB:    break;  // nothing to do
365cdf0e10cSrcweir         case COLOR_HSL:     break;  // nothing to do
366cdf0e10cSrcweir 
367cdf0e10cSrcweir         case COLOR_SCHEME:  setResolvedRgb( rGraphicHelper.getSchemeColor( mnC1 ) );        break;
368cdf0e10cSrcweir         case COLOR_PALETTE: setResolvedRgb( rGraphicHelper.getPaletteColor( mnC1 ) );       break;
369cdf0e10cSrcweir         case COLOR_SYSTEM:  setResolvedRgb( rGraphicHelper.getSystemColor( mnC1, mnC2 ) );  break;
370cdf0e10cSrcweir         case COLOR_PH:      setResolvedRgb( nPhClr ); bIsPh = true;                         break;
371cdf0e10cSrcweir 
372cdf0e10cSrcweir         case COLOR_FINAL:   return mnC1;
373cdf0e10cSrcweir     }
374cdf0e10cSrcweir 
375cdf0e10cSrcweir     // if color is UNUSED or turns to UNUSED in setResolvedRgb, do not perform transformations
376cdf0e10cSrcweir     if( meMode != COLOR_UNUSED )
377cdf0e10cSrcweir     {
378cdf0e10cSrcweir         for( TransformVec::const_iterator aIt = maTransforms.begin(), aEnd = maTransforms.end(); aIt != aEnd; ++aIt )
379cdf0e10cSrcweir         {
380cdf0e10cSrcweir             switch( aIt->mnToken )
381cdf0e10cSrcweir             {
382cdf0e10cSrcweir                 case XML_red:       toCrgb(); lclSetValue( mnC1, aIt->mnValue );    break;
383cdf0e10cSrcweir                 case XML_redMod:    toCrgb(); lclModValue( mnC1, aIt->mnValue );    break;
384cdf0e10cSrcweir                 case XML_redOff:    toCrgb(); lclOffValue( mnC1, aIt->mnValue );    break;
385cdf0e10cSrcweir                 case XML_green:     toCrgb(); lclSetValue( mnC2, aIt->mnValue );    break;
386cdf0e10cSrcweir                 case XML_greenMod:  toCrgb(); lclModValue( mnC2, aIt->mnValue );    break;
387cdf0e10cSrcweir                 case XML_greenOff:  toCrgb(); lclOffValue( mnC2, aIt->mnValue );    break;
388cdf0e10cSrcweir                 case XML_blue:      toCrgb(); lclSetValue( mnC3, aIt->mnValue );    break;
389cdf0e10cSrcweir                 case XML_blueMod:   toCrgb(); lclModValue( mnC3, aIt->mnValue );    break;
390cdf0e10cSrcweir                 case XML_blueOff:   toCrgb(); lclOffValue( mnC3, aIt->mnValue );    break;
391cdf0e10cSrcweir 
392cdf0e10cSrcweir                 case XML_hue:       toHsl(); lclSetValue( mnC1, aIt->mnValue, MAX_DEGREE ); break;
393cdf0e10cSrcweir                 case XML_hueMod:    toHsl(); lclModValue( mnC1, aIt->mnValue, MAX_DEGREE ); break;
394cdf0e10cSrcweir                 case XML_hueOff:    toHsl(); lclOffValue( mnC1, aIt->mnValue, MAX_DEGREE ); break;
395cdf0e10cSrcweir                 case XML_sat:       toHsl(); lclSetValue( mnC2, aIt->mnValue );             break;
396cdf0e10cSrcweir                 case XML_satMod:    toHsl(); lclModValue( mnC2, aIt->mnValue );             break;
397cdf0e10cSrcweir                 case XML_satOff:    toHsl(); lclOffValue( mnC2, aIt->mnValue );             break;
398cdf0e10cSrcweir 
399cdf0e10cSrcweir                 case XML_lum:
400cdf0e10cSrcweir                     toHsl();
401cdf0e10cSrcweir                     lclSetValue( mnC3, aIt->mnValue );
402cdf0e10cSrcweir                     // if color changes to black or white, it will stay gray if luminance changes again
403cdf0e10cSrcweir                     if( (mnC3 == 0) || (mnC3 == MAX_PERCENT) ) mnC2 = 0;
404cdf0e10cSrcweir                 break;
405cdf0e10cSrcweir                 case XML_lumMod:
406cdf0e10cSrcweir                     toHsl();
407cdf0e10cSrcweir                     lclModValue( mnC3, aIt->mnValue );
408cdf0e10cSrcweir                     // if color changes to black or white, it will stay gray if luminance changes again
409cdf0e10cSrcweir                     if( (mnC3 == 0) || (mnC3 == MAX_PERCENT) ) mnC2 = 0;
410cdf0e10cSrcweir                 break;
411cdf0e10cSrcweir                 case XML_lumOff:
412cdf0e10cSrcweir                     toHsl();
413cdf0e10cSrcweir                     lclOffValue( mnC3, aIt->mnValue );
414cdf0e10cSrcweir                     // if color changes to black or white, it will stay gray if luminance changes again
415cdf0e10cSrcweir                     if( (mnC3 == 0) || (mnC3 == MAX_PERCENT) ) mnC2 = 0;
416cdf0e10cSrcweir                 break;
417cdf0e10cSrcweir 
418cdf0e10cSrcweir                 case XML_shade:
419cdf0e10cSrcweir                     // shade: 0% = black, 100% = original color
420cdf0e10cSrcweir                     toCrgb();
421cdf0e10cSrcweir                     OSL_ENSURE( (0 <= aIt->mnValue) && (aIt->mnValue <= MAX_PERCENT), "Color::getColor - invalid shade value" );
422cdf0e10cSrcweir                     if( (0 <= aIt->mnValue) && (aIt->mnValue <= MAX_PERCENT) )
423cdf0e10cSrcweir                     {
424cdf0e10cSrcweir                         double fFactor = static_cast< double >( aIt->mnValue ) / MAX_PERCENT;
425cdf0e10cSrcweir                         mnC1 = static_cast< sal_Int32 >( mnC1 * fFactor );
426cdf0e10cSrcweir                         mnC2 = static_cast< sal_Int32 >( mnC2 * fFactor );
427cdf0e10cSrcweir                         mnC3 = static_cast< sal_Int32 >( mnC3 * fFactor );
428cdf0e10cSrcweir                     }
429cdf0e10cSrcweir                 break;
430cdf0e10cSrcweir                 case XML_tint:
431cdf0e10cSrcweir                     // tint: 0% = white, 100% = original color
432cdf0e10cSrcweir                     toCrgb();
433cdf0e10cSrcweir                     OSL_ENSURE( (0 <= aIt->mnValue) && (aIt->mnValue <= MAX_PERCENT), "Color::getColor - invalid tint value" );
434cdf0e10cSrcweir                     if( (0 <= aIt->mnValue) && (aIt->mnValue <= MAX_PERCENT) )
435cdf0e10cSrcweir                     {
436cdf0e10cSrcweir                         double fFactor = static_cast< double >( aIt->mnValue ) / MAX_PERCENT;
437cdf0e10cSrcweir                         mnC1 = static_cast< sal_Int32 >( MAX_PERCENT - (MAX_PERCENT - mnC1) * fFactor );
438cdf0e10cSrcweir                         mnC2 = static_cast< sal_Int32 >( MAX_PERCENT - (MAX_PERCENT - mnC2) * fFactor );
439cdf0e10cSrcweir                         mnC3 = static_cast< sal_Int32 >( MAX_PERCENT - (MAX_PERCENT - mnC3) * fFactor );
440cdf0e10cSrcweir                     }
441cdf0e10cSrcweir                 break;
442cdf0e10cSrcweir                 case XLS_TOKEN( tint ):
443cdf0e10cSrcweir                     // Excel tint: move luminance relative to current value
444cdf0e10cSrcweir                     toHsl();
445cdf0e10cSrcweir                     OSL_ENSURE( (-MAX_PERCENT <= aIt->mnValue) && (aIt->mnValue <= MAX_PERCENT), "Color::getColor - invalid tint value" );
446cdf0e10cSrcweir                     if( (-MAX_PERCENT <= aIt->mnValue) && (aIt->mnValue < 0) )
447cdf0e10cSrcweir                     {
448cdf0e10cSrcweir                         // negative: luminance towards 0% (black)
449cdf0e10cSrcweir                         lclModValue( mnC3, aIt->mnValue + MAX_PERCENT );
450cdf0e10cSrcweir                     }
451cdf0e10cSrcweir                     else if( (0 < aIt->mnValue) && (aIt->mnValue <= MAX_PERCENT) )
452cdf0e10cSrcweir                     {
453cdf0e10cSrcweir                         // positive: luminance towards 100% (white)
454cdf0e10cSrcweir                         mnC3 = MAX_PERCENT - mnC3;
455cdf0e10cSrcweir                         lclModValue( mnC3, MAX_PERCENT - aIt->mnValue );
456cdf0e10cSrcweir                         mnC3 = MAX_PERCENT - mnC3;
457cdf0e10cSrcweir                     }
458cdf0e10cSrcweir                 break;
459cdf0e10cSrcweir 
460cdf0e10cSrcweir                 case XML_gray:
461cdf0e10cSrcweir                     // change color to gray, weighted RGB: 22% red, 72% green, 6% blue
462cdf0e10cSrcweir                     toRgb();
463cdf0e10cSrcweir                     mnC1 = mnC2 = mnC3 = (mnC1 * 22 + mnC2 * 72 + mnC3 * 6) / 100;
464cdf0e10cSrcweir                 break;
465cdf0e10cSrcweir 
466cdf0e10cSrcweir                 case XML_comp:
467cdf0e10cSrcweir                     // comp: rotate hue by 180 degrees, do not change lum/sat
468cdf0e10cSrcweir                     toHsl();
469cdf0e10cSrcweir                     (mnC1 += 180 * PER_DEGREE) %= MAX_DEGREE;
470cdf0e10cSrcweir                 break;
471cdf0e10cSrcweir                 case XML_inv:
472cdf0e10cSrcweir                     // invert percentual RGB values
473cdf0e10cSrcweir                     toCrgb();
474cdf0e10cSrcweir                     mnC1 = MAX_PERCENT - mnC1;
475cdf0e10cSrcweir                     mnC2 = MAX_PERCENT - mnC2;
476cdf0e10cSrcweir                     mnC3 = MAX_PERCENT - mnC3;
477cdf0e10cSrcweir                 break;
478cdf0e10cSrcweir 
479cdf0e10cSrcweir                 case XML_gamma:
480cdf0e10cSrcweir                     // increase gamma of color
481cdf0e10cSrcweir                     toCrgb();
482cdf0e10cSrcweir                     mnC1 = lclGamma( mnC1, INC_GAMMA );
483cdf0e10cSrcweir                     mnC2 = lclGamma( mnC2, INC_GAMMA );
484cdf0e10cSrcweir                     mnC3 = lclGamma( mnC3, INC_GAMMA );
485cdf0e10cSrcweir                 break;
486cdf0e10cSrcweir                 case XML_invGamma:
487cdf0e10cSrcweir                     // decrease gamma of color
488cdf0e10cSrcweir                     toCrgb();
489cdf0e10cSrcweir                     mnC1 = lclGamma( mnC1, DEC_GAMMA );
490cdf0e10cSrcweir                     mnC2 = lclGamma( mnC2, DEC_GAMMA );
491cdf0e10cSrcweir                     mnC3 = lclGamma( mnC3, DEC_GAMMA );
492cdf0e10cSrcweir                 break;
493cdf0e10cSrcweir             }
494cdf0e10cSrcweir         }
495cdf0e10cSrcweir 
496cdf0e10cSrcweir         // store resulting RGB value in mnC1
497cdf0e10cSrcweir         toRgb();
498cdf0e10cSrcweir         mnC1 = lclRgbComponentsToRgb( mnC1, mnC2, mnC3 );
499cdf0e10cSrcweir     }
500cdf0e10cSrcweir     else // if( meMode != COLOR_UNUSED )
501cdf0e10cSrcweir     {
502cdf0e10cSrcweir         mnC1 = API_RGB_TRANSPARENT;
503cdf0e10cSrcweir     }
504cdf0e10cSrcweir 
505cdf0e10cSrcweir     meMode = bIsPh ? COLOR_PH : COLOR_FINAL;
506cdf0e10cSrcweir     if( meMode == COLOR_FINAL )
507cdf0e10cSrcweir         maTransforms.clear();
508cdf0e10cSrcweir     return mnC1;
509cdf0e10cSrcweir }
510cdf0e10cSrcweir 
hasTransparency() const511cdf0e10cSrcweir bool Color::hasTransparency() const
512cdf0e10cSrcweir {
513cdf0e10cSrcweir     return mnAlpha < MAX_PERCENT;
514cdf0e10cSrcweir }
515cdf0e10cSrcweir 
getTransparency() const516cdf0e10cSrcweir sal_Int16 Color::getTransparency() const
517cdf0e10cSrcweir {
518cdf0e10cSrcweir     return static_cast< sal_Int16 >( (MAX_PERCENT - mnAlpha) / PER_PERCENT );
519cdf0e10cSrcweir }
520cdf0e10cSrcweir 
521cdf0e10cSrcweir // private --------------------------------------------------------------------
522cdf0e10cSrcweir 
setResolvedRgb(sal_Int32 nRgb) const523cdf0e10cSrcweir void Color::setResolvedRgb( sal_Int32 nRgb ) const
524cdf0e10cSrcweir {
525cdf0e10cSrcweir     meMode = (nRgb < 0) ? COLOR_UNUSED : COLOR_RGB;
526cdf0e10cSrcweir     lclRgbToRgbComponents( mnC1, mnC2, mnC3, nRgb );
527cdf0e10cSrcweir }
528cdf0e10cSrcweir 
toRgb() const529cdf0e10cSrcweir void Color::toRgb() const
530cdf0e10cSrcweir {
531cdf0e10cSrcweir     switch( meMode )
532cdf0e10cSrcweir     {
533cdf0e10cSrcweir         case COLOR_RGB:
534cdf0e10cSrcweir             // nothing to do
535cdf0e10cSrcweir         break;
536cdf0e10cSrcweir         case COLOR_CRGB:
537cdf0e10cSrcweir             meMode = COLOR_RGB;
538cdf0e10cSrcweir             mnC1 = lclCrgbCompToRgbComp( lclGamma( mnC1, INC_GAMMA ) );
539cdf0e10cSrcweir             mnC2 = lclCrgbCompToRgbComp( lclGamma( mnC2, INC_GAMMA ) );
540cdf0e10cSrcweir             mnC3 = lclCrgbCompToRgbComp( lclGamma( mnC3, INC_GAMMA ) );
541cdf0e10cSrcweir         break;
542cdf0e10cSrcweir         case COLOR_HSL:
543cdf0e10cSrcweir         {
544cdf0e10cSrcweir             meMode = COLOR_RGB;
545cdf0e10cSrcweir             double fR = 0.0, fG = 0.0, fB = 0.0;
546cdf0e10cSrcweir             if( (mnC2 == 0) || (mnC3 == MAX_PERCENT) )
547cdf0e10cSrcweir             {
548cdf0e10cSrcweir                 fR = fG = fB = static_cast< double >( mnC3 ) / MAX_PERCENT;
549cdf0e10cSrcweir             }
550cdf0e10cSrcweir             else if( mnC3 > 0 )
551cdf0e10cSrcweir             {
552cdf0e10cSrcweir                 // base color from hue
553cdf0e10cSrcweir                 double fHue = static_cast< double >( mnC1 ) / MAX_DEGREE * 6.0; // interval [0.0, 6.0)
554cdf0e10cSrcweir                 if( fHue <= 1.0 )       { fR = 1.0; fG = fHue; }        // red...yellow
555cdf0e10cSrcweir                 else if( fHue <= 2.0 )  { fR = 2.0 - fHue; fG = 1.0; }  // yellow...green
556cdf0e10cSrcweir                 else if( fHue <= 3.0 )  { fG = 1.0; fB = fHue - 2.0; }  // green...cyan
557cdf0e10cSrcweir                 else if( fHue <= 4.0 )  { fG = 4.0 - fHue; fB = 1.0; }  // cyan...blue
558cdf0e10cSrcweir                 else if( fHue <= 5.0 )  { fR = fHue - 4.0; fB = 1.0; }  // blue...magenta
559cdf0e10cSrcweir                 else                    { fR = 1.0; fB = 6.0 - fHue; }  // magenta...red
560cdf0e10cSrcweir 
561cdf0e10cSrcweir                 // apply saturation
562cdf0e10cSrcweir                 double fSat = static_cast< double >( mnC2 ) / MAX_PERCENT;
563cdf0e10cSrcweir                 fR = (fR - 0.5) * fSat + 0.5;
564cdf0e10cSrcweir                 fG = (fG - 0.5) * fSat + 0.5;
565cdf0e10cSrcweir                 fB = (fB - 0.5) * fSat + 0.5;
566cdf0e10cSrcweir 
567cdf0e10cSrcweir                 // apply luminance
568cdf0e10cSrcweir                 double fLum = 2.0 * static_cast< double >( mnC3 ) / MAX_PERCENT - 1.0;  // interval [-1.0, 1.0]
569cdf0e10cSrcweir                 if( fLum < 0.0 )
570cdf0e10cSrcweir                 {
571cdf0e10cSrcweir                     double fShade = fLum + 1.0; // interval [0.0, 1.0] (black...full color)
572cdf0e10cSrcweir                     fR *= fShade;
573cdf0e10cSrcweir                     fG *= fShade;
574cdf0e10cSrcweir                     fB *= fShade;
575cdf0e10cSrcweir                 }
576cdf0e10cSrcweir                 else if( fLum > 0.0 )
577cdf0e10cSrcweir                 {
578cdf0e10cSrcweir                     double fTint = 1.0 - fLum;  // interval [0.0, 1.0] (white...full color)
579cdf0e10cSrcweir                     fR = 1.0 - ((1.0 - fR) * fTint);
580cdf0e10cSrcweir                     fG = 1.0 - ((1.0 - fG) * fTint);
581cdf0e10cSrcweir                     fB = 1.0 - ((1.0 - fB) * fTint);
582cdf0e10cSrcweir                 }
583cdf0e10cSrcweir             }
584cdf0e10cSrcweir             mnC1 = static_cast< sal_Int32 >( fR * 255.0 + 0.5 );
585cdf0e10cSrcweir             mnC2 = static_cast< sal_Int32 >( fG * 255.0 + 0.5 );
586cdf0e10cSrcweir             mnC3 = static_cast< sal_Int32 >( fB * 255.0 + 0.5 );
587cdf0e10cSrcweir         }
588cdf0e10cSrcweir         break;
589cdf0e10cSrcweir         default:
590cdf0e10cSrcweir             OSL_ENSURE( false, "Color::toRgb - unexpected color mode" );
591cdf0e10cSrcweir     }
592cdf0e10cSrcweir }
593cdf0e10cSrcweir 
toCrgb() const594cdf0e10cSrcweir void Color::toCrgb() const
595cdf0e10cSrcweir {
596cdf0e10cSrcweir     switch( meMode )
597cdf0e10cSrcweir     {
598cdf0e10cSrcweir         case COLOR_HSL:
599cdf0e10cSrcweir             toRgb();
600cdf0e10cSrcweir             // run through!
601cdf0e10cSrcweir         case COLOR_RGB:
602cdf0e10cSrcweir             meMode = COLOR_CRGB;
603cdf0e10cSrcweir             mnC1 = lclGamma( lclRgbCompToCrgbComp( mnC1 ), DEC_GAMMA );
604cdf0e10cSrcweir             mnC2 = lclGamma( lclRgbCompToCrgbComp( mnC2 ), DEC_GAMMA );
605cdf0e10cSrcweir             mnC3 = lclGamma( lclRgbCompToCrgbComp( mnC3 ), DEC_GAMMA );
606cdf0e10cSrcweir         break;
607cdf0e10cSrcweir         case COLOR_CRGB:
608cdf0e10cSrcweir             // nothing to do
609cdf0e10cSrcweir         break;
610cdf0e10cSrcweir         default:
611cdf0e10cSrcweir             OSL_ENSURE( false, "Color::toCrgb - unexpected color mode" );
612cdf0e10cSrcweir     }
613cdf0e10cSrcweir }
614cdf0e10cSrcweir 
toHsl() const615cdf0e10cSrcweir void Color::toHsl() const
616cdf0e10cSrcweir {
617cdf0e10cSrcweir     switch( meMode )
618cdf0e10cSrcweir     {
619cdf0e10cSrcweir         case COLOR_CRGB:
620cdf0e10cSrcweir             toRgb();
621cdf0e10cSrcweir             // run through!
622cdf0e10cSrcweir         case COLOR_RGB:
623cdf0e10cSrcweir         {
624cdf0e10cSrcweir             meMode = COLOR_HSL;
625cdf0e10cSrcweir             double fR = static_cast< double >( mnC1 ) / 255.0;  // red [0.0, 1.0]
626cdf0e10cSrcweir             double fG = static_cast< double >( mnC2 ) / 255.0;  // green [0.0, 1.0]
627cdf0e10cSrcweir             double fB = static_cast< double >( mnC3 ) / 255.0;  // blue [0.0, 1.0]
628cdf0e10cSrcweir             double fMin = ::std::min( ::std::min( fR, fG ), fB );
629cdf0e10cSrcweir             double fMax = ::std::max( ::std::max( fR, fG ), fB );
630cdf0e10cSrcweir             double fD = fMax - fMin;
631cdf0e10cSrcweir 
632cdf0e10cSrcweir             // hue: 0deg = red, 120deg = green, 240deg = blue
633cdf0e10cSrcweir             if( fD == 0.0 )         // black/gray/white
634cdf0e10cSrcweir                 mnC1 = 0;
635cdf0e10cSrcweir             else if( fMax == fR )   // magenta...red...yellow
636cdf0e10cSrcweir                 mnC1 = static_cast< sal_Int32 >( ((fG - fB) / fD * 60.0 + 360.0) * PER_DEGREE + 0.5 ) % MAX_DEGREE;
637cdf0e10cSrcweir             else if( fMax == fG )   // yellow...green...cyan
638cdf0e10cSrcweir                 mnC1 = static_cast< sal_Int32 >( ((fB - fR) / fD * 60.0 + 120.0) * PER_DEGREE + 0.5 );
639cdf0e10cSrcweir             else                    // cyan...blue...magenta
640cdf0e10cSrcweir                 mnC1 = static_cast< sal_Int32 >( ((fR - fG) / fD * 60.0 + 240.0) * PER_DEGREE + 0.5 );
641cdf0e10cSrcweir 
642cdf0e10cSrcweir             // luminance: 0% = black, 50% = full color, 100% = white
643cdf0e10cSrcweir             mnC3 = static_cast< sal_Int32 >( (fMin + fMax) / 2.0 * MAX_PERCENT + 0.5 );
644cdf0e10cSrcweir 
645cdf0e10cSrcweir             // saturation: 0% = gray, 100% = full color
646cdf0e10cSrcweir             if( (mnC3 == 0) || (mnC3 == MAX_PERCENT) )  // black/white
647cdf0e10cSrcweir                 mnC2 = 0;
648cdf0e10cSrcweir             else if( mnC3 <= 50 * PER_PERCENT )         // dark...full color
649cdf0e10cSrcweir                 mnC2 = static_cast< sal_Int32 >( fD / (fMin + fMax) * MAX_PERCENT + 0.5 );
650cdf0e10cSrcweir             else                                        // full color...light
651cdf0e10cSrcweir                 mnC2 = static_cast< sal_Int32 >( fD / (2.0 - fMax - fMin) * MAX_PERCENT + 0.5 );
652cdf0e10cSrcweir         }
653cdf0e10cSrcweir         break;
654cdf0e10cSrcweir         case COLOR_HSL:
655cdf0e10cSrcweir             // nothing to do
656cdf0e10cSrcweir         break;
657cdf0e10cSrcweir         default:
658cdf0e10cSrcweir             OSL_ENSURE( false, "Color::toHsl - unexpected color mode" );
659cdf0e10cSrcweir     }
660cdf0e10cSrcweir }
661cdf0e10cSrcweir 
662cdf0e10cSrcweir // ============================================================================
663cdf0e10cSrcweir 
664cdf0e10cSrcweir } // namespace drawingml
665cdf0e10cSrcweir } // namespace oox
666cdf0e10cSrcweir 
667