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