LCOV - code coverage report
Current view: top level - oox/source/vml - vmlformatting.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 148 271 54.6 %
Date: 2012-08-25 Functions: 22 23 95.7 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 109 431 25.3 %

           Branch data     Line data    Source code
       1                 :            : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 :            : /*
       3                 :            :  * This file is part of the LibreOffice project.
       4                 :            :  *
       5                 :            :  * This Source Code Form is subject to the terms of the Mozilla Public
       6                 :            :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7                 :            :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8                 :            :  *
       9                 :            :  * This file incorporates work covered by the following license notice:
      10                 :            :  *
      11                 :            :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12                 :            :  *   contributor license agreements. See the NOTICE file distributed
      13                 :            :  *   with this work for additional information regarding copyright
      14                 :            :  *   ownership. The ASF licenses this file to you under the Apache
      15                 :            :  *   License, Version 2.0 (the "License"); you may not use this file
      16                 :            :  *   except in compliance with the License. You may obtain a copy of
      17                 :            :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18                 :            :  */
      19                 :            : 
      20                 :            : #include "oox/vml/vmlformatting.hxx"
      21                 :            : 
      22                 :            : #include <rtl/strbuf.hxx>
      23                 :            : #include "oox/drawingml/color.hxx"
      24                 :            : #include "oox/drawingml/drawingmltypes.hxx"
      25                 :            : #include "oox/drawingml/fillproperties.hxx"
      26                 :            : #include "oox/drawingml/lineproperties.hxx"
      27                 :            : #include "oox/drawingml/shapepropertymap.hxx"
      28                 :            : #include "oox/helper/attributelist.hxx"
      29                 :            : #include "oox/helper/graphichelper.hxx"
      30                 :            : 
      31                 :            : namespace oox {
      32                 :            : namespace vml {
      33                 :            : 
      34                 :            : // ============================================================================
      35                 :            : 
      36                 :            : using namespace ::com::sun::star::geometry;
      37                 :            : 
      38                 :            : using ::oox::drawingml::Color;
      39                 :            : using ::oox::drawingml::FillProperties;
      40                 :            : using ::oox::drawingml::LineArrowProperties;
      41                 :            : using ::oox::drawingml::LineProperties;
      42                 :            : using ::oox::drawingml::ShapePropertyMap;
      43                 :            : using ::rtl::OStringBuffer;
      44                 :            : using ::rtl::OUString;
      45                 :            : 
      46                 :            : // ============================================================================
      47                 :            : 
      48                 :            : namespace {
      49                 :            : 
      50                 :        138 : bool lclExtractDouble( double& orfValue, sal_Int32& ornEndPos, const OUString& rValue )
      51                 :            : {
      52                 :            :     // extract the double value and find start position of unit characters
      53                 :        138 :     rtl_math_ConversionStatus eConvStatus = rtl_math_ConversionStatus_Ok;
      54                 :        138 :     orfValue = ::rtl::math::stringToDouble( rValue, '.', '\0', &eConvStatus, &ornEndPos );
      55                 :        138 :     return eConvStatus == rtl_math_ConversionStatus_Ok;
      56                 :            : }
      57                 :            : 
      58                 :            : } // namespace
      59                 :            : 
      60                 :            : // ----------------------------------------------------------------------------
      61                 :            : 
      62                 :        501 : /*static*/ bool ConversionHelper::separatePair( OUString& orValue1, OUString& orValue2,
      63                 :            :         const OUString& rValue, sal_Unicode cSep )
      64                 :            : {
      65                 :        501 :     sal_Int32 nSepPos = rValue.indexOf( cSep );
      66         [ +  + ]:        501 :     if( nSepPos >= 0 )
      67                 :            :     {
      68                 :        465 :         orValue1 = rValue.copy( 0, nSepPos ).trim();
      69                 :        465 :         orValue2 = rValue.copy( nSepPos + 1 ).trim();
      70                 :            :     }
      71                 :            :     else
      72                 :            :     {
      73                 :         36 :         orValue1 = rValue.trim();
      74                 :            :     }
      75 [ +  + ][ +  + ]:        501 :     return !orValue1.isEmpty() && !orValue2.isEmpty();
      76                 :            : }
      77                 :            : 
      78                 :         42 : /*static*/ bool ConversionHelper::decodeBool( const OUString& rValue )
      79                 :            : {
      80                 :         42 :     sal_Int32 nToken = AttributeConversion::decodeToken( rValue );
      81                 :            :     // anything else than 't' or 'true' is considered to be false, as specified
      82 [ -  + ][ +  + ]:         42 :     return (nToken == XML_t) || (nToken == XML_true);
      83                 :            : }
      84                 :            : 
      85                 :          0 : /*static*/ double ConversionHelper::decodePercent( const OUString& rValue, double fDefValue )
      86                 :            : {
      87         [ #  # ]:          0 :     if( rValue.isEmpty() )
      88                 :          0 :         return fDefValue;
      89                 :            : 
      90                 :          0 :     double fValue = 0.0;
      91                 :          0 :     sal_Int32 nEndPos = 0;
      92         [ #  # ]:          0 :     if( !lclExtractDouble( fValue, nEndPos, rValue ) )
      93                 :          0 :         return fDefValue;
      94                 :            : 
      95         [ #  # ]:          0 :     if( nEndPos == rValue.getLength() )
      96                 :          0 :         return fValue;
      97                 :            : 
      98 [ #  # ][ #  # ]:          0 :     if( (nEndPos + 1 == rValue.getLength()) && (rValue[ nEndPos ] == '%') )
                 [ #  # ]
      99                 :          0 :         return fValue / 100.0;
     100                 :            : 
     101 [ #  # ][ #  # ]:          0 :     if( (nEndPos + 1 == rValue.getLength()) && (rValue[ nEndPos ] == 'f') )
                 [ #  # ]
     102                 :          0 :         return fValue / 65536.0;
     103                 :            : 
     104                 :            :     OSL_FAIL( "ConversionHelper::decodePercent - unknown measure unit" );
     105                 :          0 :     return fDefValue;
     106                 :            : }
     107                 :            : 
     108                 :        249 : /*static*/ sal_Int64 ConversionHelper::decodeMeasureToEmu( const GraphicHelper& rGraphicHelper,
     109                 :            :         const OUString& rValue, sal_Int32 nRefValue, bool bPixelX, bool bDefaultAsPixel )
     110                 :            : {
     111                 :            :     // default for missing values is 0
     112         [ +  + ]:        249 :     if( rValue.isEmpty() )
     113                 :        111 :         return 0;
     114                 :            : 
     115                 :            :     // TODO: according to spec, value may contain "auto"
     116         [ -  + ]:        138 :     if ( rValue == "auto" )
     117                 :            :     {
     118                 :            :         OSL_FAIL( "ConversionHelper::decodeMeasureToEmu - special value 'auto' must be handled by caller" );
     119                 :          0 :         return nRefValue;
     120                 :            :     }
     121                 :            : 
     122                 :            :     // extract the double value and find start position of unit characters
     123                 :        138 :     double fValue = 0.0;
     124                 :        138 :     sal_Int32 nEndPos = 0;
     125 [ +  - ][ +  + ]:        138 :     if( !lclExtractDouble( fValue, nEndPos, rValue ) || (fValue == 0.0) )
                 [ +  + ]
     126                 :         18 :         return 0;
     127                 :            : 
     128                 :            :     // process trailing unit, convert to EMU
     129 [ +  + ][ +  - ]:        120 :     static const OUString saPx = CREATE_OUSTRING( "px" );
         [ +  - ][ #  # ]
     130                 :        120 :     OUString aUnit;
     131 [ +  - ][ +  - ]:        120 :     if( (0 < nEndPos) && (nEndPos < rValue.getLength()) )
                 [ +  - ]
     132                 :        120 :         aUnit = rValue.copy( nEndPos );
     133         [ #  # ]:          0 :     else if( bDefaultAsPixel )
     134                 :          0 :         aUnit = saPx;
     135                 :            :     // else default is EMU
     136                 :            : 
     137         [ +  - ]:        120 :     if( aUnit.getLength() == 2 )
     138                 :            :     {
     139                 :        120 :         sal_Unicode cChar1 = aUnit[ 0 ];
     140                 :        120 :         sal_Unicode cChar2 = aUnit[ 1 ];
     141 [ +  - ][ +  + ]:        120 :         if( (cChar1 == 'i') && (cChar2 == 'n') )        // 1 inch = 914,400 EMU
     142                 :          6 :             fValue *= 914400.0;
     143 [ -  + ][ #  # ]:        114 :         else if( (cChar1 == 'c') && (cChar2 == 'm') )   // 1 cm = 360,000 EMU
     144                 :          0 :             fValue *= 360000.0;
     145 [ -  + ][ #  # ]:        114 :         else if( (cChar1 == 'm') && (cChar2 == 'm') )   // 1 mm = 36,000 EMU
     146                 :          0 :             fValue *= 36000.0;
     147 [ +  - ][ +  - ]:        114 :         else if( (cChar1 == 'p') && (cChar2 == 't') )   // 1 point = 1/72 inch = 12,700 EMU
     148                 :        114 :             fValue *= 12700.0;
     149 [ #  # ][ #  # ]:          0 :         else if( (cChar1 == 'p') && (cChar2 == 'c') )   // 1 pica = 1/6 inch = 152,400 EMU
     150                 :          0 :             fValue *= 152400.0;
     151 [ #  # ][ #  # ]:          0 :         else if( (cChar1 == 'p') && (cChar2 == 'x') )   // 1 pixel, dependent on output device
     152                 :            :             fValue = static_cast< double >( ::oox::drawingml::convertHmmToEmu(
     153                 :            :                 bPixelX ?
     154                 :          0 :                     rGraphicHelper.convertScreenPixelXToHmm( fValue ) :
     155 [ #  # ][ #  # ]:        120 :                     rGraphicHelper.convertScreenPixelYToHmm( fValue ) ) );
                 [ #  # ]
     156                 :            :     }
     157 [ #  # ][ #  # ]:          0 :     else if( (aUnit.getLength() == 1) && (aUnit[ 0 ] == '%') )
                 [ #  # ]
     158                 :            :     {
     159                 :          0 :         fValue *= nRefValue / 100.0;
     160                 :            :     }
     161 [ #  # ][ #  # ]:          0 :     else if( bDefaultAsPixel || !aUnit.isEmpty() )   // default as EMU and no unit -> do nothing
                 [ #  # ]
     162                 :            :     {
     163                 :            :         OSL_FAIL( "ConversionHelper::decodeMeasureToEmu - unknown measure unit" );
     164                 :          0 :         fValue = nRefValue;
     165                 :            :     }
     166                 :        249 :     return static_cast< sal_Int64 >( fValue + 0.5 );
     167                 :            : }
     168                 :            : 
     169                 :        246 : /*static*/ sal_Int32 ConversionHelper::decodeMeasureToHmm( const GraphicHelper& rGraphicHelper,
     170                 :            :         const OUString& rValue, sal_Int32 nRefValue, bool bPixelX, bool bDefaultAsPixel )
     171                 :            : {
     172                 :        246 :     return ::oox::drawingml::convertEmuToHmm( decodeMeasureToEmu( rGraphicHelper, rValue, nRefValue, bPixelX, bDefaultAsPixel ) );
     173                 :            : }
     174                 :            : 
     175                 :         54 : /*static*/ Color ConversionHelper::decodeColor( const GraphicHelper& rGraphicHelper,
     176                 :            :         const OptValue< OUString >& roVmlColor, const OptValue< double >& roVmlOpacity,
     177                 :            :         sal_Int32 nDefaultRgb, sal_Int32 nPrimaryRgb )
     178                 :            : {
     179         [ +  - ]:         54 :     Color aDmlColor;
     180                 :            : 
     181                 :            :     // convert opacity
     182                 :         54 :     const sal_Int32 DML_FULL_OPAQUE = ::oox::drawingml::MAX_PERCENT;
     183                 :         54 :     double fOpacity = roVmlOpacity.get( 1.0 );
     184         [ +  - ]:         54 :     sal_Int32 nOpacity = getLimitedValue< sal_Int32, double >( fOpacity * DML_FULL_OPAQUE, 0, DML_FULL_OPAQUE );
     185         [ -  + ]:         54 :     if( nOpacity < DML_FULL_OPAQUE )
     186         [ #  # ]:          0 :         aDmlColor.addTransformation( XML_alpha, nOpacity );
     187                 :            : 
     188                 :            :     // color attribute not present - set passed default color
     189         [ +  + ]:         54 :     if( !roVmlColor.has() )
     190                 :            :     {
     191         [ +  - ]:         42 :         aDmlColor.setSrgbClr( nDefaultRgb );
     192                 :            :         return aDmlColor;
     193                 :            :     }
     194                 :            : 
     195                 :            :     // separate leading color name or RGB value from following palette index
     196                 :         12 :     OUString aColorName, aColorIndex;
     197         [ +  - ]:         12 :     separatePair( aColorName, aColorIndex, roVmlColor.get(), ' ' );
     198                 :            : 
     199                 :            :     // RGB colors in the format '#RRGGBB'
     200 [ +  + ][ +  - ]:         12 :     if( (aColorName.getLength() == 7) && (aColorName[ 0 ] == '#') )
                 [ +  + ]
     201                 :            :     {
     202         [ +  - ]:          9 :         aDmlColor.setSrgbClr( aColorName.copy( 1 ).toInt32( 16 ) );
     203                 :            :         return aDmlColor;
     204                 :            :     }
     205                 :            : 
     206                 :            :     // RGB colors in the format '#RGB'
     207 [ +  - ][ -  + ]:          3 :     if( (aColorName.getLength() == 4) && (aColorName[ 0 ] == '#') )
                 [ -  + ]
     208                 :            :     {
     209                 :          0 :         sal_Int32 nR = aColorName.copy( 1, 1 ).toInt32( 16 ) * 0x11;
     210                 :          0 :         sal_Int32 nG = aColorName.copy( 2, 1 ).toInt32( 16 ) * 0x11;
     211                 :          0 :         sal_Int32 nB = aColorName.copy( 3, 1 ).toInt32( 16 ) * 0x11;
     212         [ #  # ]:          0 :         aDmlColor.setSrgbClr( (nR << 16) | (nG << 8) | nB );
     213                 :            :         return aDmlColor;
     214                 :            :     }
     215                 :            : 
     216                 :            :     /*  Predefined color names or system color names (resolve to RGB to detect
     217                 :            :         valid color name). */
     218         [ +  - ]:          3 :     sal_Int32 nColorToken = AttributeConversion::decodeToken( aColorName );
     219         [ +  - ]:          3 :     sal_Int32 nRgbValue = Color::getVmlPresetColor( nColorToken, API_RGB_TRANSPARENT );
     220         [ -  + ]:          3 :     if( nRgbValue == API_RGB_TRANSPARENT )
     221         [ #  # ]:          0 :         nRgbValue = rGraphicHelper.getSystemColor( nColorToken, API_RGB_TRANSPARENT );
     222         [ +  - ]:          3 :     if( nRgbValue != API_RGB_TRANSPARENT )
     223                 :            :     {
     224         [ +  - ]:          3 :         aDmlColor.setSrgbClr( nRgbValue );
     225                 :            :         return aDmlColor;
     226                 :            :     }
     227                 :            : 
     228                 :            :     // try palette colors enclosed in brackets
     229 [ #  # ][ #  # ]:          0 :     if( (aColorIndex.getLength() >= 3) && (aColorIndex[ 0 ] == '[') && (aColorIndex[ aColorIndex.getLength() - 1 ] == ']') )
         [ #  # ][ #  # ]
     230                 :            :     {
     231         [ #  # ]:          0 :         aDmlColor.setPaletteClr( aColorIndex.copy( 1, aColorIndex.getLength() - 2 ).toInt32() );
     232                 :            :         return aDmlColor;
     233                 :            :     }
     234                 :            : 
     235                 :            :     // try fill gradient modificator 'fill <modifier>(<amount>)'
     236 [ #  # ][ #  # ]:          0 :     if( (nPrimaryRgb != API_RGB_TRANSPARENT) && (nColorToken == XML_fill) )
     237                 :            :     {
     238                 :          0 :         sal_Int32 nOpenParen = aColorIndex.indexOf( '(' );
     239                 :          0 :         sal_Int32 nCloseParen = aColorIndex.indexOf( ')' );
     240 [ #  # ][ #  # ]:          0 :         if( (2 <= nOpenParen) && (nOpenParen + 1 < nCloseParen) && (nCloseParen + 1 == aColorIndex.getLength()) )
         [ #  # ][ #  # ]
     241                 :            :         {
     242                 :          0 :             sal_Int32 nModToken = XML_TOKEN_INVALID;
     243         [ #  # ]:          0 :             switch( AttributeConversion::decodeToken( aColorIndex.copy( 0, nOpenParen ) ) )
              [ #  #  # ]
     244                 :            :             {
     245                 :          0 :                 case XML_darken:    nModToken = XML_shade;break;
     246                 :          0 :                 case XML_lighten:   nModToken = XML_tint;
     247                 :            :             }
     248                 :          0 :             sal_Int32 nValue = aColorIndex.copy( nOpenParen + 1, nCloseParen - nOpenParen - 1 ).toInt32();
     249 [ #  # ][ #  # ]:          0 :             if( (nModToken != XML_TOKEN_INVALID) && (0 <= nValue) && (nValue < 255) )
                 [ #  # ]
     250                 :            :             {
     251                 :            :                 /*  Simulate this modifier color by a color with related transformation.
     252                 :            :                     The modifier amount has to be converted from the range [0;255] to
     253                 :            :                     percentage [0;100000] used by DrawingML. */
     254         [ #  # ]:          0 :                 aDmlColor.setSrgbClr( nPrimaryRgb );
     255         [ #  # ]:          0 :                 aDmlColor.addTransformation( nModToken, static_cast< sal_Int32 >( nValue * ::oox::drawingml::MAX_PERCENT / 255 ) );
     256                 :            :                 return aDmlColor;
     257                 :            :             }
     258                 :            :         }
     259                 :            :     }
     260                 :            : 
     261                 :            :     OSL_FAIL( OStringBuffer( "lclGetColor - invalid VML color name '" ).
     262                 :            :         append( OUStringToOString( roVmlColor.get(), RTL_TEXTENCODING_ASCII_US ) ).append( '\'' ).getStr() );
     263         [ #  # ]:          0 :     aDmlColor.setSrgbClr( nDefaultRgb );
     264                 :         54 :     return aDmlColor;
     265                 :            : }
     266                 :            : 
     267                 :            : // ============================================================================
     268                 :            : 
     269                 :            : namespace {
     270                 :            : 
     271                 :         30 : sal_Int64 lclGetEmu( const GraphicHelper& rGraphicHelper, const OptValue< OUString >& roValue, sal_Int64 nDefValue )
     272                 :            : {
     273         [ +  + ]:         30 :     return roValue.has() ? ConversionHelper::decodeMeasureToEmu( rGraphicHelper, roValue.get(), 0, false, false ) : nDefValue;
     274                 :            : }
     275                 :            : 
     276                 :         30 : void lclGetDmlLineDash( OptValue< sal_Int32 >& oroPresetDash, LineProperties::DashStopVector& orCustomDash, const OptValue< OUString >& roDashStyle )
     277                 :            : {
     278         [ -  + ]:         30 :     if( roDashStyle.has() )
     279                 :            :     {
     280                 :          0 :         const OUString& rDashStyle = roDashStyle.get();
     281   [ #  #  #  #  :          0 :         switch( AttributeConversion::decodeToken( rDashStyle ) )
          #  #  #  #  #  
                #  #  # ]
     282                 :            :         {
     283                 :          0 :             case XML_solid:             oroPresetDash = XML_solid;          return;
     284                 :          0 :             case XML_shortdot:          oroPresetDash = XML_sysDot;         return;
     285                 :          0 :             case XML_shortdash:         oroPresetDash = XML_sysDash;        return;
     286                 :          0 :             case XML_shortdashdot:      oroPresetDash = XML_sysDashDot;     return;
     287                 :          0 :             case XML_shortdashdotdot:   oroPresetDash = XML_sysDashDotDot;  return;
     288                 :          0 :             case XML_dot:               oroPresetDash = XML_dot;            return;
     289                 :          0 :             case XML_dash:              oroPresetDash = XML_dash;           return;
     290                 :          0 :             case XML_dashdot:           oroPresetDash = XML_dashDot;        return;
     291                 :          0 :             case XML_longdash:          oroPresetDash = XML_lgDash;         return;
     292                 :          0 :             case XML_longdashdot:       oroPresetDash = XML_lgDashDot;      return;
     293                 :          0 :             case XML_longdashdotdot:    oroPresetDash = XML_lgDashDotDot;   return;
     294                 :            : 
     295                 :            :             // try to convert user-defined dash style
     296                 :            :             default:
     297                 :            :             {
     298         [ #  # ]:          0 :                 ::std::vector< sal_Int32 > aValues;
     299                 :          0 :                 sal_Int32 nIndex = 0;
     300         [ #  # ]:          0 :                 while( nIndex >= 0 )
     301         [ #  # ]:          0 :                     aValues.push_back( rDashStyle.getToken( 0, ' ', nIndex ).toInt32() );
     302                 :          0 :                 size_t nPairs = aValues.size() / 2; // ignore last value if size is odd
     303         [ #  # ]:          0 :                 for( size_t nPairIdx = 0; nPairIdx < nPairs; ++nPairIdx )
     304 [ #  # ][ #  # ]:         30 :                     orCustomDash.push_back( LineProperties::DashStop( aValues[ 2 * nPairIdx ], aValues[ 2 * nPairIdx + 1 ] ) );
         [ #  # ][ #  # ]
     305                 :            :             }
     306                 :            :         }
     307                 :            :     }
     308                 :            : }
     309                 :            : 
     310                 :         60 : sal_Int32 lclGetDmlArrowType( const OptValue< sal_Int32 >& roArrowType )
     311                 :            : {
     312 [ +  + ][ -  +  :         60 :     if( roArrowType.has() ) switch( roArrowType.get() )
             -  -  -  -  
                      - ]
     313                 :            :     {
     314                 :          0 :         case XML_none:      return XML_none;
     315                 :         12 :         case XML_block:     return XML_triangle;
     316                 :          0 :         case XML_classic:   return XML_stealth;
     317                 :          0 :         case XML_diamond:   return XML_diamond;
     318                 :          0 :         case XML_oval:      return XML_oval;
     319                 :          0 :         case XML_open:      return XML_arrow;
     320                 :            :     }
     321                 :         60 :     return XML_none;
     322                 :            : }
     323                 :            : 
     324                 :         60 : sal_Int32 lclGetDmlArrowWidth( const OptValue< sal_Int32 >& roArrowWidth )
     325                 :            : {
     326         [ +  + ]:         60 :     if( roArrowWidth.has() ) switch( roArrowWidth.get() )
           [ -  +  -  - ]
     327                 :            :     {
     328                 :          0 :         case XML_narrow:    return XML_sm;
     329                 :          3 :         case XML_medium:    return XML_med;
     330                 :          0 :         case XML_wide:      return XML_lg;
     331                 :            :     }
     332                 :         60 :     return XML_med;
     333                 :            : }
     334                 :            : 
     335                 :         60 : sal_Int32 lclGetDmlArrowLength( const OptValue< sal_Int32 >& roArrowLength )
     336                 :            : {
     337         [ +  + ]:         60 :     if( roArrowLength.has() ) switch( roArrowLength.get() )
           [ -  +  -  - ]
     338                 :            :     {
     339                 :          0 :         case XML_short:     return XML_sm;
     340                 :          3 :         case XML_medium:    return XML_med;
     341                 :          0 :         case XML_long:      return XML_lg;
     342                 :            :     }
     343                 :         60 :     return XML_med;
     344                 :            : }
     345                 :            : 
     346                 :         60 : void lclConvertArrow( LineArrowProperties& orArrowProp, const StrokeArrowModel& rStrokeArrow )
     347                 :            : {
     348         [ +  - ]:         60 :     orArrowProp.moArrowType = lclGetDmlArrowType( rStrokeArrow.moArrowType );
     349         [ +  - ]:         60 :     orArrowProp.moArrowWidth = lclGetDmlArrowWidth( rStrokeArrow.moArrowWidth );
     350         [ +  - ]:         60 :     orArrowProp.moArrowLength = lclGetDmlArrowLength( rStrokeArrow.moArrowLength );
     351                 :         60 : }
     352                 :            : 
     353                 :         30 : sal_Int32 lclGetDmlLineCompound( const OptValue< sal_Int32 >& roLineStyle )
     354                 :            : {
     355 [ -  + ][ #  #  :         30 :     if( roLineStyle.has() ) switch( roLineStyle.get() )
             #  #  #  # ]
     356                 :            :     {
     357                 :          0 :         case XML_single:            return XML_sng;
     358                 :          0 :         case XML_thinThin:          return XML_dbl;
     359                 :          0 :         case XML_thinThick:         return XML_thinThick;
     360                 :          0 :         case XML_thickThin:         return XML_thickThin;
     361                 :          0 :         case XML_thickBetweenThin:  return XML_tri;
     362                 :            :     }
     363                 :         30 :     return XML_sng;
     364                 :            : }
     365                 :            : 
     366                 :         30 : sal_Int32 lclGetDmlLineCap( const OptValue< sal_Int32 >& roEndCap )
     367                 :            : {
     368         [ -  + ]:         30 :     if( roEndCap.has() ) switch( roEndCap.get() )
           [ #  #  #  # ]
     369                 :            :     {
     370                 :          0 :         case XML_flat:      return XML_flat;
     371                 :          0 :         case XML_square:    return XML_sq;
     372                 :          0 :         case XML_round:     return XML_rnd;
     373                 :            :     }
     374                 :         30 :     return XML_flat;    // different defaults in VML (flat) and DrawingML (square)
     375                 :            : }
     376                 :            : 
     377                 :         30 : sal_Int32 lclGetDmlLineJoint( const OptValue< sal_Int32 >& roJoinStyle )
     378                 :            : {
     379         [ +  + ]:         30 :     if( roJoinStyle.has() ) switch( roJoinStyle.get() )
           [ +  -  +  - ]
     380                 :            :     {
     381                 :          3 :         case XML_round: return XML_round;
     382                 :          0 :         case XML_bevel: return XML_bevel;
     383                 :         12 :         case XML_miter: return XML_miter;
     384                 :            :     }
     385                 :         30 :     return XML_round;
     386                 :            : }
     387                 :            : 
     388                 :            : } // namespace
     389                 :            : 
     390                 :            : // ============================================================================
     391                 :            : 
     392                 :         54 : void StrokeArrowModel::assignUsed( const StrokeArrowModel& rSource )
     393                 :            : {
     394                 :         54 :     moArrowType.assignIfUsed( rSource.moArrowType );
     395                 :         54 :     moArrowWidth.assignIfUsed( rSource.moArrowWidth );
     396                 :         54 :     moArrowLength.assignIfUsed( rSource.moArrowLength );
     397                 :         54 : }
     398                 :            : 
     399                 :            : // ============================================================================
     400                 :            : 
     401                 :         27 : void StrokeModel::assignUsed( const StrokeModel& rSource )
     402                 :            : {
     403                 :         27 :     moStroked.assignIfUsed( rSource.moStroked );
     404                 :         27 :     maStartArrow.assignUsed( rSource.maStartArrow );
     405                 :         27 :     maEndArrow.assignUsed( rSource.maEndArrow );
     406                 :         27 :     moColor.assignIfUsed( rSource.moColor );
     407                 :         27 :     moOpacity.assignIfUsed( rSource.moOpacity );
     408                 :         27 :     moWeight.assignIfUsed( rSource.moWeight );
     409                 :         27 :     moDashStyle.assignIfUsed( rSource.moDashStyle );
     410                 :         27 :     moLineStyle.assignIfUsed( rSource.moLineStyle );
     411                 :         27 :     moEndCap.assignIfUsed( rSource.moEndCap );
     412                 :         27 :     moJoinStyle.assignIfUsed( rSource.moJoinStyle );
     413                 :         27 : }
     414                 :            : 
     415                 :         39 : void StrokeModel::pushToPropMap( ShapePropertyMap& rPropMap, const GraphicHelper& rGraphicHelper ) const
     416                 :            : {
     417                 :            :     /*  Convert VML line formatting to DrawingML line formatting and let the
     418                 :            :         DrawingML code do the hard work. */
     419         [ +  - ]:         39 :     LineProperties aLineProps;
     420                 :            : 
     421         [ +  + ]:         39 :     if( moStroked.get( true ) )
     422                 :            :     {
     423         [ +  - ]:         30 :         aLineProps.maLineFill.moFillType = XML_solidFill;
     424         [ +  - ]:         30 :         lclConvertArrow( aLineProps.maStartArrow, maStartArrow );
     425         [ +  - ]:         30 :         lclConvertArrow( aLineProps.maEndArrow, maEndArrow );
     426 [ +  - ][ +  - ]:         30 :         aLineProps.maLineFill.maFillColor = ConversionHelper::decodeColor( rGraphicHelper, moColor, moOpacity, API_RGB_BLACK );
                 [ +  - ]
     427 [ +  - ][ +  - ]:         30 :         aLineProps.moLineWidth = getLimitedValue< sal_Int32, sal_Int64 >( lclGetEmu( rGraphicHelper, moWeight, 1 ), 0, SAL_MAX_INT32 );
                 [ +  - ]
     428         [ +  - ]:         30 :         lclGetDmlLineDash( aLineProps.moPresetDash, aLineProps.maCustomDash, moDashStyle );
     429 [ +  - ][ +  - ]:         30 :         aLineProps.moLineCompound = lclGetDmlLineCompound( moLineStyle );
     430 [ +  - ][ +  - ]:         30 :         aLineProps.moLineCap = lclGetDmlLineCap( moEndCap );
     431 [ +  - ][ +  - ]:         30 :         aLineProps.moLineJoint = lclGetDmlLineJoint( moJoinStyle );
     432                 :            :     }
     433                 :            :     else
     434                 :            :     {
     435         [ +  - ]:          9 :         aLineProps.maLineFill.moFillType = XML_noFill;
     436                 :            :     }
     437                 :            : 
     438 [ +  - ][ +  - ]:         39 :     aLineProps.pushToPropMap( rPropMap, rGraphicHelper );
     439                 :         39 : }
     440                 :            : 
     441                 :            : // ============================================================================
     442                 :            : 
     443                 :         27 : void FillModel::assignUsed( const FillModel& rSource )
     444                 :            : {
     445                 :         27 :     moFilled.assignIfUsed( rSource.moFilled );
     446                 :         27 :     moColor.assignIfUsed( rSource.moColor );
     447                 :         27 :     moOpacity.assignIfUsed( rSource.moOpacity );
     448                 :         27 :     moColor2.assignIfUsed( rSource.moColor2 );
     449                 :         27 :     moOpacity2.assignIfUsed( rSource.moOpacity2 );
     450                 :         27 :     moType.assignIfUsed( rSource.moType );
     451                 :         27 :     moAngle.assignIfUsed( rSource.moAngle );
     452                 :         27 :     moFocus.assignIfUsed( rSource.moFocus );
     453                 :         27 :     moFocusPos.assignIfUsed( rSource.moFocusPos );
     454                 :         27 :     moFocusSize.assignIfUsed( rSource.moFocusSize );
     455                 :         27 :     moBitmapPath.assignIfUsed( rSource.moBitmapPath );
     456                 :         27 :     moRotate.assignIfUsed( rSource.moRotate );
     457                 :         27 : }
     458                 :            : 
     459                 :         39 : void FillModel::pushToPropMap( ShapePropertyMap& rPropMap, const GraphicHelper& rGraphicHelper ) const
     460                 :            : {
     461                 :            :     /*  Convert VML fill formatting to DrawingML fill formatting and let the
     462                 :            :         DrawingML code do the hard work. */
     463         [ +  - ]:         39 :     FillProperties aFillProps;
     464                 :            : 
     465         [ +  + ]:         39 :     if( moFilled.get( true ) )
     466                 :            :     {
     467                 :         24 :         sal_Int32 nFillType = moType.get( XML_solid );
     468      [ -  -  + ]:         24 :         switch( nFillType )
     469                 :            :         {
     470                 :            :             case XML_gradient:
     471                 :            :             case XML_gradientRadial:
     472                 :            :             {
     473         [ #  # ]:          0 :                 aFillProps.moFillType = XML_gradFill;
     474         [ #  # ]:          0 :                 aFillProps.maGradientProps.moRotateWithShape = moRotate.get( false );
     475                 :          0 :                 double fFocus = moFocus.get( 0.0 );
     476                 :            : 
     477                 :            :                 // prepare colors
     478         [ #  # ]:          0 :                 Color aColor1 = ConversionHelper::decodeColor( rGraphicHelper, moColor, moOpacity, API_RGB_WHITE );
     479 [ #  # ][ #  # ]:          0 :                 Color aColor2 = ConversionHelper::decodeColor( rGraphicHelper, moColor2, moOpacity2, API_RGB_WHITE, aColor1.getColor( rGraphicHelper ) );
     480                 :            : 
     481                 :            :                 // type XML_gradient is linear or axial gradient
     482         [ #  # ]:          0 :                 if( nFillType == XML_gradient )
     483                 :            :                 {
     484                 :            :                     // normalize angle to range [0;360) degrees
     485                 :          0 :                     sal_Int32 nVmlAngle = getIntervalValue< sal_Int32, sal_Int32 >( moAngle.get( 0 ), 0, 360 );
     486                 :            : 
     487                 :            :                     // focus of -50% or 50% is axial gradient
     488 [ #  # ][ #  # ]:          0 :                     if( ((-0.75 <= fFocus) && (fFocus <= -0.25)) || ((0.25 <= fFocus) && (fFocus <= 0.75)) )
         [ #  # ][ #  # ]
     489                 :            :                     {
     490                 :            :                         /*  According to spec, focus of 50% is outer-to-inner,
     491                 :            :                             and -50% is inner-to-outer (color to color2).
     492                 :            :                             BUT: For angles >= 180 deg., the behaviour is
     493                 :            :                             reversed... that's not spec'ed of course. So,
     494                 :            :                             [0;180) deg. and 50%, or [180;360) deg. and -50% is
     495                 :            :                             outer-to-inner in fact. */
     496                 :          0 :                         bool bOuterToInner = (fFocus > 0.0) == (nVmlAngle < 180);
     497                 :            :                         // simulate axial gradient by 3-step DrawingML gradient
     498         [ #  # ]:          0 :                         const Color& rOuterColor = bOuterToInner ? aColor1 : aColor2;
     499         [ #  # ]:          0 :                         const Color& rInnerColor = bOuterToInner ? aColor2 : aColor1;
     500 [ #  # ][ #  # ]:          0 :                         aFillProps.maGradientProps.maGradientStops[ 0.0 ] = aFillProps.maGradientProps.maGradientStops[ 1.0 ] = rOuterColor;
         [ #  # ][ #  # ]
     501 [ #  # ][ #  # ]:          0 :                         aFillProps.maGradientProps.maGradientStops[ 0.5 ] = rInnerColor;
     502                 :            :                     }
     503                 :            :                     else    // focus of -100%, 0%, and 100% is linear gradient
     504                 :            :                     {
     505                 :            :                         /*  According to spec, focus of -100% or 100% swaps the
     506                 :            :                             start and stop colors, effectively reversing the
     507                 :            :                             gradient. BUT: For angles >= 180 deg., the
     508                 :            :                             behaviour is reversed. This means that in this case
     509                 :            :                             a focus of 0% swaps the gradient. */
     510 [ #  # ][ #  # ]:          0 :                         if( ((fFocus < -0.75) || (fFocus > 0.75)) == (nVmlAngle < 180) )
                 [ #  # ]
     511                 :          0 :                             (nVmlAngle += 180) %= 360;
     512                 :            :                         // set the start and stop colors
     513 [ #  # ][ #  # ]:          0 :                         aFillProps.maGradientProps.maGradientStops[ 0.0 ] = aColor1;
     514 [ #  # ][ #  # ]:          0 :                         aFillProps.maGradientProps.maGradientStops[ 1.0 ] = aColor2;
     515                 :            :                     }
     516                 :            : 
     517                 :            :                     // VML counts counterclockwise from bottom, DrawingML clockwise from left
     518                 :          0 :                     sal_Int32 nDmlAngle = (630 - nVmlAngle) % 360;
     519         [ #  # ]:          0 :                     aFillProps.maGradientProps.moShadeAngle = nDmlAngle * ::oox::drawingml::PER_DEGREE;
     520                 :            :                 }
     521                 :            :                 else    // XML_gradientRadial is rectangular gradient
     522                 :            :                 {
     523         [ #  # ]:          0 :                     aFillProps.maGradientProps.moGradientPath = XML_rect;
     524                 :            :                     // convert VML focus position and size to DrawingML fill-to-rect
     525         [ #  # ]:          0 :                     DoublePair aFocusPos = moFocusPos.get( DoublePair( 0.0, 0.0 ) );
     526         [ #  # ]:          0 :                     DoublePair aFocusSize = moFocusSize.get( DoublePair( 0.0, 0.0 ) );
     527         [ #  # ]:          0 :                     double fLeft   = getLimitedValue< double, double >( aFocusPos.first, 0.0, 1.0 );
     528         [ #  # ]:          0 :                     double fTop    = getLimitedValue< double, double >( aFocusPos.second, 0.0, 1.0 );
     529         [ #  # ]:          0 :                     double fRight  = getLimitedValue< double, double >( fLeft + aFocusSize.first, fLeft, 1.0 );
     530         [ #  # ]:          0 :                     double fBottom = getLimitedValue< double, double >( fTop + aFocusSize.second, fTop, 1.0 );
     531                 :            :                     aFillProps.maGradientProps.moFillToRect = IntegerRectangle2D(
     532                 :            :                         static_cast< sal_Int32 >( fLeft * ::oox::drawingml::MAX_PERCENT ),
     533                 :            :                         static_cast< sal_Int32 >( fTop * ::oox::drawingml::MAX_PERCENT ),
     534                 :            :                         static_cast< sal_Int32 >( (1.0 - fRight) * ::oox::drawingml::MAX_PERCENT ),
     535         [ #  # ]:          0 :                         static_cast< sal_Int32 >( (1.0 - fBottom) * ::oox::drawingml::MAX_PERCENT ) );
     536                 :            : 
     537                 :            :                     // set the start and stop colors (focus of 0% means outer-to-inner)
     538 [ #  # ][ #  # ]:          0 :                     bool bOuterToInner = (-0.5 <= fFocus) && (fFocus <= 0.5);
     539 [ #  # ][ #  # ]:          0 :                     aFillProps.maGradientProps.maGradientStops[ 0.0 ] = bOuterToInner ? aColor2 : aColor1;
                 [ #  # ]
     540 [ #  # ][ #  # ]:          0 :                     aFillProps.maGradientProps.maGradientStops[ 1.0 ] = bOuterToInner ? aColor1 : aColor2;
                 [ #  # ]
     541 [ #  # ][ #  # ]:          0 :                 }
     542                 :            :             }
     543                 :          0 :             break;
     544                 :            : 
     545                 :            :             case XML_pattern:
     546                 :            :             case XML_tile:
     547                 :            :             case XML_frame:
     548                 :            :             {
     549 [ #  # ][ #  # ]:          0 :                 if( moBitmapPath.has() && !moBitmapPath.get().isEmpty() )
                 [ #  # ]
     550                 :            :                 {
     551 [ #  # ][ #  # ]:          0 :                     aFillProps.maBlipProps.mxGraphic = rGraphicHelper.importEmbeddedGraphic( moBitmapPath.get() );
     552         [ #  # ]:          0 :                     if( aFillProps.maBlipProps.mxGraphic.is() )
     553                 :            :                     {
     554         [ #  # ]:          0 :                         aFillProps.moFillType = XML_blipFill;
     555 [ #  # ][ #  # ]:          0 :                         aFillProps.maBlipProps.moBitmapMode = (nFillType == XML_frame) ? XML_stretch : XML_tile;
     556                 :          0 :                         break;  // do not break if bitmap is missing, but run to XML_solid instead
     557                 :            :                     }
     558                 :            :                 }
     559                 :            :             }
     560                 :            :             // run-through to XML_solid in case of missing bitmap path intended!
     561                 :            : 
     562                 :            :             case XML_solid:
     563                 :            :             default:
     564                 :            :             {
     565         [ +  - ]:         24 :                 aFillProps.moFillType = XML_solidFill;
     566                 :            :                 // fill color (default is white)
     567 [ +  - ][ +  - ]:         24 :                 aFillProps.maFillColor = ConversionHelper::decodeColor( rGraphicHelper, moColor, moOpacity, API_RGB_WHITE );
                 [ +  - ]
     568                 :            :             }
     569                 :            :         }
     570                 :            :     }
     571                 :            :     else
     572                 :            :     {
     573         [ +  - ]:         15 :         aFillProps.moFillType = XML_noFill;
     574                 :            :     }
     575                 :            : 
     576 [ +  - ][ +  - ]:         39 :     aFillProps.pushToPropMap( rPropMap, rGraphicHelper );
     577                 :         39 : }
     578                 :            : 
     579                 :            : // ============================================================================
     580                 :            : 
     581                 :            : } // namespace vml
     582 [ +  - ][ +  - ]:        285 : } // namespace oox
     583                 :            : 
     584                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10