LCOV - code coverage report
Current view: top level - libreoffice/oox/source/drawingml - color.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 200 282 70.9 %
Date: 2012-12-27 Functions: 32 36 88.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           3 : 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           3 : PresetColorsPool::PresetColorsPool() :
      50             :     maDmlColors( static_cast< size_t >( XML_TOKEN_COUNT ), API_RGB_TRANSPARENT ),
      51           3 :     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         423 :     for( const sal_Int32* pnEntry = spnDmlColors; pnEntry < STATIC_ARRAY_END( spnDmlColors ); pnEntry += 2 )
     128         420 :         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          51 :     for( const sal_Int32* pnEntry = spnVmlColors; pnEntry < STATIC_ARRAY_END( spnVmlColors ); pnEntry += 2 )
     143          48 :         maVmlColors[ static_cast< size_t >( pnEntry[ 0 ] ) ] = pnEntry[ 1 ];
     144           3 : }
     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         333 : inline void lclRgbToRgbComponents( sal_Int32& ornR, sal_Int32& ornG, sal_Int32& ornB, sal_Int32 nRgb )
     158             : {
     159         333 :     ornR = (nRgb >> 16) & 0xFF;
     160         333 :     ornG = (nRgb >> 8) & 0xFF;
     161         333 :     ornB = nRgb & 0xFF;
     162         333 : }
     163             : 
     164         338 : inline sal_Int32 lclRgbComponentsToRgb( sal_Int32 nR, sal_Int32 nG, sal_Int32 nB )
     165             : {
     166         338 :     return static_cast< sal_Int32 >( (nR << 16) | (nG << 8) | nB );
     167             : }
     168             : 
     169          27 : inline sal_Int32 lclRgbCompToCrgbComp( sal_Int32 nRgbComp )
     170             : {
     171          27 :     return static_cast< sal_Int32 >( nRgbComp * MAX_PERCENT / 255 );
     172             : }
     173             : 
     174          51 : inline sal_Int32 lclCrgbCompToRgbComp( sal_Int32 nCrgbComp )
     175             : {
     176          51 :     return static_cast< sal_Int32 >( nCrgbComp * 255 / MAX_PERCENT );
     177             : }
     178             : 
     179          78 : inline sal_Int32 lclGamma( sal_Int32 nComp, double fGamma )
     180             : {
     181          78 :     return static_cast< sal_Int32 >( pow( static_cast< double >( nComp ) / MAX_PERCENT, fGamma ) * MAX_PERCENT + 0.5 );
     182             : }
     183             : 
     184          26 : 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          26 :     if( (0 <= nNew) && (nNew <= nMax) )
     188          26 :         ornValue = nNew;
     189          26 : }
     190             : 
     191           4 : void lclModValue( sal_Int32& ornValue, sal_Int32 nMod, sal_Int32 nMax = MAX_PERCENT )
     192             : {
     193             :     OSL_ENSURE( (0 <= nMod), "lclModValue - invalid modificator" );
     194           4 :     ornValue = getLimitedValue< sal_Int32, double >( static_cast< double >( ornValue ) * nMod / MAX_PERCENT, 0, nMax );
     195           4 : }
     196             : 
     197          28 : 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          28 :     ornValue = getLimitedValue< sal_Int32, sal_Int32 >( ornValue + nOff, 0, nMax );
     201          28 : }
     202             : 
     203             : } // namespace
     204             : 
     205             : // ============================================================================
     206             : 
     207       35106 : Color::Color() :
     208             :     meMode( COLOR_UNUSED ),
     209             :     mnC1( 0 ),
     210             :     mnC2( 0 ),
     211             :     mnC3( 0 ),
     212       35106 :     mnAlpha( MAX_PERCENT )
     213             : {
     214       35106 : }
     215             : 
     216       35804 : Color::~Color()
     217             : {
     218       35804 : }
     219             : 
     220           2 : /*static*/ 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           2 :     sal_Int32 nRgbValue = ContainerHelper::getVectorElement( StaticPresetColorsPool::get().maDmlColors, nToken, API_RGB_TRANSPARENT );
     226           2 :     return (nRgbValue >= 0) ? nRgbValue : nDefaultRgb;
     227             : }
     228             : 
     229           3 : /*static*/ 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           3 :     sal_Int32 nRgbValue = ContainerHelper::getVectorElement( StaticPresetColorsPool::get().maVmlColors, nToken, API_RGB_TRANSPARENT );
     235           3 :     return (nRgbValue >= 0) ? nRgbValue : nDefaultRgb;
     236             : }
     237             : 
     238           0 : void Color::setUnused()
     239             : {
     240           0 :     meMode = COLOR_UNUSED;
     241           0 : }
     242             : 
     243         181 : void Color::setSrgbClr( sal_Int32 nRgb )
     244             : {
     245             :     OSL_ENSURE( (0 <= nRgb) && (nRgb <= 0xFFFFFF), "Color::setSrgbClr - invalid RGB value" );
     246         181 :     meMode = COLOR_RGB;
     247         181 :     lclRgbToRgbComponents( mnC1, mnC2, mnC3, nRgb );
     248         181 : }
     249             : 
     250          12 : 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          12 :     meMode = COLOR_CRGB;
     256          12 :     mnC1 = getLimitedValue< sal_Int32, sal_Int32 >( nR, 0, MAX_PERCENT );
     257          12 :     mnC2 = getLimitedValue< sal_Int32, sal_Int32 >( nG, 0, MAX_PERCENT );
     258          12 :     mnC3 = getLimitedValue< sal_Int32, sal_Int32 >( nB, 0, MAX_PERCENT );
     259          12 : }
     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           2 : void Color::setPrstClr( sal_Int32 nToken )
     273             : {
     274           2 :     sal_Int32 nRgbValue = getDmlPresetColor( nToken, API_RGB_TRANSPARENT );
     275             :     OSL_ENSURE( nRgbValue >= 0, "Color::setPrstClr - invalid preset color token" );
     276           2 :     if( nRgbValue >= 0 )
     277           2 :         setSrgbClr( nRgbValue );
     278           2 : }
     279             : 
     280         296 : void Color::setSchemeClr( sal_Int32 nToken )
     281             : {
     282             :     OSL_ENSURE( nToken != XML_TOKEN_INVALID, "Color::setSchemeClr - invalid color token" );
     283         296 :     meMode = (nToken == XML_phClr) ? COLOR_PH : COLOR_SCHEME;
     284         296 :     mnC1 = nToken;
     285         296 : }
     286             : 
     287         193 : void Color::setPaletteClr( sal_Int32 nPaletteIdx )
     288             : {
     289             :     OSL_ENSURE( nPaletteIdx >= 0, "Color::setPaletteClr - invalid palette index" );
     290         193 :     meMode = COLOR_PALETTE;
     291         193 :     mnC1 = nPaletteIdx;
     292         193 : }
     293             : 
     294          16 : void Color::setSysClr( sal_Int32 nToken, sal_Int32 nLastRgb )
     295             : {
     296             :     OSL_ENSURE( (-1 <= nLastRgb) && (nLastRgb <= 0xFFFFFF), "Color::setSysClr - invalid RGB value" );
     297          16 :     meMode = COLOR_SYSTEM;
     298          16 :     mnC1 = nToken;
     299          16 :     mnC2 = nLastRgb;
     300          16 : }
     301             : 
     302         305 : 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         305 :     sal_Int32 nToken = getBaseToken( nElement );
     308         305 :     switch( nToken )
     309             :     {
     310          26 :         case XML_alpha:     lclSetValue( mnAlpha, nValue ); break;
     311           0 :         case XML_alphaMod:  lclModValue( mnAlpha, nValue ); break;
     312           7 :         case XML_alphaOff:  lclOffValue( mnAlpha, nValue ); break;
     313         272 :         default:            maTransforms.push_back( Transformation( nToken, nValue ) );
     314             :     }
     315         305 : }
     316             : 
     317           0 : void Color::addChartTintTransformation( double fTint )
     318             : {
     319           0 :     sal_Int32 nValue = getLimitedValue< sal_Int32, double >( fTint * MAX_PERCENT + 0.5, -MAX_PERCENT, MAX_PERCENT );
     320           0 :     if( nValue < 0 )
     321           0 :         maTransforms.push_back( Transformation( XML_shade, nValue + MAX_PERCENT ) );
     322           0 :     else if( nValue > 0 )
     323           0 :         maTransforms.push_back( Transformation( XML_tint, MAX_PERCENT - nValue ) );
     324           0 : }
     325             : 
     326           0 : void Color::addExcelTintTransformation( double fTint )
     327             : {
     328           0 :     sal_Int32 nValue = getLimitedValue< sal_Int32, double >( fTint * MAX_PERCENT + 0.5, -MAX_PERCENT, MAX_PERCENT );
     329           0 :     maTransforms.push_back( Transformation( XLS_TOKEN( tint ), nValue ) );
     330           0 : }
     331             : 
     332         235 : void Color::clearTransformations()
     333             : {
     334         235 :     maTransforms.clear();
     335         235 :     clearTransparence();
     336         235 : }
     337             : 
     338         235 : void Color::clearTransparence()
     339             : {
     340         235 :     mnAlpha = MAX_PERCENT;
     341         235 : }
     342             : 
     343         502 : sal_Int32 Color::getColor( const GraphicHelper& rGraphicHelper, sal_Int32 nPhClr ) const
     344             : {
     345             :     /*  Special handling for theme style list placeholder colors (state
     346             :         COLOR_PH), Color::getColor() may be called with different placeholder
     347             :         colors in the nPhClr parameter. Therefore, the resolved color will not
     348             :         be stored in this object, thus the state COLOR_FINAL will not be
     349             :         reached and the transformation container will not be cleared, but the
     350             :         original COLOR_PH state will be restored instead. */
     351         502 :     bool bIsPh = false;
     352             : 
     353         502 :     switch( meMode )
     354             :     {
     355          73 :         case COLOR_UNUSED:  mnC1 = API_RGB_TRANSPARENT; break;
     356             : 
     357         178 :         case COLOR_RGB:     break;  // nothing to do
     358           8 :         case COLOR_CRGB:    break;  // nothing to do
     359           0 :         case COLOR_HSL:     break;  // nothing to do
     360             : 
     361          64 :         case COLOR_SCHEME:  setResolvedRgb( rGraphicHelper.getSchemeColor( mnC1 ) );        break;
     362          66 :         case COLOR_PALETTE: setResolvedRgb( rGraphicHelper.getPaletteColor( mnC1 ) );       break;
     363          16 :         case COLOR_SYSTEM:  setResolvedRgb( rGraphicHelper.getSystemColor( mnC1, mnC2 ) );  break;
     364           6 :         case COLOR_PH:      setResolvedRgb( nPhClr ); bIsPh = true;                         break;
     365             : 
     366          91 :         case COLOR_FINAL:   return mnC1;
     367             :     }
     368             : 
     369             :     // if color is UNUSED or turns to UNUSED in setResolvedRgb, do not perform transformations
     370         411 :     if( meMode != COLOR_UNUSED )
     371             :     {
     372         372 :         for( TransformVec::const_iterator aIt = maTransforms.begin(), aEnd = maTransforms.end(); aIt != aEnd; ++aIt )
     373             :         {
     374             :         OSL_ASSERT((aIt->mnToken & sal_Int32(0xFFFF0000))==0);
     375          34 :             switch( aIt->mnToken )
     376             :             {
     377           0 :                 case XML_red:       toCrgb(); lclSetValue( mnC1, aIt->mnValue );    break;
     378           0 :                 case XML_redMod:    toCrgb(); lclModValue( mnC1, aIt->mnValue );    break;
     379           0 :                 case XML_redOff:    toCrgb(); lclOffValue( mnC1, aIt->mnValue );    break;
     380           0 :                 case XML_green:     toCrgb(); lclSetValue( mnC2, aIt->mnValue );    break;
     381           0 :                 case XML_greenMod:  toCrgb(); lclModValue( mnC2, aIt->mnValue );    break;
     382           0 :                 case XML_greenOff:  toCrgb(); lclOffValue( mnC2, aIt->mnValue );    break;
     383           0 :                 case XML_blue:      toCrgb(); lclSetValue( mnC3, aIt->mnValue );    break;
     384           0 :                 case XML_blueMod:   toCrgb(); lclModValue( mnC3, aIt->mnValue );    break;
     385           0 :                 case XML_blueOff:   toCrgb(); lclOffValue( mnC3, aIt->mnValue );    break;
     386             : 
     387           0 :                 case XML_hue:       toHsl(); lclSetValue( mnC1, aIt->mnValue, MAX_DEGREE ); break;
     388           0 :                 case XML_hueMod:    toHsl(); lclModValue( mnC1, aIt->mnValue, MAX_DEGREE ); break;
     389           7 :                 case XML_hueOff:    toHsl(); lclOffValue( mnC1, aIt->mnValue, MAX_DEGREE ); break;
     390           0 :                 case XML_sat:       toHsl(); lclSetValue( mnC2, aIt->mnValue );             break;
     391           4 :                 case XML_satMod:    toHsl(); lclModValue( mnC2, aIt->mnValue );             break;
     392           7 :                 case XML_satOff:    toHsl(); lclOffValue( mnC2, aIt->mnValue );             break;
     393             : 
     394             :                 case XML_lum:
     395           0 :                     toHsl();
     396           0 :                     lclSetValue( mnC3, aIt->mnValue );
     397             :                     // if color changes to black or white, it will stay gray if luminance changes again
     398           0 :                     if( (mnC3 == 0) || (mnC3 == MAX_PERCENT) ) mnC2 = 0;
     399           0 :                 break;
     400             :                 case XML_lumMod:
     401           0 :                     toHsl();
     402           0 :                     lclModValue( mnC3, aIt->mnValue );
     403             :                     // if color changes to black or white, it will stay gray if luminance changes again
     404           0 :                     if( (mnC3 == 0) || (mnC3 == MAX_PERCENT) ) mnC2 = 0;
     405           0 :                 break;
     406             :                 case XML_lumOff:
     407           7 :                     toHsl();
     408           7 :                     lclOffValue( mnC3, aIt->mnValue );
     409             :                     // if color changes to black or white, it will stay gray if luminance changes again
     410           7 :                     if( (mnC3 == 0) || (mnC3 == MAX_PERCENT) ) mnC2 = 0;
     411           7 :                 break;
     412             : 
     413             :                 case XML_shade:
     414             :                     // shade: 0% = black, 100% = original color
     415           4 :                     toCrgb();
     416             :                     OSL_ENSURE( (0 <= aIt->mnValue) && (aIt->mnValue <= MAX_PERCENT), "Color::getColor - invalid shade value" );
     417           4 :                     if( (0 <= aIt->mnValue) && (aIt->mnValue <= MAX_PERCENT) )
     418             :                     {
     419           4 :                         double fFactor = static_cast< double >( aIt->mnValue ) / MAX_PERCENT;
     420           4 :                         mnC1 = static_cast< sal_Int32 >( mnC1 * fFactor );
     421           4 :                         mnC2 = static_cast< sal_Int32 >( mnC2 * fFactor );
     422           4 :                         mnC3 = static_cast< sal_Int32 >( mnC3 * fFactor );
     423             :                     }
     424           4 :                 break;
     425             :                 case XML_tint:
     426             :                     // tint: 0% = white, 100% = original color
     427           5 :                     toCrgb();
     428             :                     OSL_ENSURE( (0 <= aIt->mnValue) && (aIt->mnValue <= MAX_PERCENT), "Color::getColor - invalid tint value" );
     429           5 :                     if( (0 <= aIt->mnValue) && (aIt->mnValue <= MAX_PERCENT) )
     430             :                     {
     431           5 :                         double fFactor = static_cast< double >( aIt->mnValue ) / MAX_PERCENT;
     432           5 :                         mnC1 = static_cast< sal_Int32 >( MAX_PERCENT - (MAX_PERCENT - mnC1) * fFactor );
     433           5 :                         mnC2 = static_cast< sal_Int32 >( MAX_PERCENT - (MAX_PERCENT - mnC2) * fFactor );
     434           5 :                         mnC3 = static_cast< sal_Int32 >( MAX_PERCENT - (MAX_PERCENT - mnC3) * fFactor );
     435             :                     }
     436           5 :                 break;
     437             :                 case XLS_TOKEN( tint ):
     438             :                     // Excel tint: move luminance relative to current value
     439           0 :                     toHsl();
     440             :                     OSL_ENSURE( (-MAX_PERCENT <= aIt->mnValue) && (aIt->mnValue <= MAX_PERCENT), "Color::getColor - invalid tint value" );
     441           0 :                     if( (-MAX_PERCENT <= aIt->mnValue) && (aIt->mnValue < 0) )
     442             :                     {
     443             :                         // negative: luminance towards 0% (black)
     444           0 :                         lclModValue( mnC3, aIt->mnValue + MAX_PERCENT );
     445             :                     }
     446           0 :                     else if( (0 < aIt->mnValue) && (aIt->mnValue <= MAX_PERCENT) )
     447             :                     {
     448             :                         // positive: luminance towards 100% (white)
     449           0 :                         mnC3 = MAX_PERCENT - mnC3;
     450           0 :                         lclModValue( mnC3, MAX_PERCENT - aIt->mnValue );
     451           0 :                         mnC3 = MAX_PERCENT - mnC3;
     452             :                     }
     453           0 :                 break;
     454             : 
     455             :                 case XML_gray:
     456             :                     // change color to gray, weighted RGB: 22% red, 72% green, 6% blue
     457           0 :                     toRgb();
     458           0 :                     mnC1 = mnC2 = mnC3 = (mnC1 * 22 + mnC2 * 72 + mnC3 * 6) / 100;
     459           0 :                 break;
     460             : 
     461             :                 case XML_comp:
     462             :                     // comp: rotate hue by 180 degrees, do not change lum/sat
     463           0 :                     toHsl();
     464           0 :                     (mnC1 += 180 * PER_DEGREE) %= MAX_DEGREE;
     465           0 :                 break;
     466             :                 case XML_inv:
     467             :                     // invert percentual RGB values
     468           0 :                     toCrgb();
     469           0 :                     mnC1 = MAX_PERCENT - mnC1;
     470           0 :                     mnC2 = MAX_PERCENT - mnC2;
     471           0 :                     mnC3 = MAX_PERCENT - mnC3;
     472           0 :                 break;
     473             : 
     474             :                 case XML_gamma:
     475             :                     // increase gamma of color
     476           0 :                     toCrgb();
     477           0 :                     mnC1 = lclGamma( mnC1, INC_GAMMA );
     478           0 :                     mnC2 = lclGamma( mnC2, INC_GAMMA );
     479           0 :                     mnC3 = lclGamma( mnC3, INC_GAMMA );
     480           0 :                 break;
     481             :                 case XML_invGamma:
     482             :                     // decrease gamma of color
     483           0 :                     toCrgb();
     484           0 :                     mnC1 = lclGamma( mnC1, DEC_GAMMA );
     485           0 :                     mnC2 = lclGamma( mnC2, DEC_GAMMA );
     486           0 :                     mnC3 = lclGamma( mnC3, DEC_GAMMA );
     487           0 :                 break;
     488             :             }
     489             :         }
     490             : 
     491             :         // store resulting RGB value in mnC1
     492         338 :         toRgb();
     493         338 :         mnC1 = lclRgbComponentsToRgb( mnC1, mnC2, mnC3 );
     494             :     }
     495             :     else // if( meMode != COLOR_UNUSED )
     496             :     {
     497          73 :         mnC1 = API_RGB_TRANSPARENT;
     498             :     }
     499             : 
     500         411 :     meMode = bIsPh ? COLOR_PH : COLOR_FINAL;
     501         411 :     if( meMode == COLOR_FINAL )
     502         405 :         maTransforms.clear();
     503         411 :     return mnC1;
     504             : }
     505             : 
     506          34 : bool Color::hasTransparency() const
     507             : {
     508          34 :     return mnAlpha < MAX_PERCENT;
     509             : }
     510             : 
     511           6 : sal_Int16 Color::getTransparency() const
     512             : {
     513           6 :     return static_cast< sal_Int16 >( (MAX_PERCENT - mnAlpha) / PER_PERCENT );
     514             : }
     515             : 
     516             : // private --------------------------------------------------------------------
     517             : 
     518         152 : void Color::setResolvedRgb( sal_Int32 nRgb ) const
     519             : {
     520         152 :     meMode = (nRgb < 0) ? COLOR_UNUSED : COLOR_RGB;
     521         152 :     lclRgbToRgbComponents( mnC1, mnC2, mnC3, nRgb );
     522         152 : }
     523             : 
     524         343 : void Color::toRgb() const
     525             : {
     526         343 :     switch( meMode )
     527             :     {
     528             :         case COLOR_RGB:
     529             :             // nothing to do
     530         315 :         break;
     531             :         case COLOR_CRGB:
     532          17 :             meMode = COLOR_RGB;
     533          17 :             mnC1 = lclCrgbCompToRgbComp( lclGamma( mnC1, INC_GAMMA ) );
     534          17 :             mnC2 = lclCrgbCompToRgbComp( lclGamma( mnC2, INC_GAMMA ) );
     535          17 :             mnC3 = lclCrgbCompToRgbComp( lclGamma( mnC3, INC_GAMMA ) );
     536          17 :         break;
     537             :         case COLOR_HSL:
     538             :         {
     539          11 :             meMode = COLOR_RGB;
     540          11 :             double fR = 0.0, fG = 0.0, fB = 0.0;
     541          11 :             if( (mnC2 == 0) || (mnC3 == MAX_PERCENT) )
     542             :             {
     543           3 :                 fR = fG = fB = static_cast< double >( mnC3 ) / MAX_PERCENT;
     544             :             }
     545           8 :             else if( mnC3 > 0 )
     546             :             {
     547             :                 // base color from hue
     548           8 :                 double fHue = static_cast< double >( mnC1 ) / MAX_DEGREE * 6.0; // interval [0.0, 6.0)
     549           8 :                 if( fHue <= 1.0 )       { fR = 1.0; fG = fHue; }        // red...yellow
     550           8 :                 else if( fHue <= 2.0 )  { fR = 2.0 - fHue; fG = 1.0; }  // yellow...green
     551           8 :                 else if( fHue <= 3.0 )  { fG = 1.0; fB = fHue - 2.0; }  // green...cyan
     552           8 :                 else if( fHue <= 4.0 )  { fG = 4.0 - fHue; fB = 1.0; }  // cyan...blue
     553           0 :                 else if( fHue <= 5.0 )  { fR = fHue - 4.0; fB = 1.0; }  // blue...magenta
     554           0 :                 else                    { fR = 1.0; fB = 6.0 - fHue; }  // magenta...red
     555             : 
     556             :                 // apply saturation
     557           8 :                 double fSat = static_cast< double >( mnC2 ) / MAX_PERCENT;
     558           8 :                 fR = (fR - 0.5) * fSat + 0.5;
     559           8 :                 fG = (fG - 0.5) * fSat + 0.5;
     560           8 :                 fB = (fB - 0.5) * fSat + 0.5;
     561             : 
     562             :                 // apply luminance
     563           8 :                 double fLum = 2.0 * static_cast< double >( mnC3 ) / MAX_PERCENT - 1.0;  // interval [-1.0, 1.0]
     564           8 :                 if( fLum < 0.0 )
     565             :                 {
     566           0 :                     double fShade = fLum + 1.0; // interval [0.0, 1.0] (black...full color)
     567           0 :                     fR *= fShade;
     568           0 :                     fG *= fShade;
     569           0 :                     fB *= fShade;
     570             :                 }
     571           8 :                 else if( fLum > 0.0 )
     572             :                 {
     573           8 :                     double fTint = 1.0 - fLum;  // interval [0.0, 1.0] (white...full color)
     574           8 :                     fR = 1.0 - ((1.0 - fR) * fTint);
     575           8 :                     fG = 1.0 - ((1.0 - fG) * fTint);
     576           8 :                     fB = 1.0 - ((1.0 - fB) * fTint);
     577             :                 }
     578             :             }
     579          11 :             mnC1 = static_cast< sal_Int32 >( fR * 255.0 + 0.5 );
     580          11 :             mnC2 = static_cast< sal_Int32 >( fG * 255.0 + 0.5 );
     581          11 :             mnC3 = static_cast< sal_Int32 >( fB * 255.0 + 0.5 );
     582             :         }
     583          11 :         break;
     584             :         default:
     585             :             OSL_FAIL( "Color::toRgb - unexpected color mode" );
     586             :     }
     587         343 : }
     588             : 
     589           9 : void Color::toCrgb() const
     590             : {
     591           9 :     switch( meMode )
     592             :     {
     593             :         case COLOR_HSL:
     594           0 :             toRgb();
     595             :             // run through!
     596             :         case COLOR_RGB:
     597           9 :             meMode = COLOR_CRGB;
     598           9 :             mnC1 = lclGamma( lclRgbCompToCrgbComp( mnC1 ), DEC_GAMMA );
     599           9 :             mnC2 = lclGamma( lclRgbCompToCrgbComp( mnC2 ), DEC_GAMMA );
     600           9 :             mnC3 = lclGamma( lclRgbCompToCrgbComp( mnC3 ), DEC_GAMMA );
     601           9 :         break;
     602             :         case COLOR_CRGB:
     603             :             // nothing to do
     604           0 :         break;
     605             :         default:
     606             :             OSL_FAIL( "Color::toCrgb - unexpected color mode" );
     607             :     }
     608           9 : }
     609             : 
     610          25 : void Color::toHsl() const
     611             : {
     612          25 :     switch( meMode )
     613             :     {
     614             :         case COLOR_CRGB:
     615           5 :             toRgb();
     616             :             // run through!
     617             :         case COLOR_RGB:
     618             :         {
     619          11 :             meMode = COLOR_HSL;
     620          11 :             double fR = static_cast< double >( mnC1 ) / 255.0;  // red [0.0, 1.0]
     621          11 :             double fG = static_cast< double >( mnC2 ) / 255.0;  // green [0.0, 1.0]
     622          11 :             double fB = static_cast< double >( mnC3 ) / 255.0;  // blue [0.0, 1.0]
     623          11 :             double fMin = ::std::min( ::std::min( fR, fG ), fB );
     624          11 :             double fMax = ::std::max( ::std::max( fR, fG ), fB );
     625          11 :             double fD = fMax - fMin;
     626             : 
     627             :             // hue: 0deg = red, 120deg = green, 240deg = blue
     628          11 :             if( fD == 0.0 )         // black/gray/white
     629           3 :                 mnC1 = 0;
     630           8 :             else if( fMax == fR )   // magenta...red...yellow
     631           0 :                 mnC1 = static_cast< sal_Int32 >( ((fG - fB) / fD * 60.0 + 360.0) * PER_DEGREE + 0.5 ) % MAX_DEGREE;
     632           8 :             else if( fMax == fG )   // yellow...green...cyan
     633           0 :                 mnC1 = static_cast< sal_Int32 >( ((fB - fR) / fD * 60.0 + 120.0) * PER_DEGREE + 0.5 );
     634             :             else                    // cyan...blue...magenta
     635           8 :                 mnC1 = static_cast< sal_Int32 >( ((fR - fG) / fD * 60.0 + 240.0) * PER_DEGREE + 0.5 );
     636             : 
     637             :             // luminance: 0% = black, 50% = full color, 100% = white
     638          11 :             mnC3 = static_cast< sal_Int32 >( (fMin + fMax) / 2.0 * MAX_PERCENT + 0.5 );
     639             : 
     640             :             // saturation: 0% = gray, 100% = full color
     641          11 :             if( (mnC3 == 0) || (mnC3 == MAX_PERCENT) )  // black/white
     642           3 :                 mnC2 = 0;
     643           8 :             else if( mnC3 <= 50 * PER_PERCENT )         // dark...full color
     644           0 :                 mnC2 = static_cast< sal_Int32 >( fD / (fMin + fMax) * MAX_PERCENT + 0.5 );
     645             :             else                                        // full color...light
     646           8 :                 mnC2 = static_cast< sal_Int32 >( fD / (2.0 - fMax - fMin) * MAX_PERCENT + 0.5 );
     647             :         }
     648          11 :         break;
     649             :         case COLOR_HSL:
     650             :             // nothing to do
     651          14 :         break;
     652             :         default:
     653             :             OSL_FAIL( "Color::toHsl - unexpected color mode" );
     654             :     }
     655          25 : }
     656             : 
     657             : // ============================================================================
     658             : 
     659             : } // namespace drawingml
     660          51 : } // namespace oox
     661             : 
     662             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10