LCOV - code coverage report
Current view: top level - oox/source/drawingml - color.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 300 385 77.9 %
Date: 2015-06-13 12:38:46 Functions: 37 38 97.4 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.11