1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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
;
51 // ============================================================================
55 BitmapMode
lclGetBitmapMode( sal_Int32 nToken
)
57 OSL_ASSERT((nToken
& sal_Int32(0xFFFF0000))==0);
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);
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 );
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
);
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
168 if( moFillType
.has() ) switch( moFillType
.get() )
171 aSolidColor
= maFillColor
;
174 if( !maGradientProps
.maGradientStops
.empty() )
175 aSolidColor
= maGradientProps
.maGradientStops
.begin()->second
;
178 aSolidColor
= maPatternProps
.maPattBgColor
.isUsed() ? maPatternProps
.maPattBgColor
: maPatternProps
.maPattFgColor
;
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;
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() )
263 eFillStyle
= FillStyle_NONE
;
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
;
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;
300 nShapeRotation
= 180*60000 - nShapeRotation
;
302 nShapeRotation
= -nShapeRotation
;
304 // "rotate with shape" not set, or set to false -> do not rotate
305 if ( !maGradientProps
.moRotateWithShape
.get( false ) )
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
;
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 );
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)
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
);
362 aGrad
.EndColor
= (sal_Int32
)( nEndTrans
| nEndTrans
<< 8 | nEndTrans
<< 16 );
363 aGrad
.StartColor
= (sal_Int32
)( nStartTrans
| nStartTrans
<< 8 | nStartTrans
<< 16 );
365 rPropMap
.setProperty( SHAPEPROP_GradientTransparency
, aGrad
);
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
);
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
;
446 eFillStyle
= FillStyle_NONE
;
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
);
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
;
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 );
495 aGraphCrop
.Left
= static_cast< sal_Int32
>( ( static_cast< double >( aOriginalSize
.Width
) * oClipRect
.X1
) / 100000 );
497 aGraphCrop
.Top
= static_cast< sal_Int32
>( ( static_cast< double >( aOriginalSize
.Height
) * oClipRect
.Y1
) / 100000 );
499 aGraphCrop
.Right
= static_cast< sal_Int32
>( ( static_cast< double >( aOriginalSize
.Width
) * oClipRect
.X2
) / 100000 );
501 aGraphCrop
.Bottom
= static_cast< sal_Int32
>( ( static_cast< double >( aOriginalSize
.Height
) * oClipRect
.Y2
) / 100000 );
502 rPropMap
[ PROP_GraphicCrop
] <<= aGraphCrop
;
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 );
522 rPropMap
[ PROP_AdjustContrast
] <<= nContrast
;
525 if( !maAudio
.msEmbed
.isEmpty() )
526 rPropMap
[ PROP_MediaURL
] <<= maAudio
.msEmbed
;
529 // ============================================================================
531 } // namespace drawingml
534 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */