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 <drawingml/fillproperties.hxx> 21 22 #include <iterator> 23 24 #include <drawingml/graphicproperties.hxx> 25 26 #include <com/sun/star/lang/XMultiServiceFactory.hpp> 27 #include <com/sun/star/beans/XPropertySet.hpp> 28 #include <com/sun/star/awt/Gradient.hpp> 29 #include <com/sun/star/text/GraphicCrop.hpp> 30 #include <com/sun/star/awt/Size.hpp> 31 #include <com/sun/star/awt/XBitmap.hpp> 32 #include <com/sun/star/drawing/BitmapMode.hpp> 33 #include <com/sun/star/drawing/ColorMode.hpp> 34 #include <com/sun/star/drawing/FillStyle.hpp> 35 #include <com/sun/star/drawing/Hatch.hpp> 36 #include <com/sun/star/drawing/RectanglePoint.hpp> 37 #include <com/sun/star/graphic/XGraphicTransformer.hpp> 38 #include <oox/core/fragmenthandler.hxx> 39 #include <oox/helper/graphichelper.hxx> 40 #include <oox/drawingml/drawingmltypes.hxx> 41 #include <oox/drawingml/shapepropertymap.hxx> 42 #include <oox/token/namespaces.hxx> 43 #include <oox/token/properties.hxx> 44 #include <oox/token/tokens.hxx> 45 #include <rtl/math.hxx> 46 #include <osl/diagnose.h> 47 #include <sal/log.hxx> 48 49 using namespace ::com::sun::star; 50 using namespace ::com::sun::star::drawing; 51 using namespace ::com::sun::star::graphic; 52 53 using ::com::sun::star::uno::Reference; 54 using ::com::sun::star::uno::Exception; 55 using ::com::sun::star::uno::UNO_QUERY_THROW; 56 using ::com::sun::star::geometry::IntegerRectangle2D; 57 58 namespace oox { 59 namespace drawingml { 60 61 namespace { 62 63 Reference< XGraphic > lclCheckAndApplyDuotoneTransform(const BlipFillProperties& aBlipProps, uno::Reference<graphic::XGraphic> const & xGraphic, 64 const GraphicHelper& rGraphicHelper, const ::Color nPhClr) 65 { 66 if (aBlipProps.maDuotoneColors[0].isUsed() && aBlipProps.maDuotoneColors[1].isUsed()) 67 { 68 ::Color nColor1 = aBlipProps.maDuotoneColors[0].getColor( rGraphicHelper, nPhClr ); 69 ::Color nColor2 = aBlipProps.maDuotoneColors[1].getColor( rGraphicHelper, nPhClr ); 70 71 uno::Reference<graphic::XGraphicTransformer> xTransformer(aBlipProps.mxFillGraphic, uno::UNO_QUERY); 72 if (xTransformer.is()) 73 return xTransformer->applyDuotone(xGraphic, sal_Int32(nColor1), sal_Int32(nColor2)); 74 } 75 return xGraphic; 76 } 77 78 Reference< XGraphic > lclCheckAndApplyChangeColorTransform(const BlipFillProperties &aBlipProps, uno::Reference<graphic::XGraphic> const & xGraphic, 79 const GraphicHelper& rGraphicHelper, const ::Color nPhClr) 80 { 81 if( aBlipProps.maColorChangeFrom.isUsed() && aBlipProps.maColorChangeTo.isUsed() ) 82 { 83 ::Color nFromColor = aBlipProps.maColorChangeFrom.getColor( rGraphicHelper, nPhClr ); 84 ::Color nToColor = aBlipProps.maColorChangeTo.getColor( rGraphicHelper, nPhClr ); 85 if ( (nFromColor != nToColor) || aBlipProps.maColorChangeTo.hasTransparency() ) 86 { 87 sal_Int16 nToTransparence = aBlipProps.maColorChangeTo.getTransparency(); 88 sal_Int8 nToAlpha = static_cast< sal_Int8 >( (100 - nToTransparence) * 2.55 ); 89 90 uno::Reference<graphic::XGraphicTransformer> xTransformer(aBlipProps.mxFillGraphic, uno::UNO_QUERY); 91 if (xTransformer.is()) 92 return xTransformer->colorChange(xGraphic, sal_Int32(nFromColor), 9, sal_Int32(nToColor), nToAlpha); 93 } 94 } 95 return xGraphic; 96 } 97 98 uno::Reference<graphic::XGraphic> applyBrightnessContrast(uno::Reference<graphic::XGraphic> const & xGraphic, sal_Int32 brightness, sal_Int32 contrast) 99 { 100 uno::Reference<graphic::XGraphicTransformer> xTransformer(xGraphic, uno::UNO_QUERY); 101 if (xTransformer.is()) 102 return xTransformer->applyBrightnessContrast(xGraphic, brightness, contrast, true); 103 return xGraphic; 104 } 105 106 BitmapMode lclGetBitmapMode( sal_Int32 nToken ) 107 { 108 OSL_ASSERT((nToken & sal_Int32(0xFFFF0000))==0); 109 switch( nToken ) 110 { 111 case XML_tile: return BitmapMode_REPEAT; 112 case XML_stretch: return BitmapMode_STRETCH; 113 } 114 return BitmapMode_NO_REPEAT; 115 } 116 117 RectanglePoint lclGetRectanglePoint( sal_Int32 nToken ) 118 { 119 OSL_ASSERT((nToken & sal_Int32(0xFFFF0000))==0); 120 switch( nToken ) 121 { 122 case XML_tl: return RectanglePoint_LEFT_TOP; 123 case XML_t: return RectanglePoint_MIDDLE_TOP; 124 case XML_tr: return RectanglePoint_RIGHT_TOP; 125 case XML_l: return RectanglePoint_LEFT_MIDDLE; 126 case XML_ctr: return RectanglePoint_MIDDLE_MIDDLE; 127 case XML_r: return RectanglePoint_RIGHT_MIDDLE; 128 case XML_bl: return RectanglePoint_LEFT_BOTTOM; 129 case XML_b: return RectanglePoint_MIDDLE_BOTTOM; 130 case XML_br: return RectanglePoint_RIGHT_BOTTOM; 131 } 132 return RectanglePoint_LEFT_TOP; 133 } 134 135 awt::Size lclGetOriginalSize( const GraphicHelper& rGraphicHelper, const Reference< XGraphic >& rxGraphic ) 136 { 137 awt::Size aSizeHmm( 0, 0 ); 138 try 139 { 140 Reference< beans::XPropertySet > xGraphicPropertySet( rxGraphic, UNO_QUERY_THROW ); 141 if( xGraphicPropertySet->getPropertyValue( "Size100thMM" ) >>= aSizeHmm ) 142 { 143 if( !aSizeHmm.Width && !aSizeHmm.Height ) 144 { // MAPMODE_PIXEL USED :-( 145 awt::Size aSourceSizePixel( 0, 0 ); 146 if( xGraphicPropertySet->getPropertyValue( "SizePixel" ) >>= aSourceSizePixel ) 147 aSizeHmm = rGraphicHelper.convertScreenPixelToHmm( aSourceSizePixel ); 148 } 149 } 150 } 151 catch( Exception& ) 152 { 153 } 154 return aSizeHmm; 155 } 156 157 /** 158 * Looks for a last gradient transition and possibly sets a gradient border 159 * based on that. 160 */ 161 void extractGradientBorderFromStops(const GradientFillProperties& rGradientProps, 162 const GraphicHelper& rGraphicHelper, ::Color nPhClr, 163 awt::Gradient& rGradient) 164 { 165 if (rGradientProps.maGradientStops.size() <= 1) 166 return; 167 168 auto it = rGradientProps.maGradientStops.rbegin(); 169 double fLastPos = it->first; 170 Color aLastColor = it->second; 171 ++it; 172 double fLastButOnePos = it->first; 173 Color aLastButOneColor = it->second; 174 if (!aLastColor.equals(aLastButOneColor, rGraphicHelper, nPhClr)) 175 return; 176 177 // Last transition has the same color, we can map that to a border. 178 rGradient.Border = rtl::math::round((fLastPos - fLastButOnePos) * 100); 179 } 180 181 } // namespace 182 183 void GradientFillProperties::assignUsed( const GradientFillProperties& rSourceProps ) 184 { 185 if( !rSourceProps.maGradientStops.empty() ) 186 maGradientStops = rSourceProps.maGradientStops; 187 moFillToRect.assignIfUsed( rSourceProps.moFillToRect ); 188 moTileRect.assignIfUsed( rSourceProps.moTileRect ); 189 moGradientPath.assignIfUsed( rSourceProps.moGradientPath ); 190 moShadeAngle.assignIfUsed( rSourceProps.moShadeAngle ); 191 moShadeFlip.assignIfUsed( rSourceProps.moShadeFlip ); 192 moShadeScaled.assignIfUsed( rSourceProps.moShadeScaled ); 193 moRotateWithShape.assignIfUsed( rSourceProps.moRotateWithShape ); 194 } 195 196 void PatternFillProperties::assignUsed( const PatternFillProperties& rSourceProps ) 197 { 198 maPattFgColor.assignIfUsed( rSourceProps.maPattFgColor ); 199 maPattBgColor.assignIfUsed( rSourceProps.maPattBgColor ); 200 moPattPreset.assignIfUsed( rSourceProps.moPattPreset ); 201 } 202 203 void BlipFillProperties::assignUsed( const BlipFillProperties& rSourceProps ) 204 { 205 if(rSourceProps.mxFillGraphic.is()) 206 mxFillGraphic = rSourceProps.mxFillGraphic; 207 moBitmapMode.assignIfUsed( rSourceProps.moBitmapMode ); 208 moFillRect.assignIfUsed( rSourceProps.moFillRect ); 209 moTileOffsetX.assignIfUsed( rSourceProps.moTileOffsetX ); 210 moTileOffsetY.assignIfUsed( rSourceProps.moTileOffsetY ); 211 moTileScaleX.assignIfUsed( rSourceProps.moTileScaleX ); 212 moTileScaleY.assignIfUsed( rSourceProps.moTileScaleY ); 213 moTileAlign.assignIfUsed( rSourceProps.moTileAlign ); 214 moTileFlip.assignIfUsed( rSourceProps.moTileFlip ); 215 moRotateWithShape.assignIfUsed( rSourceProps.moRotateWithShape ); 216 moColorEffect.assignIfUsed( rSourceProps.moColorEffect ); 217 moBrightness.assignIfUsed( rSourceProps.moBrightness ); 218 moContrast.assignIfUsed( rSourceProps.moContrast ); 219 maColorChangeFrom.assignIfUsed( rSourceProps.maColorChangeFrom ); 220 maColorChangeTo.assignIfUsed( rSourceProps.maColorChangeTo ); 221 maDuotoneColors[0].assignIfUsed( rSourceProps.maDuotoneColors[0] ); 222 maDuotoneColors[1].assignIfUsed( rSourceProps.maDuotoneColors[1] ); 223 maEffect.assignUsed( rSourceProps.maEffect ); 224 moAlphaModFix.assignIfUsed(rSourceProps.moAlphaModFix); 225 } 226 227 void FillProperties::assignUsed( const FillProperties& rSourceProps ) 228 { 229 moFillType.assignIfUsed( rSourceProps.moFillType ); 230 maFillColor.assignIfUsed( rSourceProps.maFillColor ); 231 maGradientProps.assignUsed( rSourceProps.maGradientProps ); 232 maPatternProps.assignUsed( rSourceProps.maPatternProps ); 233 maBlipProps.assignUsed( rSourceProps.maBlipProps ); 234 } 235 236 Color FillProperties::getBestSolidColor() const 237 { 238 Color aSolidColor; 239 if( moFillType.has() ) switch( moFillType.get() ) 240 { 241 case XML_solidFill: 242 aSolidColor = maFillColor; 243 break; 244 case XML_gradFill: 245 if( !maGradientProps.maGradientStops.empty() ) 246 { 247 GradientFillProperties::GradientStopMap::const_iterator aGradientStop = 248 maGradientProps.maGradientStops.begin(); 249 if (maGradientProps.maGradientStops.size() > 2) 250 ++aGradientStop; 251 aSolidColor = aGradientStop->second; 252 } 253 break; 254 case XML_pattFill: 255 aSolidColor = maPatternProps.maPattBgColor.isUsed() ? maPatternProps.maPattBgColor : maPatternProps.maPattFgColor; 256 break; 257 } 258 return aSolidColor; 259 } 260 261 /// Maps the hatch token to drawing::Hatch. 262 static drawing::Hatch createHatch( sal_Int32 nHatchToken, ::Color nColor ) 263 { 264 drawing::Hatch aHatch; 265 aHatch.Color = sal_Int32(nColor); 266 267 // best-effort mapping; we do not support all the styles in core 268 switch ( nHatchToken ) 269 { 270 case XML_pct5: aHatch.Style = drawing::HatchStyle_SINGLE; aHatch.Distance = 250; aHatch.Angle = 450; break; 271 case XML_pct10: aHatch.Style = drawing::HatchStyle_SINGLE; aHatch.Distance = 200; aHatch.Angle = 450; break; 272 case XML_pct20: aHatch.Style = drawing::HatchStyle_SINGLE; aHatch.Distance = 150; aHatch.Angle = 450; break; 273 case XML_pct25: aHatch.Style = drawing::HatchStyle_DOUBLE; aHatch.Distance = 200; aHatch.Angle = 450; break; 274 case XML_pct30: aHatch.Style = drawing::HatchStyle_DOUBLE; aHatch.Distance = 175; aHatch.Angle = 450; break; 275 case XML_pct40: aHatch.Style = drawing::HatchStyle_DOUBLE; aHatch.Distance = 150; aHatch.Angle = 450; break; 276 case XML_pct50: aHatch.Style = drawing::HatchStyle_DOUBLE; aHatch.Distance = 125; aHatch.Angle = 450; break; 277 case XML_pct60: aHatch.Style = drawing::HatchStyle_TRIPLE; aHatch.Distance = 150; aHatch.Angle = 450; break; 278 case XML_pct70: aHatch.Style = drawing::HatchStyle_TRIPLE; aHatch.Distance = 125; aHatch.Angle = 450; break; 279 case XML_pct75: aHatch.Style = drawing::HatchStyle_TRIPLE; aHatch.Distance = 100; aHatch.Angle = 450; break; 280 case XML_pct80: aHatch.Style = drawing::HatchStyle_TRIPLE; aHatch.Distance = 75; aHatch.Angle = 450; break; 281 case XML_pct90: aHatch.Style = drawing::HatchStyle_TRIPLE; aHatch.Distance = 50; aHatch.Angle = 450; break; 282 case XML_horz: aHatch.Style = drawing::HatchStyle_SINGLE; aHatch.Distance = 100; aHatch.Angle = 0; break; 283 case XML_vert: aHatch.Style = drawing::HatchStyle_SINGLE; aHatch.Distance = 100; aHatch.Angle = 900; break; 284 case XML_ltHorz: aHatch.Style = drawing::HatchStyle_SINGLE; aHatch.Distance = 50; aHatch.Angle = 0; break; 285 case XML_ltVert: aHatch.Style = drawing::HatchStyle_SINGLE; aHatch.Distance = 50; aHatch.Angle = 900; break; 286 case XML_dkHorz: aHatch.Style = drawing::HatchStyle_SINGLE; aHatch.Distance = 25; aHatch.Angle = 0; break; 287 case XML_dkVert: aHatch.Style = drawing::HatchStyle_SINGLE; aHatch.Distance = 25; aHatch.Angle = 900; break; 288 case XML_narHorz: aHatch.Style = drawing::HatchStyle_SINGLE; aHatch.Distance = 50; aHatch.Angle = 0; break; 289 case XML_narVert: aHatch.Style = drawing::HatchStyle_SINGLE; aHatch.Distance = 50; aHatch.Angle = 900; break; 290 case XML_dashHorz: aHatch.Style = drawing::HatchStyle_SINGLE; aHatch.Distance = 150; aHatch.Angle = 0; break; 291 case XML_dashVert: aHatch.Style = drawing::HatchStyle_SINGLE; aHatch.Distance = 150; aHatch.Angle = 900; break; 292 case XML_cross: aHatch.Style = drawing::HatchStyle_DOUBLE; aHatch.Distance = 100; aHatch.Angle = 0; break; 293 case XML_dnDiag: aHatch.Style = drawing::HatchStyle_SINGLE; aHatch.Distance = 100; aHatch.Angle = 1350; break; 294 case XML_upDiag: aHatch.Style = drawing::HatchStyle_SINGLE; aHatch.Distance = 100; aHatch.Angle = 450; break; 295 case XML_ltDnDiag: aHatch.Style = drawing::HatchStyle_SINGLE; aHatch.Distance = 50; aHatch.Angle = 1350; break; 296 case XML_ltUpDiag: aHatch.Style = drawing::HatchStyle_SINGLE; aHatch.Distance = 50; aHatch.Angle = 450; break; 297 case XML_dkDnDiag: aHatch.Style = drawing::HatchStyle_SINGLE; aHatch.Distance = 50; aHatch.Angle = 1350; break; 298 case XML_dkUpDiag: aHatch.Style = drawing::HatchStyle_SINGLE; aHatch.Distance = 50; aHatch.Angle = 450; break; 299 case XML_wdDnDiag: aHatch.Style = drawing::HatchStyle_SINGLE; aHatch.Distance = 100; aHatch.Angle = 1350; break; 300 case XML_wdUpDiag: aHatch.Style = drawing::HatchStyle_SINGLE; aHatch.Distance = 100; aHatch.Angle = 450; break; 301 case XML_dashDnDiag: aHatch.Style = drawing::HatchStyle_SINGLE; aHatch.Distance = 150; aHatch.Angle = 1350; break; 302 case XML_dashUpDiag: aHatch.Style = drawing::HatchStyle_SINGLE; aHatch.Distance = 150; aHatch.Angle = 450; break; 303 case XML_diagCross: aHatch.Style = drawing::HatchStyle_DOUBLE; aHatch.Distance = 100; aHatch.Angle = 450; break; 304 case XML_smCheck: aHatch.Style = drawing::HatchStyle_DOUBLE; aHatch.Distance = 50; aHatch.Angle = 450; break; 305 case XML_lgCheck: aHatch.Style = drawing::HatchStyle_DOUBLE; aHatch.Distance = 100; aHatch.Angle = 450; break; 306 case XML_smGrid: aHatch.Style = drawing::HatchStyle_DOUBLE; aHatch.Distance = 50; aHatch.Angle = 0; break; 307 case XML_lgGrid: aHatch.Style = drawing::HatchStyle_DOUBLE; aHatch.Distance = 100; aHatch.Angle = 0; break; 308 case XML_dotGrid: aHatch.Style = drawing::HatchStyle_DOUBLE; aHatch.Distance = 400; aHatch.Angle = 0; break; 309 case XML_smConfetti: aHatch.Style = drawing::HatchStyle_SINGLE; aHatch.Distance = 200; aHatch.Angle = 600; break; 310 case XML_lgConfetti: aHatch.Style = drawing::HatchStyle_SINGLE; aHatch.Distance = 100; aHatch.Angle = 600; break; 311 case XML_horzBrick: aHatch.Style = drawing::HatchStyle_DOUBLE; aHatch.Distance = 300; aHatch.Angle = 0; break; 312 case XML_diagBrick: aHatch.Style = drawing::HatchStyle_DOUBLE; aHatch.Distance = 300; aHatch.Angle = 450; break; 313 case XML_solidDmnd: aHatch.Style = drawing::HatchStyle_DOUBLE; aHatch.Distance = 100; aHatch.Angle = 450; break; 314 case XML_openDmnd: aHatch.Style = drawing::HatchStyle_DOUBLE; aHatch.Distance = 100; aHatch.Angle = 450; break; 315 case XML_dotDmnd: aHatch.Style = drawing::HatchStyle_DOUBLE; aHatch.Distance = 300; aHatch.Angle = 450; break; 316 case XML_plaid: aHatch.Style = drawing::HatchStyle_TRIPLE; aHatch.Distance = 200; aHatch.Angle = 900; break; 317 case XML_sphere: aHatch.Style = drawing::HatchStyle_TRIPLE; aHatch.Distance = 100; aHatch.Angle = 0; break; 318 case XML_weave: aHatch.Style = drawing::HatchStyle_DOUBLE; aHatch.Distance = 150; aHatch.Angle = 450; break; 319 case XML_divot: aHatch.Style = drawing::HatchStyle_TRIPLE; aHatch.Distance = 400; aHatch.Angle = 450; break; 320 case XML_shingle: aHatch.Style = drawing::HatchStyle_SINGLE; aHatch.Distance = 200; aHatch.Angle = 1350; break; 321 case XML_wave: aHatch.Style = drawing::HatchStyle_SINGLE; aHatch.Distance = 100; aHatch.Angle = 0; break; 322 case XML_trellis: aHatch.Style = drawing::HatchStyle_DOUBLE; aHatch.Distance = 75; aHatch.Angle = 450; break; 323 case XML_zigZag: aHatch.Style = drawing::HatchStyle_SINGLE; aHatch.Distance = 75; aHatch.Angle = 0; break; 324 } 325 326 return aHatch; 327 } 328 329 void FillProperties::pushToPropMap( ShapePropertyMap& rPropMap, 330 const GraphicHelper& rGraphicHelper, sal_Int32 nShapeRotation, ::Color nPhClr, 331 bool bFlipH, bool bFlipV ) const 332 { 333 if( moFillType.has() ) 334 { 335 FillStyle eFillStyle = FillStyle_NONE; 336 OSL_ASSERT((moFillType.get() & sal_Int32(0xFFFF0000))==0); 337 switch( moFillType.get() ) 338 { 339 case XML_noFill: 340 eFillStyle = FillStyle_NONE; 341 break; 342 343 case XML_solidFill: 344 if( maFillColor.isUsed() ) 345 { 346 rPropMap.setProperty( ShapeProperty::FillColor, maFillColor.getColor( rGraphicHelper, nPhClr ) ); 347 if( maFillColor.hasTransparency() ) 348 rPropMap.setProperty( ShapeProperty::FillTransparency, maFillColor.getTransparency() ); 349 eFillStyle = FillStyle_SOLID; 350 } 351 break; 352 353 case XML_gradFill: 354 // do not create gradient struct if property is not supported... 355 if( rPropMap.supportsProperty( ShapeProperty::FillGradient ) ) 356 { 357 sal_Int32 nEndTrans = 0; 358 sal_Int32 nStartTrans = 0; 359 awt::Gradient aGradient; 360 aGradient.Angle = 900; 361 aGradient.StartIntensity = 100; 362 aGradient.EndIntensity = 100; 363 364 // Old code, values in aGradient overwritten in many cases by newer code below 365 if( maGradientProps.maGradientStops.size() > 1 ) 366 { 367 aGradient.StartColor = sal_Int32(maGradientProps.maGradientStops.begin()->second.getColor( rGraphicHelper, nPhClr )); 368 aGradient.EndColor = sal_Int32(maGradientProps.maGradientStops.rbegin()->second.getColor( rGraphicHelper, nPhClr )); 369 if( maGradientProps.maGradientStops.rbegin()->second.hasTransparency() ) 370 nEndTrans = maGradientProps.maGradientStops.rbegin()->second.getTransparency()*255/100; 371 if( maGradientProps.maGradientStops.begin()->second.hasTransparency() ) 372 nStartTrans = maGradientProps.maGradientStops.begin()->second.getTransparency()*255/100; 373 } 374 375 // "rotate with shape" set to false -> do not rotate 376 if ( !maGradientProps.moRotateWithShape.get( true ) ) 377 nShapeRotation = 0; 378 379 if( maGradientProps.moGradientPath.has() ) 380 { 381 // position of gradient center (limited to [30%;100%], otherwise gradient is too hidden) 382 IntegerRectangle2D aFillToRect = maGradientProps.moFillToRect.get( IntegerRectangle2D( 0, 0, MAX_PERCENT, MAX_PERCENT ) ); 383 sal_Int32 nCenterX = (MAX_PERCENT + aFillToRect.X1 - aFillToRect.X2) / 2; 384 aGradient.XOffset = getLimitedValue<sal_Int16, sal_Int32>( 385 nCenterX / PER_PERCENT, 30, 100); 386 387 // Style should be radial at least when the horizontal center is at 50%. 388 awt::GradientStyle eCircle = aGradient.XOffset == 50 389 ? awt::GradientStyle_RADIAL 390 : awt::GradientStyle_ELLIPTICAL; 391 aGradient.Style = (maGradientProps.moGradientPath.get() == XML_circle) 392 ? eCircle 393 : awt::GradientStyle_RECT; 394 395 sal_Int32 nCenterY = (MAX_PERCENT + aFillToRect.Y1 - aFillToRect.Y2) / 2; 396 aGradient.YOffset = getLimitedValue<sal_Int16, sal_Int32>( 397 nCenterY / PER_PERCENT, 30, 100); 398 ::std::swap( aGradient.StartColor, aGradient.EndColor ); 399 ::std::swap( nStartTrans, nEndTrans ); 400 401 extractGradientBorderFromStops(maGradientProps, rGraphicHelper, nPhClr, 402 aGradient); 403 } 404 else if (!maGradientProps.maGradientStops.empty()) 405 { 406 // A copy of the gradient stops for local modification 407 GradientFillProperties::GradientStopMap aGradientStops(maGradientProps.maGradientStops); 408 409 // Add a fake gradient stop at 0% and 100% if necessary, so that the gradient always starts 410 // at 0% and ends at 100%, to make following logic clearer (?). 411 auto a0 = aGradientStops.find( 0.0 ); 412 if( a0 == aGradientStops.end() ) 413 { 414 // temp variable required 415 Color aFirstColor(aGradientStops.begin()->second); 416 aGradientStops.emplace( 0.0, aFirstColor ); 417 } 418 419 auto a1 = aGradientStops.find( 1.0 ); 420 if( a1 == aGradientStops.end() ) 421 { 422 // ditto 423 Color aLastColor(aGradientStops.rbegin()->second); 424 aGradientStops.emplace( 1.0, aLastColor ); 425 } 426 427 // Check if the gradient is symmetric, which we will emulate with an "axial" gradient. 428 bool bSymmetric(true); 429 { 430 GradientFillProperties::GradientStopMap::const_iterator aItA( aGradientStops.begin() ); 431 GradientFillProperties::GradientStopMap::const_iterator aItZ(std::prev(aGradientStops.end())); 432 while( bSymmetric && aItA->first < aItZ->first ) 433 { 434 if (!aItA->second.equals(aItZ->second, rGraphicHelper, nPhClr)) 435 bSymmetric = false; 436 else 437 { 438 ++aItA; 439 aItZ = std::prev(aItZ); 440 } 441 } 442 // Don't be fooled if the middlemost stop isn't at 0.5. 443 if( bSymmetric && aItA == aItZ && aItA->first != 0.5 ) 444 bSymmetric = false; 445 446 // If symmetric, do the rest of the logic for just a half. 447 if( bSymmetric ) 448 { 449 // aItZ already points to the colour for the middle, but insert a fake stop at the 450 // exact middle if necessary. 451 if( aItA->first != aItZ->first ) 452 { 453 Color aMiddleColor = aItZ->second; 454 auto a05 = aGradientStops.find( 0.5 ); 455 456 if( a05 != aGradientStops.end() ) 457 a05->second = aMiddleColor; 458 else 459 aGradientStops.emplace( 0.5, aMiddleColor ); 460 } 461 // Drop the rest of the stops 462 while( aGradientStops.rbegin()->first > 0.5 ) 463 aGradientStops.erase( aGradientStops.rbegin()->first ); 464 } 465 } 466 467 SAL_INFO("oox.drawingml.gradient", "symmetric: " << (bSymmetric ? "YES" : "NO") << 468 ", number of stops: " << aGradientStops.size()); 469 size_t nIndex = 0; 470 for (auto const& gradientStop : aGradientStops) 471 SAL_INFO("oox.drawingml.gradient", " " << nIndex++ << ": " << 472 gradientStop.first << ": " << 473 std::hex << sal_Int32(gradientStop.second.getColor( rGraphicHelper, nPhClr )) << std::dec << 474 "@" << (100 - gradientStop.second.getTransparency()) << "%"); 475 476 // Now estimate the simple LO style gradient (only two stops, at n% and 100%, where n == 477 // the "border") that best emulates the gradient between begin() and prior(end()). 478 479 // First look for the largest segment in the gradient. 480 GradientFillProperties::GradientStopMap::iterator aIt(aGradientStops.begin()); 481 double nWidestWidth = -1; 482 GradientFillProperties::GradientStopMap::iterator aWidestSegmentStart; 483 ++aIt; 484 while( aIt != aGradientStops.end() ) 485 { 486 if (aIt->first - std::prev(aIt)->first > nWidestWidth) 487 { 488 nWidestWidth = aIt->first - std::prev(aIt)->first; 489 aWidestSegmentStart = std::prev(aIt); 490 } 491 ++aIt; 492 } 493 assert( nWidestWidth > 0 ); 494 495 double nBorder = 0; 496 bool bSwap(false); 497 498 // Do we have just two segments, and either one is of uniform colour, or three or more 499 // segments, and the widest one is the first or last one, and is it of uniform colour? If 500 // so, deduce the border from it, and drop that segment. 501 if( aGradientStops.size() == 3 && 502 aGradientStops.begin()->second.getColor(rGraphicHelper, nPhClr) == std::next(aGradientStops.begin())->second.getColor(rGraphicHelper, nPhClr) && 503 aGradientStops.begin()->second.getTransparency() == std::next(aGradientStops.begin())->second.getTransparency()) 504 { 505 // Two segments, first is uniformly coloured 506 SAL_INFO("oox.drawingml.gradient", "two segments, first is uniformly coloured"); 507 nBorder = std::next(aGradientStops.begin())->first - aGradientStops.begin()->first; 508 aGradientStops.erase(aGradientStops.begin()); 509 aWidestSegmentStart = aGradientStops.begin(); 510 } 511 else if( !bSymmetric && 512 aGradientStops.size() == 3 && 513 std::next(aGradientStops.begin())->second.getColor(rGraphicHelper, nPhClr) == std::prev(aGradientStops.end())->second.getColor(rGraphicHelper, nPhClr) && 514 std::next(aGradientStops.begin())->second.getTransparency() == std::prev(aGradientStops.end())->second.getTransparency()) 515 { 516 // Two segments, second is uniformly coloured 517 SAL_INFO("oox.drawingml.gradient", "two segments, second is uniformly coloured"); 518 nBorder = std::prev(aGradientStops.end())->first - std::next(aGradientStops.begin())->first; 519 aGradientStops.erase(std::next(aGradientStops.begin())); 520 aWidestSegmentStart = aGradientStops.begin(); 521 bSwap = true; 522 nShapeRotation = 180*60000 - nShapeRotation; 523 } 524 else if( !bSymmetric && 525 aGradientStops.size() >= 4 && 526 aWidestSegmentStart->second.getColor( rGraphicHelper, nPhClr ) == std::next(aWidestSegmentStart)->second.getColor(rGraphicHelper, nPhClr) && 527 aWidestSegmentStart->second.getTransparency() == std::next(aWidestSegmentStart)->second.getTransparency() && 528 ( aWidestSegmentStart == aGradientStops.begin() || 529 std::next(aWidestSegmentStart) == std::prev(aGradientStops.end()))) 530 { 531 // Not symmetric, three or more segments, the widest is first or last and is uniformly coloured 532 SAL_INFO("oox.drawingml.gradient", "first or last segment is widest and is uniformly coloured"); 533 nBorder = std::next(aWidestSegmentStart)->first - aWidestSegmentStart->first; 534 535 // If it's the last segment that is uniformly coloured, rotate the gradient 180 536 // degrees and swap start and end colours 537 if (std::next(aWidestSegmentStart) == std::prev(aGradientStops.end())) 538 { 539 bSwap = true; 540 nShapeRotation = 180*60000 - nShapeRotation; 541 } 542 543 aGradientStops.erase( aWidestSegmentStart++ ); 544 545 // Look for which is widest now 546 aIt = std::next(aGradientStops.begin()); 547 nWidestWidth = -1; 548 while( aIt != aGradientStops.end() ) 549 { 550 if (aIt->first - std::prev(aIt)->first > nWidestWidth) 551 { 552 nWidestWidth = aIt->first - std::prev(aIt)->first; 553 aWidestSegmentStart = std::prev(aIt); 554 } 555 ++aIt; 556 } 557 } 558 SAL_INFO("oox.drawingml.gradient", "widest segment start: " << aWidestSegmentStart->first << ", border: " << nBorder); 559 assert( (!bSymmetric && !bSwap) || !(bSymmetric && bSwap) ); 560 561 // Now we have a potential border and a largest segment. Use those. 562 563 aGradient.Style = bSymmetric ? awt::GradientStyle_AXIAL : awt::GradientStyle_LINEAR; 564 sal_Int32 nShadeAngle = maGradientProps.moShadeAngle.get( 0 ); 565 // Adjust for flips 566 if ( bFlipH ) 567 nShadeAngle = 180*60000 - nShadeAngle; 568 if ( bFlipV ) 569 nShadeAngle = -nShadeAngle; 570 sal_Int32 nDmlAngle = nShadeAngle + nShapeRotation; 571 // convert DrawingML angle (in 1/60000 degrees) to API angle (in 1/10 degrees) 572 aGradient.Angle = static_cast< sal_Int16 >( (8100 - (nDmlAngle / (PER_DEGREE / 10))) % 3600 ); 573 Color aStartColor, aEndColor; 574 if( bSymmetric ) 575 { 576 aStartColor = std::next(aWidestSegmentStart)->second; 577 aEndColor = aWidestSegmentStart->second; 578 nBorder *= 2; 579 } 580 else if( bSwap ) 581 { 582 aStartColor = std::next(aWidestSegmentStart)->second; 583 aEndColor = aWidestSegmentStart->second; 584 } 585 else 586 { 587 aStartColor = aWidestSegmentStart->second; 588 aEndColor = std::next(aWidestSegmentStart)->second; 589 } 590 591 SAL_INFO("oox.drawingml.gradient", "start color: " << std::hex << sal_Int32(aStartColor.getColor( rGraphicHelper, nPhClr )) << std::dec << 592 "@" << (100-aStartColor.getTransparency()) << "%" 593 ", end color: " << std::hex << sal_Int32(aEndColor.getColor( rGraphicHelper, nPhClr )) << std::dec << 594 "@" << (100-aEndColor.getTransparency()) << "%"); 595 596 aGradient.StartColor = sal_Int32(aStartColor.getColor( rGraphicHelper, nPhClr )); 597 aGradient.EndColor = sal_Int32(aEndColor.getColor( rGraphicHelper, nPhClr )); 598 599 if( aStartColor.hasTransparency() ) 600 nStartTrans = aStartColor.getTransparency()*255/100; 601 if( aEndColor.hasTransparency() ) 602 nEndTrans = aEndColor.getTransparency()*255/100; 603 604 aGradient.Border = rtl::math::round(100*nBorder); 605 } 606 607 // push gradient or named gradient to property map 608 if( rPropMap.setProperty( ShapeProperty::FillGradient, aGradient ) ) 609 eFillStyle = FillStyle_GRADIENT; 610 611 // push gradient transparency to property map 612 if( nStartTrans != 0 || nEndTrans != 0 ) 613 { 614 awt::Gradient aGrad(aGradient); 615 uno::Any aVal; 616 aGrad.EndColor = static_cast<sal_Int32>( nEndTrans | nEndTrans << 8 | nEndTrans << 16 ); 617 aGrad.StartColor = static_cast<sal_Int32>( nStartTrans | nStartTrans << 8 | nStartTrans << 16 ); 618 aVal <<= aGrad; 619 rPropMap.setProperty( ShapeProperty::GradientTransparency, aGrad ); 620 } 621 622 } 623 break; 624 625 case XML_blipFill: 626 // do not start complex graphic transformation if property is not supported... 627 if (maBlipProps.mxFillGraphic.is() && rPropMap.supportsProperty(ShapeProperty::FillBitmap)) 628 { 629 uno::Reference<graphic::XGraphic> xGraphic = lclCheckAndApplyDuotoneTransform(maBlipProps, maBlipProps.mxFillGraphic, rGraphicHelper, nPhClr); 630 // TODO: "rotate with shape" is not possible with our current core 631 632 if (xGraphic.is()) 633 { 634 if (rPropMap.supportsProperty(ShapeProperty::FillBitmapName) && 635 rPropMap.setProperty(ShapeProperty::FillBitmapName, xGraphic)) 636 { 637 eFillStyle = FillStyle_BITMAP; 638 } 639 else if (rPropMap.setProperty(ShapeProperty::FillBitmap, xGraphic)) 640 { 641 eFillStyle = FillStyle_BITMAP; 642 } 643 } 644 645 // set other bitmap properties, if bitmap has been inserted into the map 646 if( eFillStyle == FillStyle_BITMAP ) 647 { 648 // bitmap mode (single, repeat, stretch) 649 BitmapMode eBitmapMode = lclGetBitmapMode( maBlipProps.moBitmapMode.get( XML_TOKEN_INVALID ) ); 650 rPropMap.setProperty( ShapeProperty::FillBitmapMode, eBitmapMode ); 651 652 // additional settings for repeated bitmap 653 if( eBitmapMode == BitmapMode_REPEAT ) 654 { 655 // anchor position inside bitmap 656 RectanglePoint eRectPoint = lclGetRectanglePoint( maBlipProps.moTileAlign.get( XML_tl ) ); 657 rPropMap.setProperty( ShapeProperty::FillBitmapRectanglePoint, eRectPoint ); 658 659 awt::Size aOriginalSize = lclGetOriginalSize(rGraphicHelper, maBlipProps.mxFillGraphic); 660 if( (aOriginalSize.Width > 0) && (aOriginalSize.Height > 0) ) 661 { 662 // size of one bitmap tile (given as 1/1000 percent of bitmap size), convert to 1/100 mm 663 double fScaleX = maBlipProps.moTileScaleX.get( MAX_PERCENT ) / static_cast< double >( MAX_PERCENT ); 664 sal_Int32 nFillBmpSizeX = getLimitedValue< sal_Int32, double >( aOriginalSize.Width * fScaleX, 1, SAL_MAX_INT32 ); 665 rPropMap.setProperty( ShapeProperty::FillBitmapSizeX, nFillBmpSizeX ); 666 double fScaleY = maBlipProps.moTileScaleY.get( MAX_PERCENT ) / static_cast< double >( MAX_PERCENT ); 667 sal_Int32 nFillBmpSizeY = getLimitedValue< sal_Int32, double >( aOriginalSize.Height * fScaleY, 1, SAL_MAX_INT32 ); 668 rPropMap.setProperty( ShapeProperty::FillBitmapSizeY, nFillBmpSizeY ); 669 670 // offset of the first bitmap tile (given as EMUs), convert to percent 671 sal_Int16 nTileOffsetX = getDoubleIntervalValue< sal_Int16 >( maBlipProps.moTileOffsetX.get( 0 ) / 3.6 / aOriginalSize.Width, 0, 100 ); 672 rPropMap.setProperty( ShapeProperty::FillBitmapOffsetX, nTileOffsetX ); 673 sal_Int16 nTileOffsetY = getDoubleIntervalValue< sal_Int16 >( maBlipProps.moTileOffsetY.get( 0 ) / 3.6 / aOriginalSize.Height, 0, 100 ); 674 rPropMap.setProperty( ShapeProperty::FillBitmapOffsetY, nTileOffsetY ); 675 } 676 } 677 else if ( eBitmapMode == BitmapMode_STRETCH && maBlipProps.moFillRect.has() ) 678 { 679 geometry::IntegerRectangle2D aFillRect( maBlipProps.moFillRect.get() ); 680 awt::Size aOriginalSize( rGraphicHelper.getOriginalSize( xGraphic ) ); 681 if ( aOriginalSize.Width && aOriginalSize.Height ) 682 { 683 text::GraphicCrop aGraphCrop( 0, 0, 0, 0 ); 684 if ( aFillRect.X1 ) 685 aGraphCrop.Left = static_cast< sal_Int32 >( ( static_cast< double >( aOriginalSize.Width ) * aFillRect.X1 ) / 100000 ); 686 if ( aFillRect.Y1 ) 687 aGraphCrop.Top = static_cast< sal_Int32 >( ( static_cast< double >( aOriginalSize.Height ) * aFillRect.Y1 ) / 100000 ); 688 if ( aFillRect.X2 ) 689 aGraphCrop.Right = static_cast< sal_Int32 >( ( static_cast< double >( aOriginalSize.Width ) * aFillRect.X2 ) / 100000 ); 690 if ( aFillRect.Y2 ) 691 aGraphCrop.Bottom = static_cast< sal_Int32 >( ( static_cast< double >( aOriginalSize.Height ) * aFillRect.Y2 ) / 100000 ); 692 rPropMap.setProperty(PROP_GraphicCrop, aGraphCrop); 693 } 694 } 695 } 696 697 if (maBlipProps.moAlphaModFix.has()) 698 rPropMap.setProperty(ShapeProperty::FillTransparency, static_cast<sal_Int16>(100 - (maBlipProps.moAlphaModFix.get() / PER_PERCENT))); 699 } 700 break; 701 702 case XML_pattFill: 703 { 704 if( rPropMap.supportsProperty( ShapeProperty::FillHatch ) ) 705 { 706 Color aColor( maPatternProps.maPattFgColor ); 707 if( aColor.isUsed() && maPatternProps.moPattPreset.has() ) 708 { 709 eFillStyle = FillStyle_HATCH; 710 rPropMap.setProperty( ShapeProperty::FillHatch, createHatch( maPatternProps.moPattPreset.get(), aColor.getColor( rGraphicHelper, nPhClr ) ) ); 711 712 // Set background color for hatch 713 if(maPatternProps.maPattBgColor.isUsed()) 714 { 715 rPropMap.setProperty( ShapeProperty::FillBackground, true ); 716 rPropMap.setProperty( ShapeProperty::FillColor, maPatternProps.maPattBgColor.getColor( rGraphicHelper, nPhClr ) ); 717 } 718 } 719 else if ( maPatternProps.maPattBgColor.isUsed() ) 720 { 721 aColor = maPatternProps.maPattBgColor; 722 rPropMap.setProperty( ShapeProperty::FillColor, aColor.getColor( rGraphicHelper, nPhClr ) ); 723 if( aColor.hasTransparency() ) 724 rPropMap.setProperty( ShapeProperty::FillTransparency, aColor.getTransparency() ); 725 eFillStyle = FillStyle_SOLID; 726 } 727 } 728 } 729 break; 730 731 case XML_grpFill: 732 // todo 733 eFillStyle = FillStyle_NONE; 734 break; 735 } 736 737 // set final fill style property 738 rPropMap.setProperty( ShapeProperty::FillStyle, eFillStyle ); 739 } 740 } 741 742 void GraphicProperties::pushToPropMap( PropertyMap& rPropMap, const GraphicHelper& rGraphicHelper) const 743 { 744 sal_Int16 nBrightness = getLimitedValue< sal_Int16, sal_Int32 >( maBlipProps.moBrightness.get( 0 ) / PER_PERCENT, -100, 100 ); 745 sal_Int16 nContrast = getLimitedValue< sal_Int16, sal_Int32 >( maBlipProps.moContrast.get( 0 ) / PER_PERCENT, -100, 100 ); 746 ColorMode eColorMode = ColorMode_STANDARD; 747 748 switch( maBlipProps.moColorEffect.get( XML_TOKEN_INVALID ) ) 749 { 750 case XML_biLevel: eColorMode = ColorMode_MONO; break; 751 case XML_grayscl: eColorMode = ColorMode_GREYS; break; 752 } 753 754 if (maBlipProps.mxFillGraphic.is()) 755 { 756 // created transformed graphic 757 uno::Reference<graphic::XGraphic> xGraphic = lclCheckAndApplyChangeColorTransform(maBlipProps, maBlipProps.mxFillGraphic, rGraphicHelper, API_RGB_TRANSPARENT); 758 xGraphic = lclCheckAndApplyDuotoneTransform(maBlipProps, xGraphic, rGraphicHelper, API_RGB_TRANSPARENT); 759 760 if (eColorMode == ColorMode_STANDARD && nBrightness == 70 && nContrast == -70) 761 // map MSO 'washout' to our Watermark colormode 762 eColorMode = ColorMode_WATERMARK; 763 else if( nBrightness != 0 && nContrast != 0 ) 764 { 765 // MSO uses a different algorithm for contrast+brightness, LO applies contrast before brightness, 766 // while MSO apparently applies half of brightness before contrast and half after. So if only 767 // contrast or brightness need to be altered, the result is the same, but if both are involved, 768 // there's no way to map that, so just force a conversion of the image. 769 xGraphic = applyBrightnessContrast( xGraphic, nBrightness, nContrast ); 770 nBrightness = 0; 771 nContrast = 0; 772 } 773 if(mbIsCustomShape) 774 { 775 // it is a cropped graphic. 776 rPropMap.setProperty(PROP_FillStyle, FillStyle_BITMAP); 777 rPropMap.setProperty(PROP_FillBitmapMode, BitmapMode_STRETCH); 778 rPropMap.setProperty(PROP_FillBitmap, xGraphic); 779 } 780 else 781 rPropMap.setProperty(PROP_Graphic, xGraphic); 782 783 // cropping 784 if ( maBlipProps.moClipRect.has() ) 785 { 786 geometry::IntegerRectangle2D oClipRect( maBlipProps.moClipRect.get() ); 787 awt::Size aOriginalSize( rGraphicHelper.getOriginalSize( xGraphic ) ); 788 if ( aOriginalSize.Width && aOriginalSize.Height ) 789 { 790 text::GraphicCrop aGraphCrop( 0, 0, 0, 0 ); 791 if ( oClipRect.X1 ) 792 aGraphCrop.Left = rtl::math::round( ( static_cast< double >( aOriginalSize.Width ) * oClipRect.X1 ) / 100000 ); 793 if ( oClipRect.Y1 ) 794 aGraphCrop.Top = rtl::math::round( ( static_cast< double >( aOriginalSize.Height ) * oClipRect.Y1 ) / 100000 ); 795 if ( oClipRect.X2 ) 796 aGraphCrop.Right = rtl::math::round( ( static_cast< double >( aOriginalSize.Width ) * oClipRect.X2 ) / 100000 ); 797 if ( oClipRect.Y2 ) 798 aGraphCrop.Bottom = rtl::math::round( ( static_cast< double >( aOriginalSize.Height ) * oClipRect.Y2 ) / 100000 ); 799 rPropMap.setProperty(PROP_GraphicCrop, aGraphCrop); 800 } 801 } 802 803 if ( maBlipProps.moAlphaModFix.has() ) 804 { 805 rPropMap.setProperty(PROP_Transparency, static_cast<sal_Int16>(100 - (maBlipProps.moAlphaModFix.get() / PER_PERCENT))); 806 } 807 } 808 rPropMap.setProperty(PROP_GraphicColorMode, eColorMode); 809 810 // brightness and contrast 811 if( nBrightness != 0 ) 812 rPropMap.setProperty(PROP_AdjustLuminance, nBrightness); 813 if( nContrast != 0 ) 814 rPropMap.setProperty(PROP_AdjustContrast, nContrast); 815 816 // Media content 817 assert(m_xMediaStream.is() != m_sMediaPackageURL.isEmpty()); 818 if (m_xMediaStream.is() && !m_sMediaPackageURL.isEmpty()) 819 { 820 rPropMap.setProperty(PROP_PrivateStream, m_xMediaStream); 821 rPropMap.setProperty(PROP_MediaURL, m_sMediaPackageURL); 822 } 823 } 824 825 bool ArtisticEffectProperties::isEmpty() const 826 { 827 return msName.isEmpty(); 828 } 829 830 css::beans::PropertyValue ArtisticEffectProperties::getEffect() 831 { 832 css::beans::PropertyValue aRet; 833 if( msName.isEmpty() ) 834 return aRet; 835 836 css::uno::Sequence< css::beans::PropertyValue > aSeq( maAttribs.size() + 1 ); 837 sal_uInt32 i = 0; 838 for (auto const& attrib : maAttribs) 839 { 840 aSeq[i].Name = attrib.first; 841 aSeq[i].Value = attrib.second; 842 i++; 843 } 844 845 if( mrOleObjectInfo.maEmbeddedData.hasElements() ) 846 { 847 css::uno::Sequence< css::beans::PropertyValue > aGraphicSeq( 2 ); 848 aGraphicSeq[0].Name = "Id"; 849 aGraphicSeq[0].Value <<= mrOleObjectInfo.maProgId; 850 aGraphicSeq[1].Name = "Data"; 851 aGraphicSeq[1].Value <<= mrOleObjectInfo.maEmbeddedData; 852 853 aSeq[i].Name = "OriginalGraphic"; 854 aSeq[i].Value <<= aGraphicSeq; 855 } 856 857 aRet.Name = msName; 858 aRet.Value <<= aSeq; 859 860 return aRet; 861 } 862 863 void ArtisticEffectProperties::assignUsed( const ArtisticEffectProperties& rSourceProps ) 864 { 865 if( !rSourceProps.isEmpty() ) 866 { 867 msName = rSourceProps.msName; 868 maAttribs = rSourceProps.maAttribs; 869 } 870 } 871 872 OUString ArtisticEffectProperties::getEffectString( sal_Int32 nToken ) 873 { 874 switch( nToken ) 875 { 876 // effects 877 case OOX_TOKEN( a14, artisticBlur ): return "artisticBlur"; 878 case OOX_TOKEN( a14, artisticCement ): return "artisticCement"; 879 case OOX_TOKEN( a14, artisticChalkSketch ): return "artisticChalkSketch"; 880 case OOX_TOKEN( a14, artisticCrisscrossEtching ): return "artisticCrisscrossEtching"; 881 case OOX_TOKEN( a14, artisticCutout ): return "artisticCutout"; 882 case OOX_TOKEN( a14, artisticFilmGrain ): return "artisticFilmGrain"; 883 case OOX_TOKEN( a14, artisticGlass ): return "artisticGlass"; 884 case OOX_TOKEN( a14, artisticGlowDiffused ): return "artisticGlowDiffused"; 885 case OOX_TOKEN( a14, artisticGlowEdges ): return "artisticGlowEdges"; 886 case OOX_TOKEN( a14, artisticLightScreen ): return "artisticLightScreen"; 887 case OOX_TOKEN( a14, artisticLineDrawing ): return "artisticLineDrawing"; 888 case OOX_TOKEN( a14, artisticMarker ): return "artisticMarker"; 889 case OOX_TOKEN( a14, artisticMosiaicBubbles ): return "artisticMosiaicBubbles"; 890 case OOX_TOKEN( a14, artisticPaintStrokes ): return "artisticPaintStrokes"; 891 case OOX_TOKEN( a14, artisticPaintBrush ): return "artisticPaintBrush"; 892 case OOX_TOKEN( a14, artisticPastelsSmooth ): return "artisticPastelsSmooth"; 893 case OOX_TOKEN( a14, artisticPencilGrayscale ): return "artisticPencilGrayscale"; 894 case OOX_TOKEN( a14, artisticPencilSketch ): return "artisticPencilSketch"; 895 case OOX_TOKEN( a14, artisticPhotocopy ): return "artisticPhotocopy"; 896 case OOX_TOKEN( a14, artisticPlasticWrap ): return "artisticPlasticWrap"; 897 case OOX_TOKEN( a14, artisticTexturizer ): return "artisticTexturizer"; 898 case OOX_TOKEN( a14, artisticWatercolorSponge ): return "artisticWatercolorSponge"; 899 case OOX_TOKEN( a14, brightnessContrast ): return "brightnessContrast"; 900 case OOX_TOKEN( a14, colorTemperature ): return "colorTemperature"; 901 case OOX_TOKEN( a14, saturation ): return "saturation"; 902 case OOX_TOKEN( a14, sharpenSoften ): return "sharpenSoften"; 903 904 // attributes 905 case XML_visible: return "visible"; 906 case XML_trans: return "trans"; 907 case XML_crackSpacing: return "crackSpacing"; 908 case XML_pressure: return "pressure"; 909 case XML_numberOfShades: return "numberOfShades"; 910 case XML_grainSize: return "grainSize"; 911 case XML_intensity: return "intensity"; 912 case XML_smoothness: return "smoothness"; 913 case XML_gridSize: return "gridSize"; 914 case XML_pencilSize: return "pencilSize"; 915 case XML_size: return "size"; 916 case XML_brushSize: return "brushSize"; 917 case XML_scaling: return "scaling"; 918 case XML_detail: return "detail"; 919 case XML_bright: return "bright"; 920 case XML_contrast: return "contrast"; 921 case XML_colorTemp: return "colorTemp"; 922 case XML_sat: return "sat"; 923 case XML_amount: return "amount"; 924 } 925 SAL_WARN( "oox.drawingml", "ArtisticEffectProperties::getEffectString: unexpected token " << nToken ); 926 return OUString(); 927 } 928 929 sal_Int32 ArtisticEffectProperties::getEffectToken( const OUString& sName ) 930 { 931 // effects 932 if( sName == "artisticBlur" ) 933 return XML_artisticBlur; 934 else if( sName == "artisticCement" ) 935 return XML_artisticCement; 936 else if( sName == "artisticChalkSketch" ) 937 return XML_artisticChalkSketch; 938 else if( sName == "artisticCrisscrossEtching" ) 939 return XML_artisticCrisscrossEtching; 940 else if( sName == "artisticCutout" ) 941 return XML_artisticCutout; 942 else if( sName == "artisticFilmGrain" ) 943 return XML_artisticFilmGrain; 944 else if( sName == "artisticGlass" ) 945 return XML_artisticGlass; 946 else if( sName == "artisticGlowDiffused" ) 947 return XML_artisticGlowDiffused; 948 else if( sName == "artisticGlowEdges" ) 949 return XML_artisticGlowEdges; 950 else if( sName == "artisticLightScreen" ) 951 return XML_artisticLightScreen; 952 else if( sName == "artisticLineDrawing" ) 953 return XML_artisticLineDrawing; 954 else if( sName == "artisticMarker" ) 955 return XML_artisticMarker; 956 else if( sName == "artisticMosiaicBubbles" ) 957 return XML_artisticMosiaicBubbles; 958 else if( sName == "artisticPaintStrokes" ) 959 return XML_artisticPaintStrokes; 960 else if( sName == "artisticPaintBrush" ) 961 return XML_artisticPaintBrush; 962 else if( sName == "artisticPastelsSmooth" ) 963 return XML_artisticPastelsSmooth; 964 else if( sName == "artisticPencilGrayscale" ) 965 return XML_artisticPencilGrayscale; 966 else if( sName == "artisticPencilSketch" ) 967 return XML_artisticPencilSketch; 968 else if( sName == "artisticPhotocopy" ) 969 return XML_artisticPhotocopy; 970 else if( sName == "artisticPlasticWrap" ) 971 return XML_artisticPlasticWrap; 972 else if( sName == "artisticTexturizer" ) 973 return XML_artisticTexturizer; 974 else if( sName == "artisticWatercolorSponge" ) 975 return XML_artisticWatercolorSponge; 976 else if( sName == "brightnessContrast" ) 977 return XML_brightnessContrast; 978 else if( sName == "colorTemperature" ) 979 return XML_colorTemperature; 980 else if( sName == "saturation" ) 981 return XML_saturation; 982 else if( sName == "sharpenSoften" ) 983 return XML_sharpenSoften; 984 985 // attributes 986 else if( sName == "visible" ) 987 return XML_visible; 988 else if( sName == "trans" ) 989 return XML_trans; 990 else if( sName == "crackSpacing" ) 991 return XML_crackSpacing; 992 else if( sName == "pressure" ) 993 return XML_pressure; 994 else if( sName == "numberOfShades" ) 995 return XML_numberOfShades; 996 else if( sName == "grainSize" ) 997 return XML_grainSize; 998 else if( sName == "intensity" ) 999 return XML_intensity; 1000 else if( sName == "smoothness" ) 1001 return XML_smoothness; 1002 else if( sName == "gridSize" ) 1003 return XML_gridSize; 1004 else if( sName == "pencilSize" ) 1005 return XML_pencilSize; 1006 else if( sName == "size" ) 1007 return XML_size; 1008 else if( sName == "brushSize" ) 1009 return XML_brushSize; 1010 else if( sName == "scaling" ) 1011 return XML_scaling; 1012 else if( sName == "detail" ) 1013 return XML_detail; 1014 else if( sName == "bright" ) 1015 return XML_bright; 1016 else if( sName == "contrast" ) 1017 return XML_contrast; 1018 else if( sName == "colorTemp" ) 1019 return XML_colorTemp; 1020 else if( sName == "sat" ) 1021 return XML_sat; 1022 else if( sName == "amount" ) 1023 return XML_amount; 1024 1025 SAL_WARN( "oox.drawingml", "ArtisticEffectProperties::getEffectToken - unexpected token name" ); 1026 return XML_none; 1027 } 1028 1029 } // namespace drawingml 1030 } // namespace oox 1031 1032 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 1033
