fdo#74697 Add Bluez 5 support for impress remote.
[LibreOffice.git] / oox / source / drawingml / fillproperties.cxx
blob389ef8a4e2632ccec227f37d1a50d11a7dce4760
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 "oox/drawingml/fillproperties.hxx"
22 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
23 #include <com/sun/star/beans/XPropertySet.hpp>
24 #include <com/sun/star/awt/Gradient.hpp>
25 #include <com/sun/star/text/GraphicCrop.hpp>
26 #include <com/sun/star/awt/Size.hpp>
27 #include <com/sun/star/drawing/BitmapMode.hpp>
28 #include <com/sun/star/drawing/ColorMode.hpp>
29 #include <com/sun/star/drawing/FillStyle.hpp>
30 #include <com/sun/star/drawing/Hatch.hpp>
31 #include <com/sun/star/drawing/RectanglePoint.hpp>
32 #include <com/sun/star/graphic/XGraphicTransformer.hpp>
33 #include "oox/helper/graphichelper.hxx"
34 #include "oox/drawingml/drawingmltypes.hxx"
35 #include "oox/drawingml/shapepropertymap.hxx"
36 #include "oox/token/tokens.hxx"
38 using namespace ::com::sun::star;
39 using namespace ::com::sun::star::drawing;
40 using namespace ::com::sun::star::graphic;
42 using ::com::sun::star::uno::Reference;
43 using ::com::sun::star::uno::Exception;
44 using ::com::sun::star::uno::UNO_QUERY;
45 using ::com::sun::star::uno::UNO_QUERY_THROW;
46 using ::com::sun::star::geometry::IntegerRectangle2D;
48 namespace oox {
49 namespace drawingml {
51 // ============================================================================
53 namespace {
55 BitmapMode lclGetBitmapMode( sal_Int32 nToken )
57 OSL_ASSERT((nToken & sal_Int32(0xFFFF0000))==0);
58 switch( nToken )
60 case XML_tile: return BitmapMode_REPEAT;
61 case XML_stretch: return BitmapMode_STRETCH;
63 return BitmapMode_NO_REPEAT;
66 RectanglePoint lclGetRectanglePoint( sal_Int32 nToken )
68 OSL_ASSERT((nToken & sal_Int32(0xFFFF0000))==0);
69 switch( nToken )
71 case XML_tl: return RectanglePoint_LEFT_TOP;
72 case XML_t: return RectanglePoint_MIDDLE_TOP;
73 case XML_tr: return RectanglePoint_RIGHT_TOP;
74 case XML_l: return RectanglePoint_LEFT_MIDDLE;
75 case XML_ctr: return RectanglePoint_MIDDLE_MIDDLE;
76 case XML_r: return RectanglePoint_RIGHT_MIDDLE;
77 case XML_bl: return RectanglePoint_LEFT_BOTTOM;
78 case XML_b: return RectanglePoint_MIDDLE_BOTTOM;
79 case XML_br: return RectanglePoint_RIGHT_BOTTOM;
81 return RectanglePoint_LEFT_TOP;
84 const awt::Size lclGetOriginalSize( const GraphicHelper& rGraphicHelper, const Reference< XGraphic >& rxGraphic )
86 awt::Size aSizeHmm( 0, 0 );
87 try
89 Reference< beans::XPropertySet > xGraphicPropertySet( rxGraphic, UNO_QUERY_THROW );
90 if( xGraphicPropertySet->getPropertyValue( "Size100thMM" ) >>= aSizeHmm )
92 if( !aSizeHmm.Width && !aSizeHmm.Height )
93 { // MAPMODE_PIXEL USED :-(
94 awt::Size aSourceSizePixel( 0, 0 );
95 if( xGraphicPropertySet->getPropertyValue( "SizePixel" ) >>= aSourceSizePixel )
96 aSizeHmm = rGraphicHelper.convertScreenPixelToHmm( aSourceSizePixel );
100 catch( Exception& )
103 return aSizeHmm;
106 } // namespace
108 // ============================================================================
110 void GradientFillProperties::assignUsed( const GradientFillProperties& rSourceProps )
112 if( !rSourceProps.maGradientStops.empty() )
113 maGradientStops = rSourceProps.maGradientStops;
114 moFillToRect.assignIfUsed( rSourceProps.moFillToRect );
115 moTileRect.assignIfUsed( rSourceProps.moTileRect );
116 moGradientPath.assignIfUsed( rSourceProps.moGradientPath );
117 moShadeAngle.assignIfUsed( rSourceProps.moShadeAngle );
118 moShadeFlip.assignIfUsed( rSourceProps.moShadeFlip );
119 moShadeScaled.assignIfUsed( rSourceProps.moShadeScaled );
120 moRotateWithShape.assignIfUsed( rSourceProps.moRotateWithShape );
123 // ============================================================================
125 void PatternFillProperties::assignUsed( const PatternFillProperties& rSourceProps )
127 maPattFgColor.assignIfUsed( rSourceProps.maPattFgColor );
128 maPattBgColor.assignIfUsed( rSourceProps.maPattBgColor );
129 moPattPreset.assignIfUsed( rSourceProps.moPattPreset );
132 // ============================================================================
134 void BlipFillProperties::assignUsed( const BlipFillProperties& rSourceProps )
136 if( rSourceProps.mxGraphic.is() )
137 mxGraphic = rSourceProps.mxGraphic;
138 moBitmapMode.assignIfUsed( rSourceProps.moBitmapMode );
139 moFillRect.assignIfUsed( rSourceProps.moFillRect );
140 moTileOffsetX.assignIfUsed( rSourceProps.moTileOffsetX );
141 moTileOffsetY.assignIfUsed( rSourceProps.moTileOffsetY );
142 moTileScaleX.assignIfUsed( rSourceProps.moTileScaleX );
143 moTileScaleY.assignIfUsed( rSourceProps.moTileScaleY );
144 moTileAlign.assignIfUsed( rSourceProps.moTileAlign );
145 moTileFlip.assignIfUsed( rSourceProps.moTileFlip );
146 moRotateWithShape.assignIfUsed( rSourceProps.moRotateWithShape );
147 moColorEffect.assignIfUsed( rSourceProps.moColorEffect );
148 moBrightness.assignIfUsed( rSourceProps.moBrightness );
149 moContrast.assignIfUsed( rSourceProps.moContrast );
150 maColorChangeFrom.assignIfUsed( rSourceProps.maColorChangeFrom );
151 maColorChangeTo.assignIfUsed( rSourceProps.maColorChangeTo );
154 // ============================================================================
156 void FillProperties::assignUsed( const FillProperties& rSourceProps )
158 moFillType.assignIfUsed( rSourceProps.moFillType );
159 maFillColor.assignIfUsed( rSourceProps.maFillColor );
160 maGradientProps.assignUsed( rSourceProps.maGradientProps );
161 maPatternProps.assignUsed( rSourceProps.maPatternProps );
162 maBlipProps.assignUsed( rSourceProps.maBlipProps );
165 Color FillProperties::getBestSolidColor() const
167 Color aSolidColor;
168 if( moFillType.has() ) switch( moFillType.get() )
170 case XML_solidFill:
171 aSolidColor = maFillColor;
172 break;
173 case XML_gradFill:
174 if( !maGradientProps.maGradientStops.empty() )
175 aSolidColor = maGradientProps.maGradientStops.begin()->second;
176 break;
177 case XML_pattFill:
178 aSolidColor = maPatternProps.maPattBgColor.isUsed() ? maPatternProps.maPattBgColor : maPatternProps.maPattFgColor;
179 break;
181 return aSolidColor;
184 /// Maps the hatch token to drawing::Hatch.
185 static drawing::Hatch createHatch( sal_Int32 nHatchToken, sal_Int32 nColor )
187 drawing::Hatch aHatch;
188 aHatch.Color = nColor;
190 // best-effort mapping; we do not support all the styles in core
191 switch ( nHatchToken )
193 case XML_pct5: aHatch.Style = drawing::HatchStyle_SINGLE; aHatch.Distance = 250; aHatch.Angle = 450; break;
194 case XML_pct10: aHatch.Style = drawing::HatchStyle_SINGLE; aHatch.Distance = 200; aHatch.Angle = 450; break;
195 case XML_pct20: aHatch.Style = drawing::HatchStyle_SINGLE; aHatch.Distance = 150; aHatch.Angle = 450; break;
196 case XML_pct25: aHatch.Style = drawing::HatchStyle_DOUBLE; aHatch.Distance = 200; aHatch.Angle = 450; break;
197 case XML_pct30: aHatch.Style = drawing::HatchStyle_DOUBLE; aHatch.Distance = 175; aHatch.Angle = 450; break;
198 case XML_pct40: aHatch.Style = drawing::HatchStyle_DOUBLE; aHatch.Distance = 150; aHatch.Angle = 450; break;
199 case XML_pct50: aHatch.Style = drawing::HatchStyle_DOUBLE; aHatch.Distance = 125; aHatch.Angle = 450; break;
200 case XML_pct60: aHatch.Style = drawing::HatchStyle_TRIPLE; aHatch.Distance = 150; aHatch.Angle = 450; break;
201 case XML_pct70: aHatch.Style = drawing::HatchStyle_TRIPLE; aHatch.Distance = 125; aHatch.Angle = 450; break;
202 case XML_pct75: aHatch.Style = drawing::HatchStyle_TRIPLE; aHatch.Distance = 100; aHatch.Angle = 450; break;
203 case XML_pct80: aHatch.Style = drawing::HatchStyle_TRIPLE; aHatch.Distance = 75; aHatch.Angle = 450; break;
204 case XML_pct90: aHatch.Style = drawing::HatchStyle_TRIPLE; aHatch.Distance = 50; aHatch.Angle = 450; break;
205 case XML_horz: aHatch.Style = drawing::HatchStyle_SINGLE; aHatch.Distance = 100; aHatch.Angle = 0; break;
206 case XML_vert: aHatch.Style = drawing::HatchStyle_SINGLE; aHatch.Distance = 100; aHatch.Angle = 900; break;
207 case XML_ltHorz: aHatch.Style = drawing::HatchStyle_SINGLE; aHatch.Distance = 150; aHatch.Angle = 0; break;
208 case XML_ltVert: aHatch.Style = drawing::HatchStyle_SINGLE; aHatch.Distance = 150; aHatch.Angle = 900; break;
209 case XML_dkHorz: aHatch.Style = drawing::HatchStyle_SINGLE; aHatch.Distance = 25; aHatch.Angle = 0; break;
210 case XML_dkVert: aHatch.Style = drawing::HatchStyle_SINGLE; aHatch.Distance = 25; aHatch.Angle = 900; break;
211 case XML_narHorz: aHatch.Style = drawing::HatchStyle_SINGLE; aHatch.Distance = 50; aHatch.Angle = 0; break;
212 case XML_narVert: aHatch.Style = drawing::HatchStyle_SINGLE; aHatch.Distance = 50; aHatch.Angle = 900; break;
213 case XML_dashHorz: aHatch.Style = drawing::HatchStyle_SINGLE; aHatch.Distance = 150; aHatch.Angle = 0; break;
214 case XML_dashVert: aHatch.Style = drawing::HatchStyle_SINGLE; aHatch.Distance = 150; aHatch.Angle = 900; break;
215 case XML_cross: aHatch.Style = drawing::HatchStyle_DOUBLE; aHatch.Distance = 100; aHatch.Angle = 0; break;
216 case XML_dnDiag: aHatch.Style = drawing::HatchStyle_SINGLE; aHatch.Distance = 100; aHatch.Angle = 1350; break;
217 case XML_upDiag: aHatch.Style = drawing::HatchStyle_SINGLE; aHatch.Distance = 100; aHatch.Angle = 450; break;
218 case XML_ltDnDiag: aHatch.Style = drawing::HatchStyle_SINGLE; aHatch.Distance = 150; aHatch.Angle = 1350; break;
219 case XML_ltUpDiag: aHatch.Style = drawing::HatchStyle_SINGLE; aHatch.Distance = 150; aHatch.Angle = 450; break;
220 case XML_dkDnDiag: aHatch.Style = drawing::HatchStyle_SINGLE; aHatch.Distance = 50; aHatch.Angle = 1350; break;
221 case XML_dkUpDiag: aHatch.Style = drawing::HatchStyle_SINGLE; aHatch.Distance = 50; aHatch.Angle = 450; break;
222 case XML_wdDnDiag: aHatch.Style = drawing::HatchStyle_SINGLE; aHatch.Distance = 200; aHatch.Angle = 1350; break;
223 case XML_wdUpDiag: aHatch.Style = drawing::HatchStyle_SINGLE; aHatch.Distance = 200; aHatch.Angle = 450; break;
224 case XML_dashDnDiag: aHatch.Style = drawing::HatchStyle_SINGLE; aHatch.Distance = 150; aHatch.Angle = 1350; break;
225 case XML_dashUpDiag: aHatch.Style = drawing::HatchStyle_SINGLE; aHatch.Distance = 150; aHatch.Angle = 450; break;
226 case XML_diagCross: aHatch.Style = drawing::HatchStyle_DOUBLE; aHatch.Distance = 100; aHatch.Angle = 450; break;
227 case XML_smCheck: aHatch.Style = drawing::HatchStyle_DOUBLE; aHatch.Distance = 50; aHatch.Angle = 450; break;
228 case XML_lgCheck: aHatch.Style = drawing::HatchStyle_DOUBLE; aHatch.Distance = 100; aHatch.Angle = 450; break;
229 case XML_smGrid: aHatch.Style = drawing::HatchStyle_DOUBLE; aHatch.Distance = 150; aHatch.Angle = 0; break;
230 case XML_lgGrid: aHatch.Style = drawing::HatchStyle_DOUBLE; aHatch.Distance = 250; aHatch.Angle = 0; break;
231 case XML_dotGrid: aHatch.Style = drawing::HatchStyle_DOUBLE; aHatch.Distance = 400; aHatch.Angle = 0; break;
232 case XML_smConfetti: aHatch.Style = drawing::HatchStyle_SINGLE; aHatch.Distance = 200; aHatch.Angle = 600; break;
233 case XML_lgConfetti: aHatch.Style = drawing::HatchStyle_SINGLE; aHatch.Distance = 100; aHatch.Angle = 600; break;
234 case XML_horzBrick: aHatch.Style = drawing::HatchStyle_DOUBLE; aHatch.Distance = 300; aHatch.Angle = 0; break;
235 case XML_diagBrick: aHatch.Style = drawing::HatchStyle_DOUBLE; aHatch.Distance = 300; aHatch.Angle = 450; break;
236 case XML_solidDmnd: aHatch.Style = drawing::HatchStyle_DOUBLE; aHatch.Distance = 150; aHatch.Angle = 450; break;
237 case XML_openDmnd: aHatch.Style = drawing::HatchStyle_DOUBLE; aHatch.Distance = 200; aHatch.Angle = 450; break;
238 case XML_dotDmnd: aHatch.Style = drawing::HatchStyle_DOUBLE; aHatch.Distance = 300; aHatch.Angle = 450; break;
239 case XML_plaid: aHatch.Style = drawing::HatchStyle_TRIPLE; aHatch.Distance = 200; aHatch.Angle = 900; break;
240 case XML_sphere: aHatch.Style = drawing::HatchStyle_TRIPLE; aHatch.Distance = 100; aHatch.Angle = 0; break;
241 case XML_weave: aHatch.Style = drawing::HatchStyle_DOUBLE; aHatch.Distance = 150; aHatch.Angle = 450; break;
242 case XML_divot: aHatch.Style = drawing::HatchStyle_TRIPLE; aHatch.Distance = 400; aHatch.Angle = 450; break;
243 case XML_shingle: aHatch.Style = drawing::HatchStyle_SINGLE; aHatch.Distance = 200; aHatch.Angle = 1350; break;
244 case XML_wave: aHatch.Style = drawing::HatchStyle_SINGLE; aHatch.Distance = 100; aHatch.Angle = 0; break;
245 case XML_trellis: aHatch.Style = drawing::HatchStyle_DOUBLE; aHatch.Distance = 75; aHatch.Angle = 450; break;
246 case XML_zigZag: aHatch.Style = drawing::HatchStyle_SINGLE; aHatch.Distance = 75; aHatch.Angle = 0; break;
249 return aHatch;
252 void FillProperties::pushToPropMap( ShapePropertyMap& rPropMap,
253 const GraphicHelper& rGraphicHelper, sal_Int32 nShapeRotation, sal_Int32 nPhClr,
254 bool bFlipH, bool bFlipV ) const
256 if( moFillType.has() )
258 FillStyle eFillStyle = FillStyle_NONE;
259 OSL_ASSERT((moFillType.get() & sal_Int32(0xFFFF0000))==0);
260 switch( moFillType.get() )
262 case XML_noFill:
263 eFillStyle = FillStyle_NONE;
264 break;
266 case XML_solidFill:
267 if( maFillColor.isUsed() )
269 rPropMap.setProperty( SHAPEPROP_FillColor, maFillColor.getColor( rGraphicHelper, nPhClr ) );
270 if( maFillColor.hasTransparency() )
271 rPropMap.setProperty( SHAPEPROP_FillTransparency, maFillColor.getTransparency() );
272 eFillStyle = FillStyle_SOLID;
274 break;
276 case XML_gradFill:
277 // do not create gradient struct if property is not supported...
278 if( rPropMap.supportsProperty( SHAPEPROP_FillGradient ) )
280 sal_Int32 nEndTrans = 0;
281 sal_Int32 nStartTrans = 0;
282 awt::Gradient aGradient;
283 aGradient.Angle = 900;
284 aGradient.StartIntensity = 100;
285 aGradient.EndIntensity = 100;
287 size_t nColorCount = maGradientProps.maGradientStops.size();
288 if( nColorCount > 1 )
290 aGradient.StartColor = maGradientProps.maGradientStops.begin()->second.getColor( rGraphicHelper, nPhClr );
291 aGradient.EndColor = maGradientProps.maGradientStops.rbegin()->second.getColor( rGraphicHelper, nPhClr );
292 if( maGradientProps.maGradientStops.rbegin()->second.hasTransparency() )
293 nEndTrans = maGradientProps.maGradientStops.rbegin()->second.getTransparency()*255/100;
294 if( maGradientProps.maGradientStops.begin()->second.hasTransparency() )
295 nStartTrans = maGradientProps.maGradientStops.begin()->second.getTransparency()*255/100;
298 // Adjust for flips
299 if ( bFlipH )
300 nShapeRotation = 180*60000 - nShapeRotation;
301 if ( bFlipV )
302 nShapeRotation = -nShapeRotation;
304 // "rotate with shape" not set, or set to false -> do not rotate
305 if ( !maGradientProps.moRotateWithShape.get( false ) )
306 nShapeRotation = 0;
308 sal_Int32 nDmlAngle = 0;
309 if( maGradientProps.moGradientPath.has() )
311 aGradient.Style = (maGradientProps.moGradientPath.get() == XML_circle) ? awt::GradientStyle_ELLIPTICAL : awt::GradientStyle_RECT;
312 // position of gradient center (limited to [30%;70%], otherwise gradient is too hidden)
313 IntegerRectangle2D aFillToRect = maGradientProps.moFillToRect.get( IntegerRectangle2D( 0, 0, MAX_PERCENT, MAX_PERCENT ) );
314 sal_Int32 nCenterX = (MAX_PERCENT + aFillToRect.X1 - aFillToRect.X2) / 2;
315 aGradient.XOffset = getLimitedValue< sal_Int16, sal_Int32 >( nCenterX / PER_PERCENT, 30, 70 );
316 sal_Int32 nCenterY = (MAX_PERCENT + aFillToRect.Y1 - aFillToRect.Y2) / 2;
317 aGradient.YOffset = getLimitedValue< sal_Int16, sal_Int32 >( nCenterY / PER_PERCENT, 30, 70 );
318 ::std::swap( aGradient.StartColor, aGradient.EndColor );
319 ::std::swap( nStartTrans, nEndTrans );
320 nDmlAngle = nShapeRotation;
322 else
324 /* Try to detect a VML axial gradient. This type of
325 gradient is simulated by a 3-point linear gradient.
326 Even if its a multi-color linear gradient, its probably better to assume
327 axial gradient, when there are 3 or more points.
329 bool bAxial = (nColorCount >= 3);
330 aGradient.Style = bAxial ? awt::GradientStyle_AXIAL : awt::GradientStyle_LINEAR;
331 nDmlAngle = maGradientProps.moShadeAngle.get( 0 ) - nShapeRotation;
332 // convert DrawingML angle (in 1/60000 degrees) to API angle (in 1/10 degrees)
333 aGradient.Angle = static_cast< sal_Int16 >( (4500 - (nDmlAngle / (PER_DEGREE / 10))) % 3600 );
334 if( bAxial )
336 GradientFillProperties::GradientStopMap::const_iterator aIt = maGradientProps.maGradientStops.begin();
337 // Try to find the axial median
338 for(size_t i=0;i<nColorCount;i+=3)
339 ++aIt;
340 // API StartColor is inner color in axial gradient
341 // aIt->second.hasColor() kind would be better than Color != API_RGB_WHITE
342 if( aGradient.StartColor == aGradient.EndColor &&
343 ( !aIt->second.hasTransparency() || aIt->second.getColor( rGraphicHelper, nPhClr ) != API_RGB_WHITE ) )
345 aGradient.StartColor = aIt->second.getColor( rGraphicHelper, nPhClr );
348 if( nStartTrans == nEndTrans && aIt->second.hasTransparency() )
349 nStartTrans = aIt->second.getTransparency()*255/100;
353 // push gradient or named gradient to property map
354 if( rPropMap.setProperty( SHAPEPROP_FillGradient, aGradient ) )
355 eFillStyle = FillStyle_GRADIENT;
357 // push gradient transparency to property map
358 if( nStartTrans != 0 || nEndTrans != 0 )
360 awt::Gradient aGrad(aGradient);
361 uno::Any aVal;
362 aGrad.EndColor = (sal_Int32)( nEndTrans | nEndTrans << 8 | nEndTrans << 16 );
363 aGrad.StartColor = (sal_Int32)( nStartTrans | nStartTrans << 8 | nStartTrans << 16 );
364 aVal <<= aGrad;
365 rPropMap.setProperty( SHAPEPROP_GradientTransparency, aGrad );
369 break;
371 case XML_blipFill:
372 // do not start complex graphic transformation if property is not supported...
373 if( maBlipProps.mxGraphic.is() && rPropMap.supportsProperty( SHAPEPROP_FillBitmapUrl ) )
375 // TODO: "rotate with shape" is not possible with our current core
377 OUString aGraphicUrl = rGraphicHelper.createGraphicObject( maBlipProps.mxGraphic );
378 // push bitmap or named bitmap to property map
379 if( !aGraphicUrl.isEmpty() && rPropMap.supportsProperty( SHAPEPROP_FillBitmapNameFromUrl ) && rPropMap.setProperty( SHAPEPROP_FillBitmapNameFromUrl, aGraphicUrl ) )
380 eFillStyle = FillStyle_BITMAP;
381 else if( !aGraphicUrl.isEmpty() && rPropMap.setProperty( SHAPEPROP_FillBitmapUrl, aGraphicUrl ) )
382 eFillStyle = FillStyle_BITMAP;
384 // set other bitmap properties, if bitmap has been inserted into the map
385 if( eFillStyle == FillStyle_BITMAP )
387 // bitmap mode (single, repeat, stretch)
388 BitmapMode eBitmapMode = lclGetBitmapMode( maBlipProps.moBitmapMode.get( XML_TOKEN_INVALID ) );
389 rPropMap.setProperty( SHAPEPROP_FillBitmapMode, eBitmapMode );
391 // additional settings for repeated bitmap
392 if( eBitmapMode == BitmapMode_REPEAT )
394 // anchor position inside bitmap
395 RectanglePoint eRectPoint = lclGetRectanglePoint( maBlipProps.moTileAlign.get( XML_tl ) );
396 rPropMap.setProperty( SHAPEPROP_FillBitmapRectanglePoint, eRectPoint );
398 awt::Size aOriginalSize = lclGetOriginalSize( rGraphicHelper, maBlipProps.mxGraphic );
399 if( (aOriginalSize.Width > 0) && (aOriginalSize.Height > 0) )
401 // size of one bitmap tile (given as 1/1000 percent of bitmap size), convert to 1/100 mm
402 double fScaleX = maBlipProps.moTileScaleX.get( MAX_PERCENT ) / static_cast< double >( MAX_PERCENT );
403 sal_Int32 nFillBmpSizeX = getLimitedValue< sal_Int32, double >( aOriginalSize.Width * fScaleX, 1, SAL_MAX_INT32 );
404 rPropMap.setProperty( SHAPEPROP_FillBitmapSizeX, nFillBmpSizeX );
405 double fScaleY = maBlipProps.moTileScaleY.get( MAX_PERCENT ) / static_cast< double >( MAX_PERCENT );
406 sal_Int32 nFillBmpSizeY = getLimitedValue< sal_Int32, double >( aOriginalSize.Height * fScaleY, 1, SAL_MAX_INT32 );
407 rPropMap.setProperty( SHAPEPROP_FillBitmapSizeY, nFillBmpSizeY );
409 // offset of the first bitmap tile (given as EMUs), convert to percent
410 sal_Int16 nTileOffsetX = getDoubleIntervalValue< sal_Int16 >( maBlipProps.moTileOffsetX.get( 0 ) / 3.6 / aOriginalSize.Width, 0, 100 );
411 rPropMap.setProperty( SHAPEPROP_FillBitmapOffsetX, nTileOffsetX );
412 sal_Int16 nTileOffsetY = getDoubleIntervalValue< sal_Int16 >( maBlipProps.moTileOffsetY.get( 0 ) / 3.6 / aOriginalSize.Height, 0, 100 );
413 rPropMap.setProperty( SHAPEPROP_FillBitmapOffsetY, nTileOffsetY );
418 break;
420 case XML_pattFill:
422 if( rPropMap.supportsProperty( SHAPEPROP_FillHatch ) )
424 Color aColor( maPatternProps.maPattFgColor );
425 if( aColor.isUsed() && maPatternProps.moPattPreset.has() )
427 // we do not support hatches that have background
428 // color too, so all this is some best-effort approach
429 eFillStyle = FillStyle_HATCH;
430 rPropMap.setProperty( SHAPEPROP_FillHatch, createHatch( maPatternProps.moPattPreset.get(), aColor.getColor( rGraphicHelper, nPhClr ) ) );
432 else if ( maPatternProps.maPattBgColor.isUsed() )
434 aColor = maPatternProps.maPattBgColor;
435 rPropMap.setProperty( SHAPEPROP_FillColor, aColor.getColor( rGraphicHelper, nPhClr ) );
436 if( aColor.hasTransparency() )
437 rPropMap.setProperty( SHAPEPROP_FillTransparency, aColor.getTransparency() );
438 eFillStyle = FillStyle_SOLID;
442 break;
444 case XML_grpFill:
445 // todo
446 eFillStyle = FillStyle_NONE;
447 break;
450 // set final fill style property
451 rPropMap.setProperty( SHAPEPROP_FillStyle, eFillStyle );
455 // ============================================================================
457 void GraphicProperties::pushToPropMap( PropertyMap& rPropMap, const GraphicHelper& rGraphicHelper, sal_Int32 nPhClr ) const
459 if( maBlipProps.mxGraphic.is() )
461 // created transformed graphic
462 Reference< XGraphic > xGraphic = maBlipProps.mxGraphic;
463 if( maBlipProps.maColorChangeFrom.isUsed() && maBlipProps.maColorChangeTo.isUsed() )
465 sal_Int32 nFromColor = maBlipProps.maColorChangeFrom.getColor( rGraphicHelper, nPhClr );
466 sal_Int32 nToColor = maBlipProps.maColorChangeTo.getColor( rGraphicHelper, nPhClr );
467 if ( (nFromColor != nToColor) || maBlipProps.maColorChangeTo.hasTransparency() ) try
469 sal_Int16 nToTransparence = maBlipProps.maColorChangeTo.getTransparency();
470 sal_Int8 nToAlpha = static_cast< sal_Int8 >( (100 - nToTransparence) / 39.062 ); // ?!? correct ?!?
471 Reference< XGraphicTransformer > xTransformer( maBlipProps.mxGraphic, UNO_QUERY_THROW );
472 xGraphic = xTransformer->colorChange( maBlipProps.mxGraphic, nFromColor, 9, nToColor, nToAlpha );
474 catch( Exception& )
479 rPropMap[ PROP_Graphic ] <<= xGraphic;
481 // do we still need to set GraphicURL as well? (TODO)
482 OUString aGraphicUrl = rGraphicHelper.createGraphicObject( xGraphic );
483 if( !aGraphicUrl.isEmpty() )
484 rPropMap[ PROP_GraphicURL ] <<= aGraphicUrl;
486 // cropping
487 if ( maBlipProps.moClipRect.has() )
489 geometry::IntegerRectangle2D oClipRect( maBlipProps.moClipRect.get() );
490 awt::Size aOriginalSize( rGraphicHelper.getOriginalSize( xGraphic ) );
491 if ( aOriginalSize.Width && aOriginalSize.Height )
493 text::GraphicCrop aGraphCrop( 0, 0, 0, 0 );
494 if ( oClipRect.X1 )
495 aGraphCrop.Left = static_cast< sal_Int32 >( ( static_cast< double >( aOriginalSize.Width ) * oClipRect.X1 ) / 100000 );
496 if ( oClipRect.Y1 )
497 aGraphCrop.Top = static_cast< sal_Int32 >( ( static_cast< double >( aOriginalSize.Height ) * oClipRect.Y1 ) / 100000 );
498 if ( oClipRect.X2 )
499 aGraphCrop.Right = static_cast< sal_Int32 >( ( static_cast< double >( aOriginalSize.Width ) * oClipRect.X2 ) / 100000 );
500 if ( oClipRect.Y2 )
501 aGraphCrop.Bottom = static_cast< sal_Int32 >( ( static_cast< double >( aOriginalSize.Height ) * oClipRect.Y2 ) / 100000 );
502 rPropMap[ PROP_GraphicCrop ] <<= aGraphCrop;
507 // color effect
508 ColorMode eColorMode = ColorMode_STANDARD;
509 switch( maBlipProps.moColorEffect.get( XML_TOKEN_INVALID ) )
511 case XML_biLevel: eColorMode = ColorMode_MONO; break;
512 case XML_grayscl: eColorMode = ColorMode_GREYS; break;
514 rPropMap[ PROP_GraphicColorMode ] <<= eColorMode;
516 // brightness and contrast
517 sal_Int16 nBrightness = getLimitedValue< sal_Int16, sal_Int32 >( maBlipProps.moBrightness.get( 0 ) / PER_PERCENT, -100, 100 );
518 if( nBrightness != 0 )
519 rPropMap[ PROP_AdjustLuminance ] <<= nBrightness;
520 sal_Int16 nContrast = getLimitedValue< sal_Int16, sal_Int32 >( maBlipProps.moContrast.get( 0 ) / PER_PERCENT, -100, 100 );
521 if( nContrast != 0 )
522 rPropMap[ PROP_AdjustContrast ] <<= nContrast;
524 // Media content
525 if( !maAudio.msEmbed.isEmpty() )
526 rPropMap[ PROP_MediaURL ] <<= maAudio.msEmbed;
529 // ============================================================================
531 } // namespace drawingml
532 } // namespace oox
534 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */