update dev300-m58
[ooovba.git] / oox / source / drawingml / fillproperties.cxx
blob46fe6ae5292c25b1e5ada08ce647ce6fa712f6fa
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: fillproperties.cxx,v $
10 * $Revision: 1.7.6.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 #include "oox/drawingml/fillproperties.hxx"
32 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
33 #include <com/sun/star/beans/XPropertySet.hpp>
34 #include <com/sun/star/awt/Gradient.hpp>
35 #include <com/sun/star/awt/Size.hpp>
36 #include <com/sun/star/drawing/BitmapMode.hpp>
37 #include <com/sun/star/drawing/ColorMode.hpp>
38 #include <com/sun/star/drawing/FillStyle.hpp>
39 #include <com/sun/star/drawing/RectanglePoint.hpp>
40 #include <com/sun/star/graphic/XGraphicTransformer.hpp>
41 #include "properties.hxx"
42 #include "tokens.hxx"
43 #include "oox/helper/graphichelper.hxx"
44 #include "oox/helper/modelobjecthelper.hxx"
45 #include "oox/helper/propertymap.hxx"
46 #include "oox/helper/propertyset.hxx"
47 #include "oox/core/xmlfilterbase.hxx"
49 using namespace ::com::sun::star;
50 using namespace ::com::sun::star::drawing;
51 using namespace ::com::sun::star::graphic;
53 using ::rtl::OUString;
54 using ::com::sun::star::uno::Reference;
55 using ::com::sun::star::uno::Exception;
56 using ::com::sun::star::uno::UNO_QUERY;
57 using ::com::sun::star::uno::UNO_QUERY_THROW;
58 using ::oox::core::XmlFilterBase;
60 namespace oox {
61 namespace drawingml {
63 // ============================================================================
65 namespace {
67 static const sal_Int32 spnDefaultFillIds[ FillId_END ] =
69 PROP_FillStyle,
70 PROP_FillColor,
71 PROP_FillTransparence,
72 PROP_FillGradient,
73 PROP_FillBitmapURL,
74 PROP_FillBitmapMode,
75 PROP_FillBitmapSizeX,
76 PROP_FillBitmapSizeY,
77 PROP_FillBitmapPositionOffsetX,
78 PROP_FillBitmapPositionOffsetY,
79 PROP_FillBitmapRectanglePoint
82 BitmapMode lclGetBitmapMode( sal_Int32 nToken )
84 switch( nToken )
86 case XML_tile: return BitmapMode_REPEAT;
87 case XML_stretch: return BitmapMode_STRETCH;
89 return BitmapMode_NO_REPEAT;
92 RectanglePoint lclGetRectanglePoint( sal_Int32 nToken )
94 switch( nToken )
96 case XML_tl: return RectanglePoint_LEFT_TOP;
97 case XML_t: return RectanglePoint_MIDDLE_TOP;
98 case XML_tr: return RectanglePoint_RIGHT_TOP;
99 case XML_l: return RectanglePoint_LEFT_MIDDLE;
100 case XML_ctr: return RectanglePoint_MIDDLE_MIDDLE;
101 case XML_r: return RectanglePoint_RIGHT_MIDDLE;
102 case XML_bl: return RectanglePoint_LEFT_BOTTOM;
103 case XML_b: return RectanglePoint_MIDDLE_BOTTOM;
104 case XML_br: return RectanglePoint_RIGHT_BOTTOM;
106 return RectanglePoint_LEFT_TOP;
109 const awt::Size lclGetOriginalSize( const XmlFilterBase& rFilter, const Reference< XGraphic >& rxGraphic )
111 awt::Size aSize100thMM( 0, 0 );
114 Reference< beans::XPropertySet > xGraphicPropertySet( rxGraphic, UNO_QUERY_THROW );
115 if( xGraphicPropertySet->getPropertyValue( CREATE_OUSTRING( "Size100thMM" ) ) >>= aSize100thMM )
117 if( !aSize100thMM.Width && !aSize100thMM.Height )
118 { // MAPMODE_PIXEL USED :-(
119 awt::Size aSourceSizePixel( 0, 0 );
120 if( xGraphicPropertySet->getPropertyValue( CREATE_OUSTRING( "SizePixel" ) ) >>= aSourceSizePixel )
122 aSize100thMM = awt::Size(
123 rFilter.convertScreenPixelX( aSourceSizePixel.Width ),
124 rFilter.convertScreenPixelY( aSourceSizePixel.Height ) );
129 catch( Exception& )
132 return aSize100thMM;
135 } // namespace
137 // ============================================================================
139 FillPropertyIds::FillPropertyIds( const sal_Int32* pnPropertyIds, bool bNamedFillGradient, bool bNamedFillBitmap ) :
140 mpnPropertyIds( pnPropertyIds ),
141 mbNamedFillGradient( bNamedFillGradient ),
142 mbNamedFillBitmap( bNamedFillBitmap )
144 OSL_ENSURE( mpnPropertyIds != 0, "FillPropertyIds::FillPropertyIds - missing property identifiers" );
147 // ============================================================================
149 void GradientFillProperties::assignUsed( const GradientFillProperties& rSourceProps )
151 if( !rSourceProps.maGradientStops.empty() )
152 maGradientStops = rSourceProps.maGradientStops;
153 moFillToRect.assignIfUsed( rSourceProps.moFillToRect );
154 moTileRect.assignIfUsed( rSourceProps.moTileRect );
155 moGradientPath.assignIfUsed( rSourceProps.moGradientPath );
156 moShadeAngle.assignIfUsed( rSourceProps.moShadeAngle );
157 moShadeFlip.assignIfUsed( rSourceProps.moShadeFlip );
158 moShadeScaled.assignIfUsed( rSourceProps.moShadeScaled );
159 moRotateWithShape.assignIfUsed( rSourceProps.moRotateWithShape );
162 // ============================================================================
164 void PatternFillProperties::assignUsed( const PatternFillProperties& rSourceProps )
166 maPattFgColor.assignIfUsed( rSourceProps.maPattFgColor );
167 maPattBgColor.assignIfUsed( rSourceProps.maPattBgColor );
168 moPattPreset.assignIfUsed( rSourceProps.moPattPreset );
171 // ============================================================================
173 void BlipFillProperties::assignUsed( const BlipFillProperties& rSourceProps )
175 if( rSourceProps.mxGraphic.is() )
176 mxGraphic = rSourceProps.mxGraphic;
177 moBitmapMode.assignIfUsed( rSourceProps.moBitmapMode );
178 moFillRect.assignIfUsed( rSourceProps.moFillRect );
179 moTileOffsetX.assignIfUsed( rSourceProps.moTileOffsetX );
180 moTileOffsetY.assignIfUsed( rSourceProps.moTileOffsetY );
181 moTileScaleX.assignIfUsed( rSourceProps.moTileScaleX );
182 moTileScaleY.assignIfUsed( rSourceProps.moTileScaleY );
183 moTileAlign.assignIfUsed( rSourceProps.moTileAlign );
184 moTileFlip.assignIfUsed( rSourceProps.moTileFlip );
185 moRotateWithShape.assignIfUsed( rSourceProps.moRotateWithShape );
186 moColorEffect.assignIfUsed( rSourceProps.moColorEffect );
187 moBrightness.assignIfUsed( rSourceProps.moBrightness );
188 moContrast.assignIfUsed( rSourceProps.moContrast );
189 maColorChangeFrom.assignIfUsed( rSourceProps.maColorChangeFrom );
190 maColorChangeTo.assignIfUsed( rSourceProps.maColorChangeTo );
193 // ============================================================================
195 FillPropertyIds FillProperties::DEFAULT_IDS( spnDefaultFillIds, false, false );
197 void FillProperties::assignUsed( const FillProperties& rSourceProps )
199 moFillType.assignIfUsed( rSourceProps.moFillType );
200 maFillColor.assignIfUsed( rSourceProps.maFillColor );
201 maGradientProps.assignUsed( rSourceProps.maGradientProps );
202 maPatternProps.assignUsed( rSourceProps.maPatternProps );
203 maBlipProps.assignUsed( rSourceProps.maBlipProps );
206 Color FillProperties::getBestSolidColor() const
208 Color aSolidColor;
209 if( moFillType.has() ) switch( moFillType.get() )
211 case XML_solidFill:
212 aSolidColor = maFillColor;
213 break;
214 case XML_gradFill:
215 if( !maGradientProps.maGradientStops.empty() )
216 aSolidColor = maGradientProps.maGradientStops.begin()->second;
217 break;
218 case XML_pattFill:
219 aSolidColor = maPatternProps.maPattBgColor.isUsed() ? maPatternProps.maPattBgColor : maPatternProps.maPattFgColor;
220 break;
222 return aSolidColor;
225 void FillProperties::pushToPropMap( PropertyMap& rPropMap, const FillPropertyIds& rPropIds,
226 const XmlFilterBase& rFilter, ModelObjectHelper& rModelObjHelper,
227 sal_Int32 nShapeRotation, sal_Int32 nPhClr ) const
229 if( moFillType.has() )
231 FillStyle eFillStyle = FillStyle_NONE;
232 switch( moFillType.get() )
234 case XML_noFill:
235 eFillStyle = FillStyle_NONE;
236 break;
238 case XML_solidFill:
239 if( maFillColor.isUsed() )
241 rPropMap.setProperty( rPropIds[ FillColorId ], maFillColor.getColor( rFilter, nPhClr ) );
242 if( maFillColor.hasTransparence() )
243 rPropMap.setProperty( rPropIds[ FillTransparenceId ], maFillColor.getTransparence() );
244 eFillStyle = FillStyle_SOLID;
246 break;
248 case XML_gradFill:
249 // do not create gradient struct if property is not supported...
250 if( rPropIds.has( FillGradientId ) )
252 awt::Gradient aGradient;
253 aGradient.Angle = 900;
254 aGradient.StartIntensity = 100;
255 aGradient.EndIntensity = 100;
257 if( maGradientProps.maGradientStops.size() > 1 )
259 aGradient.StartColor = maGradientProps.maGradientStops.begin()->second.getColor( rFilter, nPhClr );
260 aGradient.EndColor = maGradientProps.maGradientStops.rbegin()->second.getColor( rFilter, nPhClr );
263 // "rotate with shape" not set, or set to false -> do not rotate
264 if ( !maGradientProps.moRotateWithShape.get( false ) )
265 nShapeRotation = 0;
267 if( maGradientProps.moGradientPath.has() )
269 aGradient.Style = (maGradientProps.moGradientPath.get() == XML_circle) ? awt::GradientStyle_ELLIPTICAL : awt::GradientStyle_RECT;
270 aGradient.Angle = static_cast< sal_Int16 >( (900 - (nShapeRotation / 6000)) % 3600 );
271 aGradient.XOffset = maGradientProps.moFillToRect.has() ? getLimitedValue< sal_Int16, sal_Int32 >( maGradientProps.moFillToRect.get().X1 / 1000, 30, 70 ) : 50;
272 aGradient.YOffset = maGradientProps.moFillToRect.has() ? getLimitedValue< sal_Int16, sal_Int32 >( maGradientProps.moFillToRect.get().Y1 / 1000, 30, 70 ) : 50;
273 ::std::swap( aGradient.StartColor, aGradient.EndColor );
275 else
277 aGradient.Style = awt::GradientStyle_LINEAR;
278 aGradient.Angle = static_cast< sal_Int16 >( (4500 - ((maGradientProps.moShadeAngle.get( 0 ) - nShapeRotation) / 6000)) % 3600 );
281 // push gradient or named gradient to property map
282 if( rPropIds.mbNamedFillGradient )
284 OUString aGradientName = rModelObjHelper.insertFillGradient( aGradient );
285 if( aGradientName.getLength() > 0 )
287 rPropMap.setProperty( rPropIds[ FillGradientId ], aGradientName );
288 eFillStyle = FillStyle_GRADIENT;
291 else
293 rPropMap.setProperty( rPropIds[ FillGradientId ], aGradient );
294 eFillStyle = FillStyle_GRADIENT;
297 break;
299 case XML_blipFill:
300 // do not start complex graphic transformation if property is not supported...
301 if( maBlipProps.mxGraphic.is() && rPropIds.has( FillBitmapUrlId ) )
303 // TODO: "rotate with shape" is not possible with our current core
305 OUString aGraphicUrl = rFilter.getGraphicHelper().createGraphicObject( maBlipProps.mxGraphic );
306 if( aGraphicUrl.getLength() > 0 )
308 // push bitmap or named bitmap to property map
309 if( rPropIds.mbNamedFillBitmap )
311 OUString aBitmapName = rModelObjHelper.insertFillBitmap( aGraphicUrl );
312 if( aBitmapName.getLength() > 0 )
314 rPropMap.setProperty( rPropIds[ FillBitmapUrlId ], aBitmapName );
315 eFillStyle = FillStyle_BITMAP;
318 else
320 rPropMap.setProperty( rPropIds[ FillBitmapUrlId ], aGraphicUrl );
321 eFillStyle = FillStyle_BITMAP;
325 // set other bitmap properties, if bitmap has been inserted into the map
326 if( eFillStyle == FillStyle_BITMAP )
328 // bitmap mode (single, repeat, stretch)
329 BitmapMode eBitmapMode = lclGetBitmapMode( maBlipProps.moBitmapMode.get( XML_TOKEN_INVALID ) );
330 rPropMap.setProperty( rPropIds[ FillBitmapModeId ], eBitmapMode );
332 // additional settings for repeated bitmap
333 if( eBitmapMode == BitmapMode_REPEAT )
335 // anchor position inside bitmap
336 RectanglePoint eRectPoint = lclGetRectanglePoint( maBlipProps.moTileAlign.get( XML_tl ) );
337 rPropMap.setProperty( rPropIds[ FillBitmapRectanglePointId ], eRectPoint );
339 awt::Size aOriginalSize = lclGetOriginalSize( rFilter, maBlipProps.mxGraphic );
340 if( (aOriginalSize.Width > 0) && (aOriginalSize.Height > 0) )
342 // size of one bitmap tile (given as 1/1000 percent of bitmap size), convert to 1/100 mm
343 double fScaleX = maBlipProps.moTileScaleX.get( 100000 ) / 100000.0;
344 sal_Int32 nFillBmpSizeX = getLimitedValue< sal_Int32, double >( aOriginalSize.Width * fScaleX, 1, SAL_MAX_INT32 );
345 rPropMap.setProperty( rPropIds[ FillBitmapSizeXId ], nFillBmpSizeX );
346 double fScaleY = maBlipProps.moTileScaleY.get( 100000 ) / 100000.0;
347 sal_Int32 nFillBmpSizeY = getLimitedValue< sal_Int32, double >( aOriginalSize.Height * fScaleY, 1, SAL_MAX_INT32 );
348 rPropMap.setProperty( rPropIds[ FillBitmapSizeYId ], nFillBmpSizeY );
350 // offset of the first bitmap tile (given as EMUs), convert to percent
351 sal_Int16 nTileOffsetX = getDoubleIntervalValue< sal_Int16 >( maBlipProps.moTileOffsetX.get( 0 ) / 3.6 / aOriginalSize.Width, 0, 100 );
352 rPropMap.setProperty( rPropIds[ FillBitmapOffsetXId ], nTileOffsetX );
353 sal_Int16 nTileOffsetY = getDoubleIntervalValue< sal_Int16 >( maBlipProps.moTileOffsetY.get( 0 ) / 3.6 / aOriginalSize.Height, 0, 100 );
354 rPropMap.setProperty( rPropIds[ FillBitmapOffsetYId ], nTileOffsetY );
359 break;
361 case XML_pattFill:
363 // todo
364 Color aColor = getBestSolidColor();
365 if( aColor.isUsed() )
367 rPropMap.setProperty( rPropIds[ FillColorId ], aColor.getColor( rFilter, nPhClr ) );
368 if( aColor.hasTransparence() )
369 rPropMap.setProperty( rPropIds[ FillTransparenceId ], aColor.getTransparence() );
370 eFillStyle = FillStyle_SOLID;
373 break;
375 case XML_grpFill:
376 // todo
377 eFillStyle = FillStyle_NONE;
378 break;
381 // set final fill style property
382 rPropMap.setProperty( rPropIds[ FillStyleId ], eFillStyle );
386 void FillProperties::pushToPropSet( PropertySet& rPropSet, const FillPropertyIds& rPropIds,
387 const XmlFilterBase& rFilter, ModelObjectHelper& rModelObjHelper,
388 sal_Int32 nShapeRotation, sal_Int32 nPhClr ) const
390 PropertyMap aPropMap;
391 pushToPropMap( aPropMap, rPropIds, rFilter, rModelObjHelper, nShapeRotation, nPhClr );
392 rPropSet.setProperties( aPropMap );
395 // ============================================================================
397 void GraphicProperties::assignUsed( const GraphicProperties& rSourceProps )
399 maBlipProps.assignUsed( rSourceProps.maBlipProps );
402 void GraphicProperties::pushToPropMap( PropertyMap& rPropMap, const XmlFilterBase& rFilter, sal_Int32 nPhClr ) const
404 if( maBlipProps.mxGraphic.is() )
406 // created transformed graphic
407 Reference< XGraphic > xGraphic = maBlipProps.mxGraphic;
408 if( maBlipProps.maColorChangeFrom.isUsed() && maBlipProps.maColorChangeTo.isUsed() )
410 sal_Int32 nFromColor = maBlipProps.maColorChangeFrom.getColor( rFilter, nPhClr );
411 sal_Int32 nToColor = maBlipProps.maColorChangeTo.getColor( rFilter, nPhClr );
412 if ( (nFromColor != nToColor) || maBlipProps.maColorChangeTo.hasTransparence() ) try
414 sal_Int16 nToTransparence = maBlipProps.maColorChangeTo.getTransparence();
415 sal_Int8 nToAlpha = static_cast< sal_Int8 >( (100 - nToTransparence) / 39.062 ); // ?!? correct ?!?
416 Reference< XGraphicTransformer > xTransformer( maBlipProps.mxGraphic, UNO_QUERY_THROW );
417 xGraphic = xTransformer->colorChange( maBlipProps.mxGraphic, nFromColor, 9, nToColor, nToAlpha );
419 catch( Exception& )
424 OUString aGraphicUrl = rFilter.getGraphicHelper().createGraphicObject( xGraphic );
425 if( aGraphicUrl.getLength() > 0 )
426 rPropMap[ PROP_GraphicURL ] <<= aGraphicUrl;
429 // color effect
430 ColorMode eColorMode = ColorMode_STANDARD;
431 switch( maBlipProps.moColorEffect.get( XML_TOKEN_INVALID ) )
433 case XML_biLevel: eColorMode = ColorMode_MONO; break;
434 case XML_grayscl: eColorMode = ColorMode_GREYS; break;
436 rPropMap[ PROP_GraphicColorMode ] <<= eColorMode;
438 // brightness and contrast
439 sal_Int16 nBrightness = getLimitedValue< sal_Int16, sal_Int32 >( maBlipProps.moBrightness.get( 0 ) / 1000, -100, 100 );
440 if( nBrightness != 0 )
441 rPropMap[ PROP_AdjustLuminance ] <<= nBrightness;
442 sal_Int16 nContrast = getLimitedValue< sal_Int16, sal_Int32 >( maBlipProps.moContrast.get( 0 ) / 1000, -100, 100 );
443 if( nContrast != 0 )
444 rPropMap[ PROP_AdjustContrast ] <<= nContrast;
447 void GraphicProperties::pushToPropSet( PropertySet& rPropSet, const XmlFilterBase& rFilter, sal_Int32 nPhClr ) const
449 PropertyMap aPropMap;
450 pushToPropMap( aPropMap, rFilter, nPhClr );
451 rPropSet.setProperties( aPropMap );
454 // ============================================================================
456 } // namespace drawingml
457 } // namespace oox