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

Generated by: LCOV version 1.10