tdf#131098 docx export: write fill property of graphic
[LibreOffice.git] / oox / source / drawingml / fillproperties.cxx
blobf671eea2e04344c87c18c7806faa9a137344c220
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <drawingml/fillproperties.hxx>
22 #include <iterator>
24 #include <comphelper/propertyvalue.hxx>
25 #include <drawingml/graphicproperties.hxx>
26 #include <vcl/graph.hxx>
27 #include <vcl/BitmapFilter.hxx>
28 #include <vcl/BitmapMonochromeFilter.hxx>
29 #include <docmodel/uno/UnoComplexColor.hxx>
30 #include <docmodel/uno/UnoGradientTools.hxx>
31 #include <basegfx/utils/gradienttools.hxx>
33 #include <com/sun/star/beans/XPropertySet.hpp>
34 #include <com/sun/star/awt/Gradient2.hpp>
35 #include <com/sun/star/text/GraphicCrop.hpp>
36 #include <com/sun/star/awt/Size.hpp>
37 #include <com/sun/star/drawing/BitmapMode.hpp>
38 #include <com/sun/star/drawing/ColorMode.hpp>
39 #include <com/sun/star/drawing/FillStyle.hpp>
40 #include <com/sun/star/drawing/RectanglePoint.hpp>
41 #include <com/sun/star/graphic/XGraphicTransformer.hpp>
42 #include <oox/helper/graphichelper.hxx>
43 #include <oox/drawingml/drawingmltypes.hxx>
44 #include <oox/drawingml/shapepropertymap.hxx>
45 #include <drawingml/hatchmap.hxx>
46 #include <oox/token/namespaces.hxx>
47 #include <oox/token/properties.hxx>
48 #include <oox/token/tokens.hxx>
49 #include <osl/diagnose.h>
50 #include <sal/log.hxx>
52 #include <frozen/bits/defines.h>
53 #include <frozen/bits/elsa_std.h>
54 #include <frozen/unordered_map.h>
57 using namespace ::com::sun::star;
58 using namespace ::com::sun::star::drawing;
59 using namespace ::com::sun::star::graphic;
61 using ::com::sun::star::uno::Reference;
62 using ::com::sun::star::uno::Exception;
63 using ::com::sun::star::uno::UNO_QUERY_THROW;
64 using ::com::sun::star::geometry::IntegerRectangle2D;
66 namespace oox::drawingml {
68 namespace {
70 Reference< XGraphic > lclCheckAndApplyDuotoneTransform(const BlipFillProperties& aBlipProps, uno::Reference<graphic::XGraphic> const & xGraphic,
71 const GraphicHelper& rGraphicHelper, const ::Color nPhClr)
73 if (aBlipProps.maDuotoneColors[0].isUsed() && aBlipProps.maDuotoneColors[1].isUsed())
75 ::Color nColor1 = aBlipProps.maDuotoneColors[0].getColor( rGraphicHelper, nPhClr );
76 ::Color nColor2 = aBlipProps.maDuotoneColors[1].getColor( rGraphicHelper, nPhClr );
78 uno::Reference<graphic::XGraphicTransformer> xTransformer(aBlipProps.mxFillGraphic, uno::UNO_QUERY);
79 if (xTransformer.is())
80 return xTransformer->applyDuotone(xGraphic, sal_Int32(nColor1), sal_Int32(nColor2));
82 return xGraphic;
85 Reference< XGraphic > lclRotateGraphic(uno::Reference<graphic::XGraphic> const & xGraphic, Degree10 nRotation)
87 ::Graphic aGraphic(xGraphic);
88 ::Graphic aReturnGraphic;
90 assert (aGraphic.GetType() == GraphicType::Bitmap);
92 BitmapEx aBitmapEx(aGraphic.GetBitmapEx());
93 const ::Color& aColor = ::Color(0x00);
94 aBitmapEx.Rotate(nRotation, aColor);
95 aReturnGraphic = ::Graphic(aBitmapEx);
96 aReturnGraphic.setOriginURL(aGraphic.getOriginURL());
98 return aReturnGraphic.GetXGraphic();
101 using Quotients = std::tuple<double, double, double, double>;
102 Quotients getQuotients(geometry::IntegerRectangle2D aRelRect, double hDiv, double vDiv)
104 return { aRelRect.X1 / hDiv, aRelRect.Y1 / vDiv, aRelRect.X2 / hDiv, aRelRect.Y2 / vDiv };
107 // ECMA-376 Part 1 20.1.8.55 srcRect (Source Rectangle)
108 std::optional<Quotients> CropQuotientsFromSrcRect(geometry::IntegerRectangle2D aSrcRect)
110 aSrcRect.X1 = std::max(aSrcRect.X1, sal_Int32(0));
111 aSrcRect.X2 = std::max(aSrcRect.X2, sal_Int32(0));
112 aSrcRect.Y1 = std::max(aSrcRect.Y1, sal_Int32(0));
113 aSrcRect.Y2 = std::max(aSrcRect.Y2, sal_Int32(0));
114 if (aSrcRect.X1 + aSrcRect.X2 >= MAX_PERCENT || aSrcRect.Y1 + aSrcRect.Y2 >= MAX_PERCENT)
115 return {}; // Cropped everything
116 return getQuotients(aSrcRect, MAX_PERCENT, MAX_PERCENT);
119 // ECMA-376 Part 1 20.1.8.30 fillRect (Fill Rectangle)
120 std::optional<Quotients> CropQuotientsFromFillRect(geometry::IntegerRectangle2D aFillRect)
122 aFillRect.X1 = std::min(aFillRect.X1, sal_Int32(0));
123 aFillRect.X2 = std::min(aFillRect.X2, sal_Int32(0));
124 aFillRect.Y1 = std::min(aFillRect.Y1, sal_Int32(0));
125 aFillRect.Y2 = std::min(aFillRect.Y2, sal_Int32(0));
126 // Negative divisor and negative relative offset give positive value wanted in lclCropGraphic
127 return getQuotients(aFillRect, -MAX_PERCENT + aFillRect.X1 + aFillRect.X2,
128 -MAX_PERCENT + aFillRect.Y1 + aFillRect.Y2);
131 // Crops a piece of the bitmap. lclCropGraphic doesn't handle growing.
132 Reference<XGraphic> lclCropGraphic(uno::Reference<graphic::XGraphic> const& xGraphic,
133 std::optional<Quotients> quotients)
135 ::Graphic aGraphic(xGraphic);
136 assert (aGraphic.GetType() == GraphicType::Bitmap);
138 BitmapEx aBitmapEx;
139 if (quotients)
141 aBitmapEx = aGraphic.GetBitmapEx();
143 const Size bmpSize = aBitmapEx.GetSizePixel();
144 const auto& [qx1, qy1, qx2, qy2] = *quotients;
145 const tools::Long l = std::round(bmpSize.Width() * qx1);
146 const tools::Long t = std::round(bmpSize.Height() * qy1);
147 const tools::Long r = std::round(bmpSize.Width() * qx2);
148 const tools::Long b = std::round(bmpSize.Height() * qy2);
150 aBitmapEx.Crop({ l, t, bmpSize.Width() - r - 1, bmpSize.Height() - b - 1 });
153 ::Graphic aReturnGraphic(aBitmapEx);
154 aReturnGraphic.setOriginURL(aGraphic.getOriginURL());
156 return aReturnGraphic.GetXGraphic();
159 Reference< XGraphic > lclMirrorGraphic(uno::Reference<graphic::XGraphic> const & xGraphic, bool bFlipH, bool bFlipV)
161 ::Graphic aGraphic(xGraphic);
162 ::Graphic aReturnGraphic;
164 assert (aGraphic.GetType() == GraphicType::Bitmap);
166 BitmapEx aBitmapEx(aGraphic.GetBitmapEx());
167 BmpMirrorFlags nMirrorFlags = BmpMirrorFlags::NONE;
169 if(bFlipH)
170 nMirrorFlags |= BmpMirrorFlags::Horizontal;
171 if(bFlipV)
172 nMirrorFlags |= BmpMirrorFlags::Vertical;
174 aBitmapEx.Mirror(nMirrorFlags);
176 aReturnGraphic = ::Graphic(aBitmapEx);
177 aReturnGraphic.setOriginURL(aGraphic.getOriginURL());
179 return aReturnGraphic.GetXGraphic();
182 Reference< XGraphic > lclGreysScaleGraphic(uno::Reference<graphic::XGraphic> const & xGraphic)
184 ::Graphic aGraphic(xGraphic);
185 ::Graphic aReturnGraphic;
187 assert (aGraphic.GetType() == GraphicType::Bitmap);
189 BitmapEx aBitmapEx(aGraphic.GetBitmapEx());
190 aBitmapEx.Convert(BmpConversion::N8BitGreys);
192 aReturnGraphic = ::Graphic(aBitmapEx);
193 aReturnGraphic.setOriginURL(aGraphic.getOriginURL());
195 return aReturnGraphic.GetXGraphic();
198 /// Applies the graphic Black&White (Monochrome) effect with the imported threshold
199 Reference<XGraphic> lclApplyBlackWhiteEffect(const BlipFillProperties& aBlipProps,
200 const uno::Reference<graphic::XGraphic>& xGraphic)
202 const auto& oBiLevelThreshold = aBlipProps.moBiLevelThreshold;
203 if (oBiLevelThreshold.has_value())
205 sal_uInt8 nThreshold
206 = static_cast<sal_uInt8>(oBiLevelThreshold.value() * 255 / MAX_PERCENT);
208 ::Graphic aGraphic(xGraphic);
209 ::Graphic aReturnGraphic;
211 BitmapEx aBitmapEx(aGraphic.GetBitmapEx());
212 AlphaMask aMask(aBitmapEx.GetAlphaMask());
214 BitmapEx aTmpBmpEx(aBitmapEx.GetBitmap());
215 BitmapFilter::Filter(aTmpBmpEx, BitmapMonochromeFilter{ nThreshold });
217 aReturnGraphic = ::Graphic(BitmapEx(aTmpBmpEx.GetBitmap(), aMask));
218 aReturnGraphic.setOriginURL(aGraphic.getOriginURL());
219 return aReturnGraphic.GetXGraphic();
221 return xGraphic;
224 Reference< XGraphic > lclCheckAndApplyChangeColorTransform(const BlipFillProperties &aBlipProps, uno::Reference<graphic::XGraphic> const & xGraphic,
225 const GraphicHelper& rGraphicHelper, const ::Color nPhClr)
227 if( aBlipProps.maColorChangeFrom.isUsed() && aBlipProps.maColorChangeTo.isUsed() )
229 ::Color nFromColor = aBlipProps.maColorChangeFrom.getColor( rGraphicHelper, nPhClr );
230 ::Color nToColor = aBlipProps.maColorChangeTo.getColor( rGraphicHelper, nPhClr );
231 if ( (nFromColor != nToColor) || aBlipProps.maColorChangeTo.hasTransparency() )
233 sal_Int16 nToTransparence = aBlipProps.maColorChangeTo.getTransparency();
234 sal_Int8 nToAlpha = static_cast< sal_Int8 >( (100 - nToTransparence) * 2.55 );
236 sal_uInt8 nTolerance = 9;
237 Graphic aGraphic{ xGraphic };
238 if( aGraphic.IsGfxLink() )
240 // tdf#149670: Try to guess tolerance depending on image format
241 switch (aGraphic.GetGfxLink().GetType())
243 case GfxLinkType::NativeJpg:
244 nTolerance = 15;
245 break;
246 case GfxLinkType::NativePng:
247 case GfxLinkType::NativeTif:
248 nTolerance = 1;
249 break;
250 case GfxLinkType::NativeBmp:
251 nTolerance = 0;
252 break;
253 default:
254 break;
258 uno::Reference<graphic::XGraphicTransformer> xTransformer(aBlipProps.mxFillGraphic, uno::UNO_QUERY);
259 if (xTransformer.is())
260 return xTransformer->colorChange(xGraphic, sal_Int32(nFromColor), nTolerance, sal_Int32(nToColor), nToAlpha);
263 return xGraphic;
266 uno::Reference<graphic::XGraphic> applyBrightnessContrast(uno::Reference<graphic::XGraphic> const & xGraphic, sal_Int32 brightness, sal_Int32 contrast)
268 uno::Reference<graphic::XGraphicTransformer> xTransformer(xGraphic, uno::UNO_QUERY);
269 if (xTransformer.is())
270 return xTransformer->applyBrightnessContrast(xGraphic, brightness, contrast, true);
271 return xGraphic;
274 BitmapMode lclGetBitmapMode( sal_Int32 nToken )
276 OSL_ASSERT((nToken & sal_Int32(0xFFFF0000))==0);
277 switch( nToken )
279 case XML_tile: return BitmapMode_REPEAT;
280 case XML_stretch: return BitmapMode_STRETCH;
283 // tdf#128596 Default value is XML_tile for MSO.
284 return BitmapMode_REPEAT;
287 RectanglePoint lclGetRectanglePoint( sal_Int32 nToken )
289 OSL_ASSERT((nToken & sal_Int32(0xFFFF0000))==0);
290 switch( nToken )
292 case XML_tl: return RectanglePoint_LEFT_TOP;
293 case XML_t: return RectanglePoint_MIDDLE_TOP;
294 case XML_tr: return RectanglePoint_RIGHT_TOP;
295 case XML_l: return RectanglePoint_LEFT_MIDDLE;
296 case XML_ctr: return RectanglePoint_MIDDLE_MIDDLE;
297 case XML_r: return RectanglePoint_RIGHT_MIDDLE;
298 case XML_bl: return RectanglePoint_LEFT_BOTTOM;
299 case XML_b: return RectanglePoint_MIDDLE_BOTTOM;
300 case XML_br: return RectanglePoint_RIGHT_BOTTOM;
302 return RectanglePoint_LEFT_TOP;
305 awt::Size lclGetOriginalSize( const GraphicHelper& rGraphicHelper, const Reference< XGraphic >& rxGraphic )
307 awt::Size aSizeHmm( 0, 0 );
310 Reference< beans::XPropertySet > xGraphicPropertySet( rxGraphic, UNO_QUERY_THROW );
311 if( xGraphicPropertySet->getPropertyValue( u"Size100thMM"_ustr ) >>= aSizeHmm )
313 if( !aSizeHmm.Width && !aSizeHmm.Height )
314 { // MAPMODE_PIXEL USED :-(
315 awt::Size aSourceSizePixel( 0, 0 );
316 if( xGraphicPropertySet->getPropertyValue( u"SizePixel"_ustr ) >>= aSourceSizePixel )
317 aSizeHmm = rGraphicHelper.convertScreenPixelToHmm( aSourceSizePixel );
321 catch( Exception& )
324 return aSizeHmm;
327 } // namespace
329 void GradientFillProperties::assignUsed( const GradientFillProperties& rSourceProps )
331 if( !rSourceProps.maGradientStops.empty() )
332 maGradientStops = rSourceProps.maGradientStops;
333 assignIfUsed( moFillToRect, rSourceProps.moFillToRect );
334 assignIfUsed( moTileRect, rSourceProps.moTileRect );
335 assignIfUsed( moGradientPath, rSourceProps.moGradientPath );
336 assignIfUsed( moShadeAngle, rSourceProps.moShadeAngle );
337 assignIfUsed( moShadeFlip, rSourceProps.moShadeFlip );
338 assignIfUsed( moShadeScaled, rSourceProps.moShadeScaled );
339 assignIfUsed( moRotateWithShape, rSourceProps.moRotateWithShape );
342 void PatternFillProperties::assignUsed( const PatternFillProperties& rSourceProps )
344 maPattFgColor.assignIfUsed( rSourceProps.maPattFgColor );
345 maPattBgColor.assignIfUsed( rSourceProps.maPattBgColor );
346 assignIfUsed( moPattPreset, rSourceProps.moPattPreset );
349 void BlipFillProperties::assignUsed( const BlipFillProperties& rSourceProps )
351 if(rSourceProps.mxFillGraphic.is())
352 mxFillGraphic = rSourceProps.mxFillGraphic;
353 assignIfUsed( moBitmapMode, rSourceProps.moBitmapMode );
354 assignIfUsed( moFillRect, rSourceProps.moFillRect );
355 assignIfUsed( moTileOffsetX, rSourceProps.moTileOffsetX );
356 assignIfUsed( moTileOffsetY, rSourceProps.moTileOffsetY );
357 assignIfUsed( moTileScaleX, rSourceProps.moTileScaleX );
358 assignIfUsed( moTileScaleY, rSourceProps.moTileScaleY );
359 assignIfUsed( moTileAlign, rSourceProps.moTileAlign );
360 assignIfUsed( moTileFlip, rSourceProps.moTileFlip );
361 assignIfUsed( moRotateWithShape, rSourceProps.moRotateWithShape );
362 assignIfUsed( moColorEffect, rSourceProps.moColorEffect );
363 assignIfUsed( moBrightness, rSourceProps.moBrightness );
364 assignIfUsed( moContrast, rSourceProps.moContrast );
365 assignIfUsed( moBiLevelThreshold, rSourceProps.moBiLevelThreshold );
366 maColorChangeFrom.assignIfUsed( rSourceProps.maColorChangeFrom );
367 maColorChangeTo.assignIfUsed( rSourceProps.maColorChangeTo );
368 maDuotoneColors[0].assignIfUsed( rSourceProps.maDuotoneColors[0] );
369 maDuotoneColors[1].assignIfUsed( rSourceProps.maDuotoneColors[1] );
370 maEffect.assignUsed( rSourceProps.maEffect );
371 assignIfUsed(moAlphaModFix, rSourceProps.moAlphaModFix);
374 void FillProperties::assignUsed( const FillProperties& rSourceProps )
376 assignIfUsed( moFillType, rSourceProps.moFillType );
377 maFillColor.assignIfUsed( rSourceProps.maFillColor );
378 assignIfUsed( moUseBgFill, rSourceProps.moUseBgFill );
379 maGradientProps.assignUsed( rSourceProps.maGradientProps );
380 maPatternProps.assignUsed( rSourceProps.maPatternProps );
381 maBlipProps.assignUsed( rSourceProps.maBlipProps );
384 Color FillProperties::getBestSolidColor() const
386 Color aSolidColor;
387 if( moFillType.has_value() ) switch( moFillType.value() )
389 case XML_solidFill:
390 aSolidColor = maFillColor;
391 break;
392 case XML_gradFill:
393 if( !maGradientProps.maGradientStops.empty() )
395 GradientFillProperties::GradientStopMap::const_iterator aGradientStop =
396 maGradientProps.maGradientStops.begin();
397 if (maGradientProps.maGradientStops.size() > 2)
398 ++aGradientStop;
399 aSolidColor = aGradientStop->second;
401 break;
402 case XML_pattFill:
403 aSolidColor = maPatternProps.maPattBgColor.isUsed() ? maPatternProps.maPattBgColor : maPatternProps.maPattFgColor;
404 break;
406 return aSolidColor;
409 void FillProperties::pushToPropMap(ShapePropertyMap& rPropMap, const GraphicHelper& rGraphicHelper,
410 sal_Int32 nShapeRotation, ::Color nPhClr,
411 const css::awt::Size& rSize, sal_Int16 nPhClrTheme, bool bFlipH,
412 bool bFlipV, bool bIsCustomShape) const
414 if( !moFillType.has_value() )
415 return;
417 FillStyle eFillStyle = FillStyle_NONE;
418 OSL_ASSERT((moFillType.value() & sal_Int32(0xFFFF0000))==0);
419 switch( moFillType.value() )
421 case XML_noFill:
423 eFillStyle = FillStyle_NONE;
424 rPropMap.setProperty(ShapeProperty::FillUseSlideBackground, moUseBgFill.value_or(false));
426 break;
428 case XML_solidFill:
429 if( maFillColor.isUsed() )
431 ::Color aFillColor = maFillColor.getColor(rGraphicHelper, nPhClr);
432 rPropMap.setProperty(ShapeProperty::FillColor, aFillColor);
433 if( maFillColor.hasTransparency() )
434 rPropMap.setProperty( ShapeProperty::FillTransparency, maFillColor.getTransparency() );
436 model::ComplexColor aComplexColor;
437 if (aFillColor == nPhClr)
439 aComplexColor.setThemeColor(model::convertToThemeColorType(nPhClrTheme));
441 else
443 aComplexColor = maFillColor.getComplexColor();
445 rPropMap.setProperty(PROP_FillComplexColor, model::color::createXComplexColor(aComplexColor));
447 eFillStyle = FillStyle_SOLID;
449 break;
451 case XML_gradFill:
452 // do not create gradient struct if property is not supported...
453 if( rPropMap.supportsProperty( ShapeProperty::FillGradient ) )
455 // prepare ColorStops
456 basegfx::BColorStops aColorStops;
457 basegfx::BColorStops aTransparencyStops;
458 bool bContainsTransparency(false);
460 // convert to BColorStops, check for contained transparency
461 for (const auto& rCandidate : maGradientProps.maGradientStops)
463 const ::Color aColor(rCandidate.second.getColor(rGraphicHelper, nPhClr));
464 aColorStops.emplace_back(rCandidate.first, aColor.getBColor());
465 bContainsTransparency = bContainsTransparency || rCandidate.second.hasTransparency();
468 // if we have transparency, convert to BColorStops
469 if (bContainsTransparency)
471 for (const auto& rCandidate : maGradientProps.maGradientStops)
473 const double fTrans(rCandidate.second.getTransparency() * (1.0/100.0));
474 aTransparencyStops.emplace_back(rCandidate.first, basegfx::BColor(fTrans, fTrans, fTrans));
478 // prepare BGradient with some defaults
479 // CAUTION: This used awt::Gradient2 before who's empty constructor
480 // (see workdir/UnoApiHeadersTarget/offapi/normal/com/sun/
481 // star/awt/Gradient.hpp) initializes all to zeros, so reflect
482 // this here. OTOH set all that were set, e.g. Start/EndIntens
483 // were set to 100, so just use default of BGradient constructor
484 basegfx::BGradient aGradient(
485 aColorStops,
486 awt::GradientStyle_LINEAR,
487 Degree10(900),
488 0, // border
489 0, // OfsX -> 0, not 50 (!)
490 0); // OfsY -> 0, not 50 (!)
492 // "rotate with shape" set to false -> do not rotate
493 if (!maGradientProps.moRotateWithShape.value_or(true))
495 nShapeRotation = 0;
498 if (maGradientProps.moGradientPath.has_value())
500 IntegerRectangle2D aFillToRect = maGradientProps.moFillToRect.value_or( IntegerRectangle2D( 0, 0, MAX_PERCENT, MAX_PERCENT ) );
501 sal_Int32 nCenterX = (MAX_PERCENT + aFillToRect.X1 - aFillToRect.X2) / 2;
502 aGradient.SetXOffset(getLimitedValue<sal_Int16, sal_Int32>(
503 nCenterX / PER_PERCENT, 0, 100));
504 sal_Int32 nCenterY = (MAX_PERCENT + aFillToRect.Y1 - aFillToRect.Y2) / 2;
505 aGradient.SetYOffset(getLimitedValue<sal_Int16, sal_Int32>(
506 nCenterY / PER_PERCENT, 0, 100));
508 if( maGradientProps.moGradientPath.value() == XML_circle )
510 // Style should be radial at least when the horizontal center is at 50%.
511 // Otherwise import as a linear gradient, because it is the most similar to the MSO radial style.
512 // aGradient.SetGradientStyle(awt::GradientStyle_LINEAR);
513 if( 100 == aGradient.GetXOffset() && 100 == aGradient.GetYOffset() )
514 aGradient.SetAngle( Degree10(450) );
515 else if( 0 == aGradient.GetXOffset() && 100 == aGradient.GetYOffset() )
516 aGradient.SetAngle( Degree10(3150) );
517 else if( 100 == aGradient.GetXOffset() && 0 == aGradient.GetYOffset() )
518 aGradient.SetAngle( Degree10(1350) );
519 else if( 0 == aGradient.GetXOffset() && 0 == aGradient.GetYOffset() )
520 aGradient.SetAngle( Degree10(2250) );
521 else
522 aGradient.SetGradientStyle(awt::GradientStyle_RADIAL);
524 else
526 aGradient.SetGradientStyle(awt::GradientStyle_RECT);
529 aColorStops.reverseColorStops();
530 aGradient.SetColorStops(aColorStops);
531 aTransparencyStops.reverseColorStops();
533 else if (!maGradientProps.maGradientStops.empty())
535 // aGradient.SetGradientStyle(awt::GradientStyle_LINEAR);
536 sal_Int32 nShadeAngle(maGradientProps.moShadeAngle.value_or( 0 ));
537 // Adjust for flips
538 if ( bFlipH )
539 nShadeAngle = 180*60000 - nShadeAngle;
540 if ( bFlipV )
541 nShadeAngle = -nShadeAngle;
542 const sal_Int32 nDmlAngle = nShadeAngle + nShapeRotation;
544 // convert DrawingML angle (in 1/60000 degrees) to API angle (in 1/10 degrees)
545 aGradient.SetAngle(Degree10(static_cast< sal_Int16 >( (8100 - (nDmlAngle / (PER_DEGREE / 10))) % 3600 )));
547 // If this is symmetrical, set it as an axial gradient for better UI/export.
548 // There were chart2 unit test failures when doing this to transparent gradients
549 // so just avoid that case.
550 if (!bContainsTransparency)
551 aGradient.tryToConvertToAxial();
554 if (awt::GradientStyle_RECT == aGradient.GetGradientStyle())
556 // MCGR: tdf#155362: better support border
557 // CAUTION: Need to handle TransparencyStops if used
558 aGradient.tryToRecreateBorder(aTransparencyStops.empty() ? nullptr : &aTransparencyStops);
561 // push gradient or named gradient to property map
562 if (rPropMap.setProperty(ShapeProperty::FillGradient, model::gradient::createUnoGradient2(aGradient)))
564 eFillStyle = FillStyle_GRADIENT;
567 // push gradient transparency to property map if it exists
568 if (!aTransparencyStops.empty())
570 aGradient.SetColorStops(aTransparencyStops);
571 rPropMap.setProperty(ShapeProperty::GradientTransparency, model::gradient::createUnoGradient2(aGradient));
574 break;
576 case XML_blipFill:
577 // do not start complex graphic transformation if property is not supported...
578 if (maBlipProps.mxFillGraphic.is() && rPropMap.supportsProperty(ShapeProperty::FillBitmap))
580 uno::Reference<graphic::XGraphic> xGraphic = lclCheckAndApplyDuotoneTransform(maBlipProps, maBlipProps.mxFillGraphic, rGraphicHelper, nPhClr);
581 // TODO: "rotate with shape" is not possible with our current core
583 if (xGraphic.is())
585 if (maBlipProps.moColorEffect.value_or(XML_TOKEN_INVALID) == XML_grayscl)
586 xGraphic = lclGreysScaleGraphic(xGraphic);
588 if (rPropMap.supportsProperty(ShapeProperty::FillBitmapName) &&
589 rPropMap.setProperty(ShapeProperty::FillBitmapName, xGraphic))
591 eFillStyle = FillStyle_BITMAP;
593 else if (rPropMap.setProperty(ShapeProperty::FillBitmap, xGraphic))
595 eFillStyle = FillStyle_BITMAP;
599 // set other bitmap properties, if bitmap has been inserted into the map
600 if( eFillStyle == FillStyle_BITMAP )
602 // bitmap mode (single, repeat, stretch)
603 BitmapMode eBitmapMode = lclGetBitmapMode( maBlipProps.moBitmapMode.value_or( XML_TOKEN_INVALID ) );
605 // additional settings for repeated bitmap
606 if( eBitmapMode == BitmapMode_REPEAT )
608 // anchor position inside bitmap
609 RectanglePoint eRectPoint = lclGetRectanglePoint( maBlipProps.moTileAlign.value_or( XML_tl ) );
610 rPropMap.setProperty( ShapeProperty::FillBitmapRectanglePoint, eRectPoint );
612 awt::Size aOriginalSize = lclGetOriginalSize(rGraphicHelper, maBlipProps.mxFillGraphic);
613 if( (aOriginalSize.Width > 0) && (aOriginalSize.Height > 0) )
615 // size of one bitmap tile (given as 1/1000 percent of bitmap size), convert to 1/100 mm
616 double fScaleX = maBlipProps.moTileScaleX.value_or( MAX_PERCENT ) / static_cast< double >( MAX_PERCENT );
617 sal_Int32 nFillBmpSizeX = getLimitedValue< sal_Int32, double >( aOriginalSize.Width * fScaleX, 1, SAL_MAX_INT32 );
618 rPropMap.setProperty( ShapeProperty::FillBitmapSizeX, nFillBmpSizeX );
619 double fScaleY = maBlipProps.moTileScaleY.value_or( MAX_PERCENT ) / static_cast< double >( MAX_PERCENT );
620 sal_Int32 nFillBmpSizeY = getLimitedValue< sal_Int32, double >( aOriginalSize.Height * fScaleY, 1, SAL_MAX_INT32 );
621 rPropMap.setProperty( ShapeProperty::FillBitmapSizeY, nFillBmpSizeY );
623 awt::Size aBmpSize(nFillBmpSizeX, nFillBmpSizeY);
624 // offset of the first bitmap tile (given as EMUs), convert to percent
625 sal_Int16 nTileOffsetX = getDoubleIntervalValue< sal_Int16 >(std::round(maBlipProps.moTileOffsetX.value_or( 0 ) / 3.6 / aBmpSize.Width), 0, 100 );
626 rPropMap.setProperty( ShapeProperty::FillBitmapOffsetX, nTileOffsetX );
627 sal_Int16 nTileOffsetY = getDoubleIntervalValue< sal_Int16 >(std::round(maBlipProps.moTileOffsetY.value_or( 0 ) / 3.6 / aBmpSize.Height), 0, 100 );
628 rPropMap.setProperty( ShapeProperty::FillBitmapOffsetY, nTileOffsetY );
631 else if ( eBitmapMode == BitmapMode_STRETCH && maBlipProps.moFillRect.has_value() )
633 geometry::IntegerRectangle2D aFillRect( maBlipProps.moFillRect.value() );
634 awt::Size aOriginalSize( rGraphicHelper.getOriginalSize( xGraphic ) );
635 if ( aOriginalSize.Width && aOriginalSize.Height )
637 text::GraphicCrop aGraphCrop( 0, 0, 0, 0 );
638 if ( aFillRect.X1 )
639 aGraphCrop.Left = o3tl::convert(aFillRect.X1, aOriginalSize.Width, MAX_PERCENT);
640 if ( aFillRect.Y1 )
641 aGraphCrop.Top = o3tl::convert(aFillRect.Y1, aOriginalSize.Height, MAX_PERCENT);
642 if ( aFillRect.X2 )
643 aGraphCrop.Right = o3tl::convert(aFillRect.X2, aOriginalSize.Width, MAX_PERCENT);
644 if ( aFillRect.Y2 )
645 aGraphCrop.Bottom = o3tl::convert(aFillRect.Y2, aOriginalSize.Height, MAX_PERCENT);
647 bool bHasCropValues = aGraphCrop.Left != 0 || aGraphCrop.Right !=0 || aGraphCrop.Top != 0 || aGraphCrop.Bottom != 0;
648 // Negative GraphicCrop values means "crop" here.
649 bool bNeedCrop = aGraphCrop.Left <= 0 && aGraphCrop.Right <= 0 && aGraphCrop.Top <= 0 && aGraphCrop.Bottom <= 0;
651 if (bHasCropValues)
653 if (bIsCustomShape && bNeedCrop)
655 // Physically crop the image
656 // In this case, don't set the PROP_GraphicCrop because that
657 // would lead to applying the crop twice after roundtrip
658 xGraphic = lclCropGraphic(xGraphic, CropQuotientsFromFillRect(aFillRect));
659 if (rPropMap.supportsProperty(ShapeProperty::FillBitmapName))
660 rPropMap.setProperty(ShapeProperty::FillBitmapName, xGraphic);
661 else
662 rPropMap.setProperty(ShapeProperty::FillBitmap, xGraphic);
664 else if ((aFillRect.X1 != 0 && aFillRect.X2 != 0
665 && aFillRect.X1 != aFillRect.X2)
666 || (aFillRect.Y1 != 0 && aFillRect.Y2 != 0
667 && aFillRect.Y1 != aFillRect.Y2))
669 rPropMap.setProperty(PROP_GraphicCrop, aGraphCrop);
671 else
673 double nL = aFillRect.X1 / static_cast<double>(MAX_PERCENT);
674 double nT = aFillRect.Y1 / static_cast<double>(MAX_PERCENT);
675 double nR = aFillRect.X2 / static_cast<double>(MAX_PERCENT);
676 double nB = aFillRect.Y2 / static_cast<double>(MAX_PERCENT);
678 sal_Int32 nSizeX;
679 if (nL || nR)
680 nSizeX = rSize.Width * (1 - (nL + nR));
681 else
682 nSizeX = rSize.Width;
683 rPropMap.setProperty(ShapeProperty::FillBitmapSizeX, nSizeX);
685 sal_Int32 nSizeY;
686 if (nT || nB)
687 nSizeY = rSize.Height * (1 - (nT + nB));
688 else
689 nSizeY = rSize.Height;
690 rPropMap.setProperty(ShapeProperty::FillBitmapSizeY, nSizeY);
692 RectanglePoint eRectPoint;
693 if (!aFillRect.X1 && aFillRect.X2)
695 if (!aFillRect.Y1 && aFillRect.Y2)
696 eRectPoint = lclGetRectanglePoint(XML_tl);
697 else if (aFillRect.Y1 && !aFillRect.Y2)
698 eRectPoint = lclGetRectanglePoint(XML_bl);
699 else
700 eRectPoint = lclGetRectanglePoint(XML_l);
702 else if (aFillRect.X1 && !aFillRect.X2)
704 if (!aFillRect.Y1 && aFillRect.Y2)
705 eRectPoint = lclGetRectanglePoint(XML_tr);
706 else if (aFillRect.Y1 && !aFillRect.Y2)
707 eRectPoint = lclGetRectanglePoint(XML_br);
708 else
709 eRectPoint = lclGetRectanglePoint(XML_r);
711 else
713 if (!aFillRect.Y1 && aFillRect.Y2)
714 eRectPoint = lclGetRectanglePoint(XML_t);
715 else if (aFillRect.Y1 && !aFillRect.Y2)
716 eRectPoint = lclGetRectanglePoint(XML_b);
717 else
718 eRectPoint = lclGetRectanglePoint(XML_ctr);
720 rPropMap.setProperty(ShapeProperty::FillBitmapRectanglePoint, eRectPoint);
721 eBitmapMode = BitmapMode_NO_REPEAT;
726 rPropMap.setProperty(ShapeProperty::FillBitmapMode, eBitmapMode);
729 if (maBlipProps.moAlphaModFix.has_value())
730 rPropMap.setProperty(ShapeProperty::FillTransparency, static_cast<sal_Int16>(100 - (maBlipProps.moAlphaModFix.value() / PER_PERCENT)));
732 break;
734 case XML_pattFill:
736 if( rPropMap.supportsProperty( ShapeProperty::FillHatch ) )
738 Color aColor( maPatternProps.maPattFgColor );
739 if( aColor.isUsed() && maPatternProps.moPattPreset.has_value() )
741 eFillStyle = FillStyle_HATCH;
742 rPropMap.setProperty( ShapeProperty::FillHatch, createHatch( maPatternProps.moPattPreset.value(), aColor.getColor( rGraphicHelper, nPhClr ) ) );
743 if( aColor.hasTransparency() )
744 rPropMap.setProperty( ShapeProperty::FillTransparency, aColor.getTransparency() );
746 // Set background color for hatch
747 if(maPatternProps.maPattBgColor.isUsed())
749 aColor = maPatternProps.maPattBgColor;
750 rPropMap.setProperty( ShapeProperty::FillBackground, aColor.getTransparency() != 100 );
751 rPropMap.setProperty( ShapeProperty::FillColor, aColor.getColor( rGraphicHelper, nPhClr ) );
754 else if ( maPatternProps.maPattBgColor.isUsed() )
756 aColor = maPatternProps.maPattBgColor;
757 rPropMap.setProperty( ShapeProperty::FillColor, aColor.getColor( rGraphicHelper, nPhClr ) );
758 if( aColor.hasTransparency() )
759 rPropMap.setProperty( ShapeProperty::FillTransparency, aColor.getTransparency() );
760 eFillStyle = FillStyle_SOLID;
764 break;
766 case XML_grpFill:
767 // todo
768 eFillStyle = FillStyle_NONE;
769 break;
772 // set final fill style property
773 rPropMap.setProperty( ShapeProperty::FillStyle, eFillStyle );
776 void GraphicProperties::pushToPropMap( PropertyMap& rPropMap, const GraphicHelper& rGraphicHelper, bool bFlipH, bool bFlipV) const
778 sal_Int16 nBrightness = getLimitedValue< sal_Int16, sal_Int32 >( maBlipProps.moBrightness.value_or( 0 ) / PER_PERCENT, -100, 100 );
779 sal_Int16 nContrast = getLimitedValue< sal_Int16, sal_Int32 >( maBlipProps.moContrast.value_or( 0 ) / PER_PERCENT, -100, 100 );
780 ColorMode eColorMode = ColorMode_STANDARD;
782 switch( maBlipProps.moColorEffect.value_or( XML_TOKEN_INVALID ) )
784 case XML_biLevel: eColorMode = ColorMode_MONO; break;
785 case XML_grayscl: eColorMode = ColorMode_GREYS; break;
788 if (maBlipProps.mxFillGraphic.is())
790 // created transformed graphic
791 uno::Reference<graphic::XGraphic> xGraphic = lclCheckAndApplyChangeColorTransform(maBlipProps, maBlipProps.mxFillGraphic, rGraphicHelper, API_RGB_TRANSPARENT);
792 xGraphic = lclCheckAndApplyDuotoneTransform(maBlipProps, xGraphic, rGraphicHelper, API_RGB_TRANSPARENT);
794 if( eColorMode == ColorMode_MONO )
796 // ColorMode_MONO is the same with MSO's biLevel with 50000 (50%) threshold,
797 // when threshold isn't 50000 bake the effect instead.
798 if( maBlipProps.moBiLevelThreshold != 50000 )
800 xGraphic = lclApplyBlackWhiteEffect(maBlipProps, xGraphic);
801 eColorMode = ColorMode_STANDARD;
805 if (eColorMode == ColorMode_STANDARD && nBrightness == 70 && nContrast == -70)
807 // map MSO 'washout' to our Watermark colormode
808 eColorMode = ColorMode_WATERMARK;
809 nBrightness = 0;
810 nContrast = 0;
812 else if( nBrightness != 0 && nContrast != 0 )
814 // MSO uses a different algorithm for contrast+brightness, LO applies contrast before brightness,
815 // while MSO apparently applies half of brightness before contrast and half after. So if only
816 // contrast or brightness need to be altered, the result is the same, but if both are involved,
817 // there's no way to map that, so just force a conversion of the image.
818 xGraphic = applyBrightnessContrast( xGraphic, nBrightness, nContrast );
819 nBrightness = 0;
820 nContrast = 0;
823 // cropping
824 if ( maBlipProps.moClipRect.has_value() )
826 geometry::IntegerRectangle2D oClipRect( maBlipProps.moClipRect.value() );
827 awt::Size aOriginalSize( rGraphicHelper.getOriginalSize( xGraphic ) );
828 if ( aOriginalSize.Width && aOriginalSize.Height )
830 text::GraphicCrop aGraphCrop( 0, 0, 0, 0 );
831 if ( oClipRect.X1 )
832 aGraphCrop.Left = o3tl::convert(oClipRect.X1, aOriginalSize.Width, MAX_PERCENT);
833 if ( oClipRect.Y1 )
834 aGraphCrop.Top = o3tl::convert(oClipRect.Y1, aOriginalSize.Height, MAX_PERCENT);
835 if ( oClipRect.X2 )
836 aGraphCrop.Right = o3tl::convert(oClipRect.X2, aOriginalSize.Width, MAX_PERCENT);
837 if ( oClipRect.Y2 )
838 aGraphCrop.Bottom = o3tl::convert(oClipRect.Y2, aOriginalSize.Height, MAX_PERCENT);
839 rPropMap.setProperty(PROP_GraphicCrop, aGraphCrop);
841 if(mbIsCustomShape)
843 // Positive GraphicCrop values means "crop" here.
844 if (aGraphCrop.Left > 0 || aGraphCrop.Right > 0 || aGraphCrop.Top > 0 || aGraphCrop.Bottom > 0)
845 xGraphic = lclCropGraphic(xGraphic, CropQuotientsFromSrcRect(oClipRect));
850 if(mbIsCustomShape)
852 // it is a cropped graphic.
853 rPropMap.setProperty(PROP_FillStyle, FillStyle_BITMAP);
854 rPropMap.setProperty(PROP_FillBitmapMode, BitmapMode_STRETCH);
856 // It is a bitmap filled and rotated graphic.
857 // When custom shape is rotated, bitmap have to be rotated too.
858 // Only in extruded mode the bitmap is transformed together with the shape
859 if(rPropMap.hasProperty(PROP_RotateAngle) && !mbIsExtruded)
861 tools::Long nAngle = rPropMap.getProperty(PROP_RotateAngle).get<tools::Long>();
862 xGraphic = lclRotateGraphic(xGraphic, Degree10(nAngle/10) );
865 // We have not core feature that flips graphic in the shape.
866 // Here we are applying flip property to bitmap directly.
867 if((bFlipH || bFlipV) && !mbIsExtruded)
868 xGraphic = lclMirrorGraphic(xGraphic, bFlipH, bFlipV );
870 if(eColorMode == ColorMode_GREYS)
871 xGraphic = lclGreysScaleGraphic( xGraphic );
873 rPropMap.setProperty(PROP_FillBitmap, xGraphic);
875 else
876 rPropMap.setProperty(PROP_Graphic, xGraphic);
879 if ( maBlipProps.moAlphaModFix.has_value() )
881 rPropMap.setProperty(
882 mbIsCustomShape ? PROP_FillTransparence : PROP_Transparency,
883 static_cast<sal_Int16>(100 - (maBlipProps.moAlphaModFix.value() / PER_PERCENT)));
886 rPropMap.setProperty(PROP_GraphicColorMode, eColorMode);
888 // brightness and contrast
889 if( nBrightness != 0 )
890 rPropMap.setProperty(PROP_AdjustLuminance, nBrightness);
891 if( nContrast != 0 )
892 rPropMap.setProperty(PROP_AdjustContrast, nContrast);
894 // Media content
895 if (!m_sMediaPackageURL.isEmpty())
897 rPropMap.setProperty(PROP_MediaURL, m_sMediaPackageURL);
898 if (m_xMediaStream.is())
899 rPropMap.setProperty(PROP_PrivateStream, m_xMediaStream);
903 bool ArtisticEffectProperties::isEmpty() const
905 return msName.isEmpty();
908 css::beans::PropertyValue ArtisticEffectProperties::getEffect()
910 css::beans::PropertyValue aRet;
911 if( msName.isEmpty() )
912 return aRet;
914 css::uno::Sequence< css::beans::PropertyValue > aSeq( maAttribs.size() + 1 );
915 auto pSeq = aSeq.getArray();
916 sal_uInt32 i = 0;
917 for (auto const& attrib : maAttribs)
919 pSeq[i].Name = attrib.first;
920 pSeq[i].Value = attrib.second;
921 i++;
924 if( mrOleObjectInfo.maEmbeddedData.hasElements() )
926 css::uno::Sequence< css::beans::PropertyValue > aGraphicSeq{
927 comphelper::makePropertyValue(u"Id"_ustr, mrOleObjectInfo.maProgId),
928 comphelper::makePropertyValue(u"Data"_ustr, mrOleObjectInfo.maEmbeddedData)
931 pSeq[i].Name = "OriginalGraphic";
932 pSeq[i].Value <<= aGraphicSeq;
935 aRet.Name = msName;
936 aRet.Value <<= aSeq;
938 return aRet;
941 void ArtisticEffectProperties::assignUsed( const ArtisticEffectProperties& rSourceProps )
943 if( !rSourceProps.isEmpty() )
945 msName = rSourceProps.msName;
946 maAttribs = rSourceProps.maAttribs;
950 OUString ArtisticEffectProperties::getEffectString( sal_Int32 nToken )
952 switch( nToken )
954 // effects
955 case OOX_TOKEN( a14, artisticBlur ): return u"artisticBlur"_ustr;
956 case OOX_TOKEN( a14, artisticCement ): return u"artisticCement"_ustr;
957 case OOX_TOKEN( a14, artisticChalkSketch ): return u"artisticChalkSketch"_ustr;
958 case OOX_TOKEN( a14, artisticCrisscrossEtching ): return u"artisticCrisscrossEtching"_ustr;
959 case OOX_TOKEN( a14, artisticCutout ): return u"artisticCutout"_ustr;
960 case OOX_TOKEN( a14, artisticFilmGrain ): return u"artisticFilmGrain"_ustr;
961 case OOX_TOKEN( a14, artisticGlass ): return u"artisticGlass"_ustr;
962 case OOX_TOKEN( a14, artisticGlowDiffused ): return u"artisticGlowDiffused"_ustr;
963 case OOX_TOKEN( a14, artisticGlowEdges ): return u"artisticGlowEdges"_ustr;
964 case OOX_TOKEN( a14, artisticLightScreen ): return u"artisticLightScreen"_ustr;
965 case OOX_TOKEN( a14, artisticLineDrawing ): return u"artisticLineDrawing"_ustr;
966 case OOX_TOKEN( a14, artisticMarker ): return u"artisticMarker"_ustr;
967 case OOX_TOKEN( a14, artisticMosiaicBubbles ): return u"artisticMosiaicBubbles"_ustr;
968 case OOX_TOKEN( a14, artisticPaintStrokes ): return u"artisticPaintStrokes"_ustr;
969 case OOX_TOKEN( a14, artisticPaintBrush ): return u"artisticPaintBrush"_ustr;
970 case OOX_TOKEN( a14, artisticPastelsSmooth ): return u"artisticPastelsSmooth"_ustr;
971 case OOX_TOKEN( a14, artisticPencilGrayscale ): return u"artisticPencilGrayscale"_ustr;
972 case OOX_TOKEN( a14, artisticPencilSketch ): return u"artisticPencilSketch"_ustr;
973 case OOX_TOKEN( a14, artisticPhotocopy ): return u"artisticPhotocopy"_ustr;
974 case OOX_TOKEN( a14, artisticPlasticWrap ): return u"artisticPlasticWrap"_ustr;
975 case OOX_TOKEN( a14, artisticTexturizer ): return u"artisticTexturizer"_ustr;
976 case OOX_TOKEN( a14, artisticWatercolorSponge ): return u"artisticWatercolorSponge"_ustr;
977 case OOX_TOKEN( a14, brightnessContrast ): return u"brightnessContrast"_ustr;
978 case OOX_TOKEN( a14, colorTemperature ): return u"colorTemperature"_ustr;
979 case OOX_TOKEN( a14, saturation ): return u"saturation"_ustr;
980 case OOX_TOKEN( a14, sharpenSoften ): return u"sharpenSoften"_ustr;
982 // attributes
983 case XML_visible: return u"visible"_ustr;
984 case XML_trans: return u"trans"_ustr;
985 case XML_crackSpacing: return u"crackSpacing"_ustr;
986 case XML_pressure: return u"pressure"_ustr;
987 case XML_numberOfShades: return u"numberOfShades"_ustr;
988 case XML_grainSize: return u"grainSize"_ustr;
989 case XML_intensity: return u"intensity"_ustr;
990 case XML_smoothness: return u"smoothness"_ustr;
991 case XML_gridSize: return u"gridSize"_ustr;
992 case XML_pencilSize: return u"pencilSize"_ustr;
993 case XML_size: return u"size"_ustr;
994 case XML_brushSize: return u"brushSize"_ustr;
995 case XML_scaling: return u"scaling"_ustr;
996 case XML_detail: return u"detail"_ustr;
997 case XML_bright: return u"bright"_ustr;
998 case XML_contrast: return u"contrast"_ustr;
999 case XML_colorTemp: return u"colorTemp"_ustr;
1000 case XML_sat: return u"sat"_ustr;
1001 case XML_amount: return u"amount"_ustr;
1003 SAL_WARN( "oox.drawingml", "ArtisticEffectProperties::getEffectString: unexpected token " << nToken );
1004 return OUString();
1007 constexpr auto constEffectTokenForEffectNameMap = frozen::make_unordered_map<std::u16string_view, sal_Int32>(
1009 // effects
1010 { u"artisticBlur", XML_artisticBlur },
1011 { u"artisticCement", XML_artisticCement },
1012 { u"artisticChalkSketch", XML_artisticChalkSketch },
1013 { u"artisticCrisscrossEtching", XML_artisticCrisscrossEtching },
1014 { u"artisticCutout", XML_artisticCutout },
1015 { u"artisticFilmGrain", XML_artisticFilmGrain },
1016 { u"artisticGlass", XML_artisticGlass },
1017 { u"artisticGlowDiffused", XML_artisticGlowDiffused },
1018 { u"artisticGlowEdges", XML_artisticGlowEdges },
1019 { u"artisticLightScreen", XML_artisticLightScreen },
1020 { u"artisticLineDrawing", XML_artisticLineDrawing },
1021 { u"artisticMarker", XML_artisticMarker },
1022 { u"artisticMosiaicBubbles", XML_artisticMosiaicBubbles },
1023 { u"artisticPaintStrokes", XML_artisticPaintStrokes },
1024 { u"artisticPaintBrush", XML_artisticPaintBrush },
1025 { u"artisticPastelsSmooth", XML_artisticPastelsSmooth },
1026 { u"artisticPencilGrayscale", XML_artisticPencilGrayscale },
1027 { u"artisticPencilSketch", XML_artisticPencilSketch },
1028 { u"artisticPhotocopy", XML_artisticPhotocopy },
1029 { u"artisticPlasticWrap", XML_artisticPlasticWrap },
1030 { u"artisticTexturizer", XML_artisticTexturizer },
1031 { u"artisticWatercolorSponge", XML_artisticWatercolorSponge },
1032 { u"brightnessContrast", XML_brightnessContrast },
1033 { u"colorTemperature", XML_colorTemperature },
1034 { u"saturation", XML_saturation },
1035 { u"sharpenSoften", XML_sharpenSoften },
1037 // attributes
1038 { u"visible", XML_visible },
1039 { u"trans", XML_trans },
1040 { u"crackSpacing", XML_crackSpacing },
1041 { u"pressure", XML_pressure },
1042 { u"numberOfShades", XML_numberOfShades },
1043 { u"grainSize", XML_grainSize },
1044 { u"intensity", XML_intensity },
1045 { u"smoothness", XML_smoothness },
1046 { u"gridSize", XML_gridSize },
1047 { u"pencilSize", XML_pencilSize },
1048 { u"size", XML_size },
1049 { u"brushSize", XML_brushSize },
1050 { u"scaling", XML_scaling },
1051 { u"detail", XML_detail },
1052 { u"bright", XML_bright },
1053 { u"contrast", XML_contrast },
1054 { u"colorTemp", XML_colorTemp },
1055 { u"sat", XML_sat },
1056 { u"amount", XML_amount }
1059 sal_Int32 ArtisticEffectProperties::getEffectToken(const OUString& sName)
1061 auto const aIterator = constEffectTokenForEffectNameMap.find(sName);
1063 if (aIterator != constEffectTokenForEffectNameMap.end())
1064 return aIterator->second;
1066 SAL_WARN( "oox.drawingml", "ArtisticEffectProperties::getEffectToken - unexpected token name: " << sName );
1067 return XML_none;
1070 } // namespace oox
1072 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */