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

Generated by: LCOV version 1.10