Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include "oox/core/xmlfilterbase.hxx"
21 : #include "oox/export/drawingml.hxx"
22 : #include "oox/export/utils.hxx"
23 : #include <oox/drawingml/color.hxx>
24 : #include <oox/token/tokens.hxx>
25 : #include <oox/drawingml/drawingmltypes.hxx>
26 :
27 : #include <cstdio>
28 : #include <com/sun/star/awt/CharSet.hpp>
29 : #include <com/sun/star/awt/FontDescriptor.hpp>
30 : #include <com/sun/star/awt/FontSlant.hpp>
31 : #include <com/sun/star/awt/FontWeight.hpp>
32 : #include <com/sun/star/awt/FontUnderline.hpp>
33 : #include <com/sun/star/awt/Gradient.hpp>
34 : #include <com/sun/star/beans/XPropertySet.hpp>
35 : #include <com/sun/star/beans/XPropertyState.hpp>
36 : #include <com/sun/star/beans/Property.hpp>
37 : #include <com/sun/star/beans/XPropertySetInfo.hpp>
38 : #include <com/sun/star/container/XEnumerationAccess.hpp>
39 : #include <com/sun/star/container/XIndexAccess.hpp>
40 : #include <com/sun/star/drawing/BitmapMode.hpp>
41 : #include <com/sun/star/drawing/EnhancedCustomShapeAdjustmentValue.hpp>
42 : #include <com/sun/star/drawing/LineDash.hpp>
43 : #include <com/sun/star/drawing/LineJoint.hpp>
44 : #include <com/sun/star/drawing/LineStyle.hpp>
45 : #include <com/sun/star/drawing/TextHorizontalAdjust.hpp>
46 : #include <com/sun/star/drawing/TextVerticalAdjust.hpp>
47 : #include <com/sun/star/drawing/XShape.hpp>
48 : #include <com/sun/star/drawing/FillStyle.hpp>
49 : #include <com/sun/star/geometry/IntegerRectangle2D.hpp>
50 : #include <com/sun/star/i18n/ScriptType.hpp>
51 : #include <com/sun/star/io/XOutputStream.hpp>
52 : #include <com/sun/star/style/LineSpacing.hpp>
53 : #include <com/sun/star/style/LineSpacingMode.hpp>
54 : #include <com/sun/star/style/ParagraphAdjust.hpp>
55 : #include <com/sun/star/text/WritingMode.hpp>
56 : #include <com/sun/star/text/GraphicCrop.hpp>
57 : #include <com/sun/star/text/XText.hpp>
58 : #include <com/sun/star/text/XTextContent.hpp>
59 : #include <com/sun/star/text/XTextField.hpp>
60 : #include <com/sun/star/text/XTextRange.hpp>
61 : #include <tools/stream.hxx>
62 : #include <unotools/fontdefs.hxx>
63 : #include <vcl/cvtgrf.hxx>
64 : #include <vcl/graph.hxx>
65 : #include <vcl/settings.hxx>
66 : #include <svtools/grfmgr.hxx>
67 : #include <rtl/strbuf.hxx>
68 : #include <sfx2/app.hxx>
69 : #include <svl/languageoptions.hxx>
70 : #include <filter/msfilter/escherex.hxx>
71 : #include <filter/msfilter/util.hxx>
72 : #include <editeng/outlobj.hxx>
73 : #include <editeng/svxenum.hxx>
74 : #include <svx/unoapi.hxx>
75 : #include <svx/svdoashp.hxx>
76 : #include <svx/unoshape.hxx>
77 :
78 : using namespace ::com::sun::star;
79 : using namespace ::com::sun::star::beans;
80 : using namespace ::com::sun::star::drawing;
81 : using namespace ::com::sun::star::i18n;
82 : using namespace ::com::sun::star::style;
83 : using namespace ::com::sun::star::text;
84 : using namespace ::com::sun::star::uno;
85 : using ::com::sun::star::beans::PropertyState;
86 : using ::com::sun::star::beans::PropertyValue;
87 : using ::com::sun::star::beans::XPropertySet;
88 : using ::com::sun::star::beans::XPropertyState;
89 : using ::com::sun::star::container::XEnumeration;
90 : using ::com::sun::star::container::XEnumerationAccess;
91 : using ::com::sun::star::container::XIndexAccess;
92 : using ::com::sun::star::geometry::IntegerRectangle2D;
93 : using ::com::sun::star::io::XOutputStream;
94 : using ::com::sun::star::style::LineSpacing;
95 : using ::com::sun::star::text::XText;
96 : using ::com::sun::star::text::XTextContent;
97 : using ::com::sun::star::text::XTextField;
98 : using ::com::sun::star::text::XTextRange;
99 : using ::sax_fastparser::FSHelperPtr;
100 :
101 : DBG(extern void dump_pset(Reference< XPropertySet > rXPropSet));
102 :
103 : // Defined in generated code.
104 : extern std::map< OString, std::vector<OString> > ooxDrawingMLGetAdjNames();
105 :
106 : namespace oox {
107 : namespace drawingml {
108 :
109 : #define GETA(propName) \
110 : GetProperty( rXPropSet, OUString( #propName ) )
111 :
112 : #define GETAD(propName) \
113 : ( GetPropertyAndState( rXPropSet, rXPropState, OUString( #propName ), eState ) && eState == beans::PropertyState_DIRECT_VALUE )
114 :
115 : #define GET(variable, propName) \
116 : if ( GETA(propName) ) \
117 : mAny >>= variable;
118 :
119 : // not thread safe
120 : int DrawingML::mnImageCounter = 1;
121 :
122 276 : void DrawingML::ResetCounters()
123 : {
124 276 : mnImageCounter = 1;
125 276 : }
126 :
127 9680 : bool DrawingML::GetProperty( Reference< XPropertySet > rXPropSet, const OUString& aName )
128 : {
129 9680 : bool bRetValue = false;
130 :
131 : try {
132 9680 : mAny = rXPropSet->getPropertyValue( aName );
133 8471 : if ( mAny.hasValue() )
134 8297 : bRetValue = true;
135 1209 : } catch( const Exception& ) { /* printf ("exception when trying to get value of property: %s\n", USS(aName)); */ }
136 :
137 9680 : return bRetValue;
138 : }
139 :
140 506 : bool DrawingML::GetPropertyAndState( Reference< XPropertySet > rXPropSet, Reference< XPropertyState > rXPropState, const OUString& aName, PropertyState& eState )
141 : {
142 506 : bool bRetValue = false;
143 :
144 : try {
145 506 : mAny = rXPropSet->getPropertyValue( aName );
146 506 : if ( mAny.hasValue() ) {
147 506 : bRetValue = true;
148 506 : eState = rXPropState->getPropertyState( aName );
149 : }
150 0 : } catch( const Exception& ) { /* printf ("exception when trying to get value of property: %s\n", USS(aName)); */ }
151 :
152 506 : return bRetValue;
153 : }
154 :
155 611 : void DrawingML::WriteColor( sal_uInt32 nColor, sal_Int32 nAlpha )
156 : {
157 611 : OString sColor = OString::number( nColor, 16 );
158 611 : if( sColor.getLength() < 6 ) {
159 150 : OStringBuffer sBuf( "0" );
160 150 : int remains = 5 - sColor.getLength();
161 :
162 848 : while( remains > 0 ) {
163 548 : sBuf.append( "0" );
164 548 : remains--;
165 : }
166 :
167 150 : sBuf.append( sColor );
168 :
169 150 : sColor = sBuf.getStr();
170 : }
171 611 : if( nAlpha < MAX_PERCENT )
172 : {
173 2 : mpFS->startElementNS( XML_a, XML_srgbClr, XML_val, sColor.getStr(), FSEND );
174 2 : mpFS->singleElementNS( XML_a, XML_alpha, XML_val, OString::number(nAlpha), FSEND );
175 2 : mpFS->endElementNS( XML_a, XML_srgbClr );
176 :
177 : }
178 : else
179 : {
180 609 : mpFS->singleElementNS( XML_a, XML_srgbClr, XML_val, sColor.getStr(), FSEND );
181 611 : }
182 611 : }
183 :
184 199 : void DrawingML::WriteColor( const OUString& sColorSchemeName, Sequence< PropertyValue > aTransformations )
185 : {
186 : // prevent writing a tag with empty val attribute
187 199 : if( sColorSchemeName.isEmpty() )
188 247 : return;
189 :
190 151 : if( aTransformations.hasElements() )
191 : {
192 : mpFS->startElementNS( XML_a, XML_schemeClr,
193 : XML_val, USS( sColorSchemeName ),
194 52 : FSEND );
195 52 : WriteColorTransformations( aTransformations );
196 52 : mpFS->endElementNS( XML_a, XML_schemeClr );
197 : }
198 : else
199 : mpFS->singleElementNS( XML_a, XML_schemeClr,
200 : XML_val, USS( sColorSchemeName ),
201 99 : FSEND );
202 : }
203 :
204 52 : void DrawingML::WriteColorTransformations( Sequence< PropertyValue > aTransformations )
205 : {
206 106 : for( sal_Int32 i = 0; i < aTransformations.getLength(); i++ )
207 : {
208 54 : sal_Int32 nToken = Color::getColorTransformationToken( aTransformations[i].Name );
209 54 : if( nToken != XML_TOKEN_INVALID && aTransformations[i].Value.hasValue() )
210 : {
211 54 : sal_Int32 nValue = aTransformations[i].Value.get<sal_Int32>();
212 54 : mpFS->singleElementNS( XML_a, nToken, XML_val, I32S( nValue ), FSEND );
213 : }
214 : }
215 52 : }
216 :
217 552 : void DrawingML::WriteSolidFill( sal_uInt32 nColor, sal_Int32 nAlpha )
218 : {
219 552 : mpFS->startElementNS( XML_a, XML_solidFill, FSEND );
220 552 : WriteColor( nColor, nAlpha );
221 552 : mpFS->endElementNS( XML_a, XML_solidFill );
222 552 : }
223 :
224 55 : void DrawingML::WriteSolidFill( const OUString& sSchemeName, Sequence< PropertyValue > aTransformations )
225 : {
226 55 : mpFS->startElementNS( XML_a, XML_solidFill, FSEND );
227 55 : WriteColor( sSchemeName, aTransformations );
228 55 : mpFS->endElementNS( XML_a, XML_solidFill );
229 55 : }
230 :
231 262 : void DrawingML::WriteSolidFill( Reference< XPropertySet > rXPropSet )
232 : {
233 : // get fill color
234 262 : if ( !GetProperty( rXPropSet, "FillColor" ) )
235 263 : return;
236 261 : sal_uInt32 nFillColor = mAny.get<sal_uInt32>();
237 :
238 : // get InteropGrabBag and search the relevant attributes
239 261 : OUString sColorFillScheme;
240 261 : sal_uInt32 nOriginalColor = 0;
241 522 : Sequence< PropertyValue > aStyleProperties, aTransformations;
242 261 : if ( GetProperty( rXPropSet, "InteropGrabBag" ) )
243 : {
244 138 : Sequence< PropertyValue > aGrabBag;
245 138 : mAny >>= aGrabBag;
246 506 : for( sal_Int32 i=0; i < aGrabBag.getLength(); ++i )
247 368 : if( aGrabBag[i].Name == "SpPrSolidFillSchemeClr" )
248 30 : aGrabBag[i].Value >>= sColorFillScheme;
249 338 : else if( aGrabBag[i].Name == "OriginalSolidFillClr" )
250 66 : aGrabBag[i].Value >>= nOriginalColor;
251 272 : else if( aGrabBag[i].Name == "StyleFillRef" )
252 26 : aGrabBag[i].Value >>= aStyleProperties;
253 246 : else if( aGrabBag[i].Name == "SpPrSolidFillSchemeClrTransformations" )
254 168 : aGrabBag[i].Value >>= aTransformations;
255 : }
256 :
257 261 : sal_Int32 nAlpha = MAX_PERCENT;
258 261 : if( GetProperty( rXPropSet, "FillTransparence" ) )
259 : {
260 261 : sal_Int32 nTransparency = 0;
261 261 : mAny >>= nTransparency;
262 : // Calculate alpha value (see oox/source/drawingml/color.cxx : getTransparency())
263 261 : nAlpha = (MAX_PERCENT - ( PER_PERCENT * nTransparency ) );
264 : }
265 :
266 : // write XML
267 261 : if ( nFillColor != nOriginalColor )
268 : // the user has set a different color for the shape
269 192 : WriteSolidFill( nFillColor & 0xffffff, nAlpha );
270 69 : else if ( !sColorFillScheme.isEmpty() )
271 : // the shape had a scheme color and the user didn't change it
272 30 : WriteSolidFill( sColorFillScheme, aTransformations );
273 39 : else if ( aStyleProperties.hasElements() )
274 : {
275 21 : sal_uInt32 nThemeColor = 0;
276 63 : for( sal_Int32 i=0; i < aStyleProperties.getLength(); ++i )
277 63 : if( aStyleProperties[i].Name == "Color" )
278 : {
279 21 : aStyleProperties[i].Value >>= nThemeColor;
280 21 : break;
281 : }
282 21 : if ( nFillColor != nThemeColor )
283 : // the shape contains a theme but it wasn't being used
284 2 : WriteSolidFill( nFillColor & 0xffffff, nAlpha );
285 : // in case the shape used the style color and the user didn't change it,
286 : // we must not write a <a: solidFill> tag.
287 : }
288 : else
289 : // the shape had a custom color and the user didn't change it
290 279 : WriteSolidFill( nFillColor & 0xffffff, nAlpha );
291 : }
292 :
293 28 : void DrawingML::WriteGradientStop( sal_uInt16 nStop, sal_uInt32 nColor )
294 : {
295 : mpFS->startElementNS( XML_a, XML_gs,
296 : XML_pos, I32S( nStop * 1000 ),
297 28 : FSEND );
298 28 : WriteColor( nColor );
299 28 : mpFS->endElementNS( XML_a, XML_gs );
300 28 : }
301 :
302 28 : sal_uInt32 DrawingML::ColorWithIntensity( sal_uInt32 nColor, sal_uInt32 nIntensity )
303 : {
304 28 : return ( ( ( nColor & 0xff ) * nIntensity ) / 100 )
305 28 : | ( ( ( ( ( nColor & 0xff00 ) >> 8 ) * nIntensity ) / 100 ) << 8 )
306 28 : | ( ( ( ( ( nColor & 0xff0000 ) >> 8 ) * nIntensity ) / 100 ) << 8 );
307 : }
308 :
309 15 : bool DrawingML::EqualGradients( awt::Gradient aGradient1, awt::Gradient aGradient2 )
310 : {
311 26 : return aGradient1.Style == aGradient2.Style &&
312 14 : aGradient1.StartColor == aGradient2.StartColor &&
313 6 : aGradient1.EndColor == aGradient2.EndColor &&
314 6 : aGradient1.Angle == aGradient2.Angle &&
315 6 : aGradient1.Border == aGradient2.Border &&
316 6 : aGradient1.XOffset == aGradient2.XOffset &&
317 6 : aGradient1.YOffset == aGradient2.YOffset &&
318 6 : aGradient1.StartIntensity == aGradient2.StartIntensity &&
319 21 : aGradient1.EndIntensity == aGradient2.EndIntensity &&
320 18 : aGradient1.StepCount == aGradient2.StepCount;
321 : }
322 :
323 15 : void DrawingML::WriteGradientFill( Reference< XPropertySet > rXPropSet )
324 : {
325 15 : awt::Gradient aGradient;
326 15 : if( GETA( FillGradient ) ) {
327 15 : aGradient = *static_cast< const awt::Gradient* >( mAny.getValue() );
328 :
329 : // get InteropGrabBag and search the relevant attributes
330 15 : awt::Gradient aOriginalGradient;
331 15 : Sequence< PropertyValue > aGradientStops;
332 15 : if ( GetProperty( rXPropSet, "InteropGrabBag" ) )
333 : {
334 4 : Sequence< PropertyValue > aGrabBag;
335 4 : mAny >>= aGrabBag;
336 24 : for( sal_Int32 i=0; i < aGrabBag.getLength(); ++i )
337 20 : if( aGrabBag[i].Name == "GradFillDefinition" )
338 2 : aGrabBag[i].Value >>= aGradientStops;
339 18 : else if( aGrabBag[i].Name == "OriginalGradFill" )
340 7 : aGrabBag[i].Value >>= aOriginalGradient;
341 : }
342 :
343 : // check if an ooxml gradient had been imported and if the user has modified it
344 15 : if( EqualGradients( aOriginalGradient, aGradient ) )
345 : {
346 : // If we have no gradient stops that means original gradient were defined by a theme.
347 3 : if( aGradientStops.hasElements() )
348 : {
349 2 : mpFS->startElementNS( XML_a, XML_gradFill, FSEND );
350 2 : WriteGrabBagGradientFill(aGradientStops, aGradient);
351 2 : mpFS->endElementNS( XML_a, XML_gradFill );
352 : }
353 : }
354 : else
355 : {
356 12 : mpFS->startElementNS( XML_a, XML_gradFill, FSEND );
357 12 : WriteGradientFill(aGradient);
358 12 : mpFS->endElementNS( XML_a, XML_gradFill );
359 15 : }
360 : }
361 15 : }
362 :
363 2 : void DrawingML::WriteGrabBagGradientFill( Sequence< PropertyValue > aGradientStops, awt::Gradient rGradient )
364 : {
365 : // write back the original gradient
366 2 : mpFS->startElementNS( XML_a, XML_gsLst, FSEND );
367 :
368 : // get original stops and write them
369 8 : for( sal_Int32 i=0; i < aGradientStops.getLength(); ++i )
370 : {
371 6 : Sequence< PropertyValue > aGradientStop;
372 6 : aGradientStops[i].Value >>= aGradientStop;
373 :
374 : // get values
375 12 : OUString sSchemeClr;
376 6 : double nPos = 0;
377 6 : sal_Int16 nTransparency = 0;
378 6 : sal_Int32 nRgbClr = 0;
379 12 : Sequence< PropertyValue > aTransformations;
380 24 : for( sal_Int32 j=0; j < aGradientStop.getLength(); ++j )
381 18 : if( aGradientStop[j].Name == "SchemeClr" )
382 3 : aGradientStop[j].Value >>= sSchemeClr;
383 15 : else if( aGradientStop[j].Name == "RgbClr" )
384 3 : aGradientStop[j].Value >>= nRgbClr;
385 12 : else if( aGradientStop[j].Name == "Pos" )
386 6 : aGradientStop[j].Value >>= nPos;
387 6 : else if( aGradientStop[j].Name == "Transparency" )
388 1 : aGradientStop[j].Value >>= nTransparency;
389 5 : else if( aGradientStop[j].Name == "Transformations" )
390 3 : aGradientStop[j].Value >>= aTransformations;
391 :
392 : // write stop
393 : mpFS->startElementNS( XML_a, XML_gs,
394 : XML_pos, OString::number( nPos * 100000.0 ).getStr(),
395 6 : FSEND );
396 6 : if( sSchemeClr.isEmpty() )
397 : {
398 : // Calculate alpha value (see oox/source/drawingml/color.cxx : getTransparency())
399 3 : sal_Int32 nAlpha = (MAX_PERCENT - ( PER_PERCENT * nTransparency ) );
400 3 : WriteColor( nRgbClr, nAlpha );
401 : }
402 : else
403 3 : WriteColor( sSchemeClr, aTransformations );
404 6 : mpFS->endElementNS( XML_a, XML_gs );
405 6 : }
406 2 : mpFS->endElementNS( XML_a, XML_gsLst );
407 :
408 : mpFS->singleElementNS( XML_a, XML_lin,
409 2 : XML_ang, I32S( ( ( ( 3600 - rGradient.Angle + 900 ) * 6000 ) % 21600000 ) ),
410 2 : FSEND );
411 2 : }
412 :
413 12 : void DrawingML::WriteGradientFill( awt::Gradient rGradient )
414 : {
415 12 : switch( rGradient.Style ) {
416 : default:
417 : case GradientStyle_LINEAR:
418 8 : mpFS->startElementNS( XML_a, XML_gsLst, FSEND );
419 8 : WriteGradientStop( 0, ColorWithIntensity( rGradient.StartColor, rGradient.StartIntensity ) );
420 8 : WriteGradientStop( 100, ColorWithIntensity( rGradient.EndColor, rGradient.EndIntensity ) );
421 8 : mpFS->endElementNS( XML_a, XML_gsLst );
422 : mpFS->singleElementNS( XML_a, XML_lin,
423 8 : XML_ang, I32S( ( ( ( 3600 - rGradient.Angle + 900 ) * 6000 ) % 21600000 ) ),
424 8 : FSEND );
425 8 : break;
426 :
427 : case GradientStyle_AXIAL:
428 4 : mpFS->startElementNS( XML_a, XML_gsLst, FSEND );
429 4 : WriteGradientStop( 0, ColorWithIntensity( rGradient.EndColor, rGradient.EndIntensity ) );
430 4 : WriteGradientStop( 50, ColorWithIntensity( rGradient.StartColor, rGradient.StartIntensity ) );
431 4 : WriteGradientStop( 100, ColorWithIntensity( rGradient.EndColor, rGradient.EndIntensity ) );
432 4 : mpFS->endElementNS( XML_a, XML_gsLst );
433 : mpFS->singleElementNS( XML_a, XML_lin,
434 4 : XML_ang, I32S( ( ( ( 3600 - rGradient.Angle + 900 ) * 6000 ) % 21600000 ) ),
435 4 : FSEND );
436 4 : break;
437 :
438 : /* I don't see how to apply transformation to gradients, so
439 : * elliptical will end as radial and square as
440 : * rectangular. also position offsets are not applied */
441 : case GradientStyle_RADIAL:
442 : case GradientStyle_ELLIPTICAL:
443 : case GradientStyle_RECT:
444 : case GradientStyle_SQUARE:
445 0 : mpFS->startElementNS( XML_a, XML_gsLst, FSEND );
446 0 : WriteGradientStop( 0, ColorWithIntensity( rGradient.EndColor, rGradient.EndIntensity ) );
447 0 : WriteGradientStop( 100, ColorWithIntensity( rGradient.StartColor, rGradient.StartIntensity ) );
448 0 : mpFS->endElementNS( XML_a, XML_gsLst );
449 : mpFS->singleElementNS( XML_a, XML_path,
450 0 : XML_path, ( rGradient.Style == awt::GradientStyle_RADIAL || rGradient.Style == awt::GradientStyle_ELLIPTICAL ) ? "circle" : "rect",
451 0 : FSEND );
452 0 : break;
453 : }
454 12 : }
455 :
456 712 : void DrawingML::WriteLineArrow( Reference< XPropertySet > rXPropSet, bool bLineStart )
457 : {
458 : ESCHER_LineEnd eLineEnd;
459 : sal_Int32 nArrowLength;
460 : sal_Int32 nArrowWidth;
461 :
462 712 : if ( EscherPropertyContainer::GetLineArrow( bLineStart, rXPropSet, eLineEnd, nArrowLength, nArrowWidth ) ) {
463 : const char* len;
464 : const char* type;
465 : const char* width;
466 :
467 24 : switch( nArrowLength ) {
468 : case ESCHER_LineShortArrow:
469 0 : len = "sm";
470 0 : break;
471 : default:
472 : case ESCHER_LineMediumLenArrow:
473 24 : len = "med";
474 24 : break;
475 : case ESCHER_LineLongArrow:
476 0 : len = "lg";
477 0 : break;
478 : }
479 :
480 24 : switch( eLineEnd ) {
481 : default:
482 : case ESCHER_LineNoEnd:
483 0 : type = "none";
484 0 : break;
485 : case ESCHER_LineArrowEnd:
486 20 : type = "triangle";
487 20 : break;
488 : case ESCHER_LineArrowStealthEnd:
489 1 : type = "stealth";
490 1 : break;
491 : case ESCHER_LineArrowDiamondEnd:
492 2 : type = "diamond";
493 2 : break;
494 : case ESCHER_LineArrowOvalEnd:
495 0 : type = "oval";
496 0 : break;
497 : case ESCHER_LineArrowOpenEnd:
498 1 : type = "arrow";
499 1 : break;
500 : }
501 :
502 24 : switch( nArrowWidth ) {
503 : case ESCHER_LineNarrowArrow:
504 0 : width = "sm";
505 0 : break;
506 : default:
507 : case ESCHER_LineMediumWidthArrow:
508 24 : width = "med";
509 24 : break;
510 : case ESCHER_LineWideArrow:
511 0 : width = "lg";
512 0 : break;
513 : }
514 :
515 : mpFS->singleElementNS( XML_a, bLineStart ? XML_headEnd : XML_tailEnd,
516 : XML_len, len,
517 : XML_type, type,
518 : XML_w, width,
519 24 : FSEND );
520 : }
521 712 : }
522 :
523 617 : void DrawingML::WriteOutline( Reference< XPropertySet > rXPropSet )
524 : {
525 617 : drawing::LineStyle aLineStyle( drawing::LineStyle_NONE );
526 :
527 617 : GET( aLineStyle, LineStyle );
528 :
529 617 : sal_uInt32 nLineWidth = 0;
530 617 : sal_uInt32 nColor = 0;
531 617 : bool bColorSet = false;
532 617 : const char* cap = NULL;
533 617 : drawing::LineDash aLineDash;
534 617 : bool bDashSet = false;
535 617 : bool bNoFill = false;
536 :
537 : // get InteropGrabBag and search the relevant attributes
538 617 : OUString sColorFillScheme;
539 617 : sal_uInt32 nOriginalColor( 0 ), nStyleColor( 0 ), nStyleLineWidth( 0 );
540 1234 : Sequence< PropertyValue > aStyleProperties, aTransformations;
541 617 : drawing::LineStyle aStyleLineStyle( drawing::LineStyle_NONE );
542 617 : drawing::LineJoint aStyleLineJoint( drawing::LineJoint_NONE );
543 617 : if ( GetProperty( rXPropSet, "InteropGrabBag" ) )
544 : {
545 264 : Sequence< PropertyValue > aGrabBag;
546 264 : mAny >>= aGrabBag;
547 804 : for( sal_Int32 i=0; i < aGrabBag.getLength(); ++i )
548 540 : if( aGrabBag[i].Name == "SpPrLnSolidFillSchemeClr" )
549 25 : aGrabBag[i].Value >>= sColorFillScheme;
550 515 : else if( aGrabBag[i].Name == "OriginalLnSolidFillClr" )
551 141 : aGrabBag[i].Value >>= nOriginalColor;
552 374 : else if( aGrabBag[i].Name == "StyleLnRef" )
553 55 : aGrabBag[i].Value >>= aStyleProperties;
554 319 : else if( aGrabBag[i].Name == "SpPrLnSolidFillSchemeClrTransformations" )
555 25 : aGrabBag[i].Value >>= aTransformations;
556 264 : if( aStyleProperties.hasElements() )
557 : {
558 440 : for( sal_Int32 i=0; i < aStyleProperties.getLength(); ++i )
559 385 : if( aStyleProperties[i].Name == "Color" )
560 55 : aStyleProperties[i].Value >>= nStyleColor;
561 330 : else if( aStyleProperties[i].Name == "LineStyle" )
562 55 : aStyleProperties[i].Value >>= aStyleLineStyle;
563 275 : else if( aStyleProperties[i].Name == "LineJoint" )
564 55 : aStyleProperties[i].Value >>= aStyleLineJoint;
565 220 : else if( aStyleProperties[i].Name == "LineWidth" )
566 55 : aStyleProperties[i].Value >>= nStyleLineWidth;
567 264 : }
568 : }
569 :
570 617 : GET( nLineWidth, LineWidth );
571 :
572 617 : switch( aLineStyle ) {
573 : case drawing::LineStyle_NONE:
574 261 : bNoFill = true;
575 261 : break;
576 : case drawing::LineStyle_DASH:
577 5 : if( GETA( LineDash ) ) {
578 5 : aLineDash = *(drawing::LineDash*) mAny.getValue();
579 5 : bDashSet = true;
580 5 : if( aLineDash.Style == DashStyle_ROUND || aLineDash.Style == DashStyle_ROUNDRELATIVE )
581 2 : cap = "rnd";
582 :
583 : DBG(fprintf(stderr, "dash dots: %d dashes: %d dotlen: %d dashlen: %d distance: %d\n",
584 : int( aLineDash.Dots ), int( aLineDash.Dashes ), int( aLineDash.DotLen ), int( aLineDash.DashLen ), int( aLineDash.Distance )));
585 : }
586 : /* fallthru intended */
587 : case drawing::LineStyle_SOLID:
588 : default:
589 356 : if ( GETA( LineColor ) ) {
590 356 : nColor = *((sal_uInt32*) mAny.getValue()) & 0xffffff;
591 356 : bColorSet = true;
592 : }
593 356 : break;
594 : }
595 :
596 : mpFS->startElementNS( XML_a, XML_ln,
597 : XML_cap, cap,
598 854 : XML_w, nLineWidth > 1 && nStyleLineWidth != nLineWidth ?
599 1035 : I64S( MM100toEMU( nLineWidth ) ) :NULL,
600 1851 : FSEND );
601 :
602 617 : if( bColorSet )
603 : {
604 356 : if( nColor != nOriginalColor )
605 : // the user has set a different color for the line
606 182 : WriteSolidFill( nColor );
607 174 : else if( !sColorFillScheme.isEmpty() )
608 : // the line had a scheme color and the user didn't change it
609 25 : WriteSolidFill( sColorFillScheme, aTransformations );
610 149 : else if( aStyleProperties.hasElements() )
611 : {
612 26 : if( nColor != nStyleColor )
613 : // the line style defines some color but it wasn't being used
614 2 : WriteSolidFill( nColor );
615 : // in case the shape used the style color and the user didn't change it,
616 : // we must not write a <a: solidFill> tag.
617 : }
618 : else
619 123 : WriteSolidFill( nColor );
620 : }
621 :
622 617 : if( bDashSet && aStyleLineStyle != drawing::LineStyle_DASH ) {
623 : // line style is a dash and it was not set by the shape style
624 : // TODO: the XML_d and XML_sp values seem insane
625 5 : mpFS->startElementNS( XML_a, XML_custDash, FSEND );
626 : int i;
627 5 : for( i = 0; i < aLineDash.Dots; i ++ )
628 : mpFS->singleElementNS( XML_a, XML_ds,
629 : XML_d, aLineDash.DotLen ? writePercentage( aLineDash.DotLen*1000 ) : "100000%",
630 : XML_sp, writePercentage( aLineDash.Distance*1000 ),
631 0 : FSEND );
632 10 : for( i = 0; i < aLineDash.Dashes; i ++ )
633 : mpFS->singleElementNS( XML_a, XML_ds,
634 : XML_d, aLineDash.DashLen ? writePercentage( aLineDash.DashLen*1000 ) : "100000%",
635 : XML_sp, writePercentage( aLineDash.Distance*1000 ),
636 5 : FSEND );
637 5 : mpFS->endElementNS( XML_a, XML_custDash );
638 : }
639 :
640 617 : if( !bNoFill && nLineWidth > 1 && GETA( LineJoint ) ) {
641 : LineJoint eLineJoint;
642 :
643 220 : mAny >>= eLineJoint;
644 220 : if( aStyleLineJoint == LineJoint_NONE || aStyleLineJoint != eLineJoint )
645 : // style-defined line joint does not exist, or is different from the shape's joint
646 216 : switch( eLineJoint ) {
647 : case LineJoint_NONE:
648 : case LineJoint_MIDDLE:
649 : case LineJoint_BEVEL:
650 1 : mpFS->singleElementNS( XML_a, XML_bevel, FSEND );
651 1 : break;
652 : default:
653 : case LineJoint_MITER:
654 21 : mpFS->singleElementNS( XML_a, XML_miter, FSEND );
655 21 : break;
656 : case LineJoint_ROUND:
657 194 : mpFS->singleElementNS( XML_a, XML_round, FSEND );
658 194 : break;
659 : }
660 : }
661 :
662 617 : if( !bNoFill )
663 : {
664 356 : WriteLineArrow( rXPropSet, true );
665 356 : WriteLineArrow( rXPropSet, false );
666 : }
667 : else
668 : {
669 261 : mpFS->singleElementNS( XML_a, XML_noFill, FSEND );
670 : }
671 :
672 1234 : mpFS->endElementNS( XML_a, XML_ln );
673 617 : }
674 :
675 38 : OUString DrawingML::WriteImage( const OUString& rURL, bool bRelPathToMedia )
676 : {
677 38 : OString aURLBS(OUStringToOString(rURL, RTL_TEXTENCODING_UTF8));
678 :
679 38 : const char aURLBegin[] = "vnd.sun.star.GraphicObject:";
680 38 : sal_Int32 index = aURLBS.indexOf(aURLBegin);
681 :
682 38 : if ( index != -1 )
683 : {
684 : DBG(fprintf (stderr, "begin: %ld %s\n", long( sizeof( aURLBegin ) ), USS( rURL ) + RTL_CONSTASCII_LENGTH( aURLBegin ) ));
685 38 : Graphic aGraphic = GraphicObject( aURLBS.copy(RTL_CONSTASCII_LENGTH(aURLBegin)) ).GetTransformedGraphic ();
686 :
687 38 : return WriteImage( aGraphic , bRelPathToMedia );
688 : } else {
689 : // add link to relations
690 : }
691 :
692 0 : return OUString();
693 : }
694 :
695 109 : const char* DrawingML::GetComponentDir()
696 : {
697 109 : switch ( meDocumentType )
698 : {
699 99 : case DOCUMENT_DOCX: return "word";
700 8 : case DOCUMENT_PPTX: return "ppt";
701 2 : case DOCUMENT_XLSX: return "xl";
702 : }
703 :
704 0 : return "unknown";
705 : }
706 :
707 109 : const char* DrawingML::GetRelationCompPrefix()
708 : {
709 109 : switch ( meDocumentType )
710 : {
711 99 : case DOCUMENT_DOCX: return "";
712 : case DOCUMENT_PPTX:
713 10 : case DOCUMENT_XLSX: return "../";
714 : }
715 :
716 0 : return "unknown";
717 : }
718 :
719 110 : OUString DrawingML::WriteImage( const Graphic& rGraphic , bool bRelPathToMedia )
720 : {
721 110 : GfxLink aLink = rGraphic.GetLink ();
722 220 : OUString sMediaType;
723 110 : const char* pExtension = "";
724 110 : OUString sRelId;
725 :
726 220 : SvMemoryStream aStream;
727 110 : const void* aData = aLink.GetData();
728 110 : sal_Size nDataSize = aLink.GetDataSize();
729 :
730 110 : switch ( aLink.GetType() ) {
731 : case GFX_LINK_TYPE_NATIVE_GIF:
732 11 : sMediaType = "image/gif";
733 11 : pExtension = ".gif";
734 11 : break;
735 :
736 : // #i15508# added BMP type for better exports
737 : // export not yet active, so adding for reference (not checked)
738 : case GFX_LINK_TYPE_NATIVE_BMP:
739 2 : sMediaType = "image/bmp";
740 2 : pExtension = ".bmp";
741 2 : break;
742 :
743 : case GFX_LINK_TYPE_NATIVE_JPG:
744 22 : sMediaType = "image/jpeg";
745 22 : pExtension = ".jpeg";
746 22 : break;
747 : case GFX_LINK_TYPE_NATIVE_PNG:
748 32 : sMediaType = "image/png";
749 32 : pExtension = ".png";
750 32 : break;
751 : case GFX_LINK_TYPE_NATIVE_TIF:
752 0 : sMediaType = "image/tiff";
753 0 : pExtension = ".tiff";
754 0 : break;
755 : case GFX_LINK_TYPE_NATIVE_WMF:
756 26 : sMediaType = "image/x-wmf";
757 26 : pExtension = ".wmf";
758 26 : break;
759 : case GFX_LINK_TYPE_NATIVE_MET:
760 0 : sMediaType = "image/x-met";
761 0 : pExtension = ".met";
762 0 : break;
763 : case GFX_LINK_TYPE_NATIVE_PCT:
764 0 : sMediaType = "image/x-pict";
765 0 : pExtension = ".pct";
766 0 : break;
767 : case GFX_LINK_TYPE_NATIVE_MOV:
768 0 : sMediaType = "application/movie";
769 0 : pExtension = ".MOV";
770 0 : break;
771 : default: {
772 17 : GraphicType aType = rGraphic.GetType();
773 17 : if ( aType == GRAPHIC_BITMAP ) {
774 11 : GraphicConverter::Export( aStream, rGraphic, CVT_PNG );
775 11 : sMediaType = "image/png";
776 11 : pExtension = ".png";
777 6 : } else if ( aType == GRAPHIC_GDIMETAFILE ) {
778 5 : GraphicConverter::Export( aStream, rGraphic, CVT_EMF );
779 5 : sMediaType = "image/x-emf";
780 5 : pExtension = ".emf";
781 : } else {
782 : OSL_TRACE( "unhandled graphic type" );
783 : /*Earlier, even in case of unhandled graphic types we were
784 : proceeding to write the image, which would eventually
785 : write an empty image with a zero size, and return a valid
786 : relationID, which is incorrect.
787 : */
788 1 : return sRelId;
789 : }
790 :
791 16 : aData = aStream.GetData();
792 16 : nDataSize = aStream.GetEndOfData();
793 16 : break;
794 : }
795 : }
796 :
797 : Reference< XOutputStream > xOutStream = mpFB->openFragmentStream( OUStringBuffer()
798 218 : .appendAscii( GetComponentDir() )
799 109 : .appendAscii( "/media/image" )
800 218 : .append( (sal_Int32) mnImageCounter )
801 109 : .appendAscii( pExtension )
802 : .makeStringAndClear(),
803 109 : sMediaType );
804 109 : xOutStream->writeBytes( Sequence< sal_Int8 >( (const sal_Int8*) aData, nDataSize ) );
805 109 : xOutStream->closeOutput();
806 :
807 218 : OString sRelPathToMedia = "media/image";
808 109 : if ( bRelPathToMedia )
809 1 : sRelPathToMedia = "../" + sRelPathToMedia;
810 218 : sRelId = mpFB->addRelation( mpFS->getOutputStream(),
811 : "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",
812 : OUStringBuffer()
813 218 : .appendAscii( GetRelationCompPrefix() )
814 218 : .appendAscii( sRelPathToMedia.getStr() )
815 218 : .append( (sal_Int32) mnImageCounter ++ )
816 109 : .appendAscii( pExtension )
817 109 : .makeStringAndClear() );
818 :
819 328 : return sRelId;
820 : }
821 :
822 38 : OUString DrawingML::WriteBlip( Reference< XPropertySet > rXPropSet, const OUString& rURL, bool bRelPathToMedia, const Graphic *pGraphic )
823 : {
824 38 : OUString sRelId = pGraphic ? WriteImage( *pGraphic, bRelPathToMedia ) : WriteImage( rURL, bRelPathToMedia );
825 38 : sal_Int16 nBright = 0;
826 38 : sal_Int32 nContrast = 0;
827 :
828 38 : GET( nBright, AdjustLuminance );
829 38 : GET( nContrast, AdjustContrast );
830 :
831 : mpFS->startElementNS( XML_a, XML_blip,
832 : FSNS( XML_r, XML_embed), OUStringToOString( sRelId, RTL_TEXTENCODING_UTF8 ).getStr(),
833 38 : FSEND );
834 38 : if( nBright || nContrast )
835 : mpFS->singleElementNS( XML_a, XML_lum,
836 0 : XML_bright, nBright ? I32S( nBright*1000 ) : NULL,
837 0 : XML_contrast, nContrast ? I32S( nContrast*1000 ) : NULL,
838 38 : FSEND );
839 :
840 38 : mpFS->endElementNS( XML_a, XML_blip );
841 :
842 38 : return sRelId;
843 : }
844 :
845 4 : void DrawingML::WriteBlipMode( Reference< XPropertySet > rXPropSet, const OUString& rURL )
846 : {
847 4 : BitmapMode eBitmapMode( BitmapMode_NO_REPEAT );
848 4 : if (GetProperty( rXPropSet, "FillBitmapMode" ) )
849 4 : mAny >>= eBitmapMode;
850 :
851 : DBG(fprintf(stderr, "fill bitmap mode: %d\n", eBitmapMode));
852 :
853 4 : switch (eBitmapMode) {
854 : case BitmapMode_REPEAT:
855 0 : mpFS->singleElementNS( XML_a, XML_tile, FSEND );
856 0 : break;
857 : case BitmapMode_STRETCH:
858 4 : WriteStretch( rXPropSet, rURL );
859 4 : break;
860 : default:
861 : ;
862 : }
863 4 : }
864 :
865 85 : void DrawingML::WriteBlipOrNormalFill( Reference< XPropertySet > xPropSet, const OUString& rURLPropName )
866 : {
867 : // check for blip and otherwise fall back to normal fill
868 : // we always store normal fill properties but OOXML
869 : // uses a choice between our fill props and BlipFill
870 85 : if (GetProperty ( xPropSet, rURLPropName ))
871 0 : WriteBlipFill( xPropSet, rURLPropName );
872 : else
873 85 : WriteFill(xPropSet);
874 85 : }
875 :
876 154 : void DrawingML::WriteBlipFill( Reference< XPropertySet > rXPropSet, const OUString& sURLPropName )
877 : {
878 154 : WriteBlipFill( rXPropSet, sURLPropName, XML_a );
879 154 : }
880 :
881 154 : void DrawingML::WriteBlipFill( Reference< XPropertySet > rXPropSet, const OUString& sURLPropName, sal_Int32 nXmlNamespace )
882 : {
883 154 : if ( GetProperty( rXPropSet, sURLPropName ) ) {
884 3 : OUString aURL;
885 3 : mAny >>= aURL;
886 3 : bool bWriteMode = false;
887 3 : if( sURLPropName == "FillBitmapURL" || sURLPropName == "BackGraphicURL")
888 3 : bWriteMode = true;
889 3 : WriteBlipFill( rXPropSet, aURL, nXmlNamespace, bWriteMode );
890 : }
891 154 : }
892 :
893 4 : void DrawingML::WriteBlipFill( Reference< XPropertySet > rXPropSet, const OUString& sBitmapURL, sal_Int32 nXmlNamespace, bool bWriteMode, bool bRelPathToMedia )
894 : {
895 4 : if ( !sBitmapURL.isEmpty() ) {
896 : DBG(fprintf (stderr, "URL: %s\n", OUStringToOString( sBitmapURL, RTL_TEXTENCODING_UTF8 ).getStr() ));
897 :
898 4 : mpFS->startElementNS( nXmlNamespace , XML_blipFill, FSEND );
899 :
900 4 : WriteBlip( rXPropSet, sBitmapURL, bRelPathToMedia );
901 :
902 4 : if( bWriteMode )
903 4 : WriteBlipMode( rXPropSet, sBitmapURL );
904 0 : else if( GetProperty( rXPropSet, "FillBitmapStretch" ) ) {
905 0 : bool bStretch = false;
906 0 : mAny >>= bStretch;
907 :
908 0 : if( bStretch )
909 0 : WriteStretch( rXPropSet, sBitmapURL );
910 : }
911 4 : mpFS->endElementNS( nXmlNamespace, XML_blipFill );
912 : }
913 4 : }
914 :
915 14 : void DrawingML::WritePattFill( Reference< XPropertySet > rXPropSet )
916 : {
917 14 : if ( GetProperty( rXPropSet, "FillHatch" ) )
918 : {
919 14 : drawing::Hatch aHatch;
920 14 : mAny >>= aHatch;
921 :
922 14 : mpFS->startElementNS( XML_a , XML_pattFill, XML_prst, GetHatchPattern(aHatch), FSEND );
923 :
924 14 : mpFS->startElementNS( XML_a , XML_fgClr, FSEND );
925 14 : WriteColor(aHatch.Color);
926 14 : mpFS->endElementNS( XML_a , XML_fgClr );
927 :
928 : // In Writer hatching has no background so use white as a default value.
929 14 : mpFS->startElementNS( XML_a , XML_bgClr, FSEND );
930 14 : WriteColor(COL_WHITE);
931 14 : mpFS->endElementNS( XML_a , XML_bgClr );
932 :
933 14 : mpFS->endElementNS( XML_a , XML_pattFill );
934 : }
935 14 : }
936 :
937 34 : void DrawingML::WriteSrcRect( Reference< XPropertySet > rXPropSet, const OUString& rURL )
938 : {
939 34 : Size aOriginalSize( GraphicObject::CreateGraphicObjectFromURL( rURL ).GetPrefSize() );
940 :
941 34 : if ( GetProperty( rXPropSet, "GraphicCrop" ) )
942 : {
943 34 : ::com::sun::star::text::GraphicCrop aGraphicCropStruct;
944 34 : mAny >>= aGraphicCropStruct;
945 :
946 34 : if ( (0 != aGraphicCropStruct.Left) || (0 != aGraphicCropStruct.Top) || (0 != aGraphicCropStruct.Right) || (0 != aGraphicCropStruct.Bottom) )
947 : {
948 : mpFS->singleElementNS( XML_a, XML_srcRect,
949 0 : XML_l, I32S(((aGraphicCropStruct.Left) * 100000)/aOriginalSize.Width()),
950 0 : XML_t, I32S(((aGraphicCropStruct.Top) * 100000)/aOriginalSize.Height()),
951 0 : XML_r, I32S(((aGraphicCropStruct.Right) * 100000)/aOriginalSize.Width()),
952 0 : XML_b, I32S(((aGraphicCropStruct.Bottom) * 100000)/aOriginalSize.Height()),
953 0 : FSEND );
954 : }
955 : }
956 34 : }
957 :
958 4 : void DrawingML::WriteStretch( ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > rXPropSet, const OUString& rURL )
959 : {
960 4 : mpFS->startElementNS( XML_a, XML_stretch, FSEND );
961 :
962 4 : bool bCrop = false;
963 4 : if ( GetProperty( rXPropSet, "GraphicCrop" ) )
964 : {
965 2 : ::com::sun::star::text::GraphicCrop aGraphicCropStruct;
966 2 : mAny >>= aGraphicCropStruct;
967 :
968 2 : if ( (0 != aGraphicCropStruct.Left) || (0 != aGraphicCropStruct.Top) || (0 != aGraphicCropStruct.Right) || (0 != aGraphicCropStruct.Bottom) )
969 : {
970 1 : Size aOriginalSize( GraphicObject::CreateGraphicObjectFromURL( rURL ).GetPrefSize() );
971 : mpFS->singleElementNS( XML_a, XML_fillRect,
972 1 : XML_l, I32S(((aGraphicCropStruct.Left) * 100000)/aOriginalSize.Width()),
973 1 : XML_t, I32S(((aGraphicCropStruct.Top) * 100000)/aOriginalSize.Height()),
974 1 : XML_r, I32S(((aGraphicCropStruct.Right) * 100000)/aOriginalSize.Width()),
975 1 : XML_b, I32S(((aGraphicCropStruct.Bottom) * 100000)/aOriginalSize.Height()),
976 4 : FSEND );
977 1 : bCrop = true;
978 : }
979 : }
980 :
981 4 : if( !bCrop )
982 : {
983 3 : mpFS->singleElementNS( XML_a, XML_fillRect, FSEND );
984 : }
985 :
986 4 : mpFS->endElementNS( XML_a, XML_stretch );
987 4 : }
988 :
989 527 : void DrawingML::WriteTransformation( const Rectangle& rRect,
990 : sal_Int32 nXmlNamespace, bool bFlipH, bool bFlipV, sal_Int32 nRotation )
991 : {
992 : mpFS->startElementNS( nXmlNamespace, XML_xfrm,
993 : XML_flipH, bFlipH ? "1" : NULL,
994 : XML_flipV, bFlipV ? "1" : NULL,
995 1118 : XML_rot, (nRotation % 21600000) ? I32S( nRotation ) : NULL,
996 1054 : FSEND );
997 :
998 527 : sal_Int32 nLeft = rRect.Left();
999 527 : sal_Int32 nTop = rRect.Top();
1000 527 : if (GetDocumentType() == DOCUMENT_DOCX && !m_xParent.is())
1001 : {
1002 160 : nLeft = 0;
1003 160 : nTop = 0;
1004 : }
1005 :
1006 527 : mpFS->singleElementNS( XML_a, XML_off, XML_x, IS( MM100toEMU( nLeft ) ), XML_y, IS( MM100toEMU( nTop ) ), FSEND );
1007 527 : mpFS->singleElementNS( XML_a, XML_ext, XML_cx, IS( MM100toEMU( rRect.GetWidth() ) ), XML_cy, IS( MM100toEMU( rRect.GetHeight() ) ), FSEND );
1008 :
1009 527 : mpFS->endElementNS( nXmlNamespace, XML_xfrm );
1010 527 : }
1011 :
1012 486 : void DrawingML::WriteShapeTransformation( Reference< XShape > rXShape, sal_Int32 nXmlNamespace, bool bFlipH, bool bFlipV, bool bSuppressRotation )
1013 : {
1014 : DBG(fprintf(stderr, "write shape transformation\n" ));
1015 :
1016 486 : sal_Int32 nRotation=0;
1017 486 : awt::Point aPos = rXShape->getPosition();
1018 486 : awt::Size aSize = rXShape->getSize();
1019 :
1020 486 : if (m_xParent.is())
1021 : {
1022 152 : awt::Point aParentPos = m_xParent->getPosition();
1023 152 : aPos.X -= aParentPos.X;
1024 152 : aPos.Y -= aParentPos.Y;
1025 : }
1026 :
1027 486 : if ( aSize.Width < 0 )
1028 24 : aSize.Width = 1000;
1029 486 : if ( aSize.Height < 0 )
1030 11 : aSize.Height = 1000;
1031 486 : if (!bSuppressRotation)
1032 : {
1033 482 : SdrObject* pShape = (SdrObject*) GetSdrObjectFromXShape( rXShape );
1034 482 : nRotation=pShape->GetRotateAngle();
1035 482 : if (nRotation != 0 && nRotation != 18000)
1036 : {
1037 6 : int faccos=bFlipV ? -1 : 1;
1038 6 : int facsin=bFlipH ? -1 : 1;
1039 6 : aPos.X-=(1-faccos*cos(nRotation*F_PI18000))*aSize.Width/2-facsin*sin(nRotation*F_PI18000)*aSize.Height/2;
1040 6 : aPos.Y-=(1-faccos*cos(nRotation*F_PI18000))*aSize.Height/2+facsin*sin(nRotation*F_PI18000)*aSize.Width/2;
1041 : }
1042 : }
1043 486 : if (!bSuppressRotation)
1044 : {
1045 482 : if (bFlipV) {nRotation=(nRotation+18000)%36000;}
1046 : }
1047 486 : WriteTransformation( Rectangle( Point( aPos.X, aPos.Y ), Size( aSize.Width, aSize.Height ) ), nXmlNamespace, bFlipH, bFlipV, PPTX_EXPORT_ROTATE_CLOCKWISIFY(nRotation) );
1048 486 : }
1049 :
1050 80 : void DrawingML::WriteRunProperties( Reference< XPropertySet > rRun, bool bIsField )
1051 : {
1052 80 : Reference< XPropertySet > rXPropSet( rRun, UNO_QUERY );
1053 160 : Reference< XPropertyState > rXPropState( rRun, UNO_QUERY );
1054 160 : OUString usLanguage;
1055 : PropertyState eState;
1056 80 : sal_Int16 nScriptType = SvtLanguageOptions::GetScriptTypeOfLanguage( Application::GetSettings().GetLanguageTag().getLanguageType() );
1057 80 : bool bComplex = ( nScriptType == ScriptType::COMPLEX );
1058 80 : const char* bold = NULL;
1059 80 : const char* italic = NULL;
1060 80 : const char* underline = NULL;
1061 80 : sal_Int32 nSize = 1800;
1062 80 : sal_Int32 nCharEscapement = 0;
1063 :
1064 80 : if( GETA( CharHeight ) )
1065 80 : nSize = (sal_Int32) (100*(*((float*) mAny.getValue())));
1066 :
1067 80 : if ( ( bComplex && GETA( CharWeightComplex ) ) || GETA( CharWeight ) )
1068 80 : if ( *((float*) mAny.getValue()) >= awt::FontWeight::SEMIBOLD )
1069 23 : bold = "1";
1070 :
1071 80 : if ( ( bComplex && GETA( CharPostureComplex ) ) || GETA( CharPosture ) )
1072 80 : switch ( *((awt::FontSlant*) mAny.getValue()) )
1073 : {
1074 : case awt::FontSlant_OBLIQUE :
1075 : case awt::FontSlant_ITALIC :
1076 0 : italic = "1";
1077 0 : break;
1078 : default:
1079 80 : break;
1080 : }
1081 :
1082 80 : if ( GETAD( CharUnderline ) )
1083 6 : switch ( *((sal_Int16*) mAny.getValue()) )
1084 : {
1085 : case awt::FontUnderline::SINGLE :
1086 0 : underline = "sng";
1087 0 : break;
1088 : case awt::FontUnderline::DOUBLE :
1089 0 : underline = "dbl";
1090 0 : break;
1091 : case awt::FontUnderline::DOTTED :
1092 0 : underline = "dotted";
1093 0 : break;
1094 : case awt::FontUnderline::DASH :
1095 0 : underline = "dash";
1096 0 : break;
1097 : case awt::FontUnderline::LONGDASH :
1098 0 : underline = "dashLong";
1099 0 : break;
1100 : case awt::FontUnderline::DASHDOT :
1101 0 : underline = "dotDash";
1102 0 : break;
1103 : case awt::FontUnderline::DASHDOTDOT :
1104 0 : underline = "dotDotDash";
1105 0 : break;
1106 : case awt::FontUnderline::WAVE :
1107 0 : underline = "wavy";
1108 0 : break;
1109 : case awt::FontUnderline::DOUBLEWAVE :
1110 0 : underline = "wavyDbl";
1111 0 : break;
1112 : case awt::FontUnderline::BOLD :
1113 0 : underline = "heavy";
1114 0 : break;
1115 : case awt::FontUnderline::BOLDDOTTED :
1116 0 : underline = "dottedHeavy";
1117 0 : break;
1118 : case awt::FontUnderline::BOLDDASH :
1119 0 : underline = "dashHeavy";
1120 0 : break;
1121 : case awt::FontUnderline::BOLDLONGDASH :
1122 0 : underline = "dashLongHeavy";
1123 0 : break;
1124 : case awt::FontUnderline::BOLDDASHDOT :
1125 0 : underline = "dotDashHeavy";
1126 0 : break;
1127 : case awt::FontUnderline::BOLDDASHDOTDOT :
1128 0 : underline = "dotDotDashHeavy";
1129 0 : break;
1130 : case awt::FontUnderline::BOLDWAVE :
1131 0 : underline = "wavyHeavy";
1132 0 : break;
1133 : }
1134 :
1135 80 : if( GETA( CharLocale ) ) {
1136 80 : com::sun::star::lang::Locale aLocale;
1137 80 : mAny >>= aLocale;
1138 160 : LanguageTag aLanguageTag( aLocale);
1139 80 : if (!aLanguageTag.isSystemLocale())
1140 138 : usLanguage = aLanguageTag.getBcp47();
1141 : }
1142 :
1143 80 : if( GETAD( CharEscapement ) )
1144 28 : mAny >>= nCharEscapement;
1145 :
1146 80 : if( nCharEscapement && GETAD( CharEscapementHeight ) ) {
1147 1 : sal_uInt32 nCharEscapementHeight = 0;
1148 1 : mAny >>= nCharEscapementHeight;
1149 1 : nSize = (nSize * nCharEscapementHeight) / 100;
1150 : // MSO uses default ~58% size
1151 1 : nSize = (nSize / 0.58);
1152 : }
1153 :
1154 : mpFS->startElementNS( XML_a, XML_rPr,
1155 : XML_b, bold,
1156 : XML_i, italic,
1157 218 : XML_lang, usLanguage.isEmpty() ? NULL : USS( usLanguage ),
1158 147 : XML_sz, nSize == 1800 ? NULL : IS( nSize ),
1159 : XML_u, underline,
1160 162 : XML_baseline, nCharEscapement == 0 ? NULL : IS( nCharEscapement*1000 ),
1161 365 : FSEND );
1162 :
1163 : // mso doesn't like text color to be placed after typeface
1164 80 : if( GETAD( CharColor ) ) {
1165 28 : sal_uInt32 color = *((sal_uInt32*) mAny.getValue());
1166 : DBG(fprintf(stderr, "run color: %x auto: %x\n", static_cast<unsigned int>( color ), static_cast<unsigned int>( COL_AUTO )));
1167 :
1168 28 : if( color == COL_AUTO ) { // nCharColor depends to the background color
1169 0 : bool bIsDark = false;
1170 0 : GET( bIsDark, IsBackgroundDark );
1171 0 : color = bIsDark ? 0xffffff : 0x000000;
1172 : }
1173 28 : color &= 0xffffff;
1174 :
1175 : // TODO: special handle embossed/engraved
1176 :
1177 28 : WriteSolidFill( color );
1178 : }
1179 :
1180 80 : if( GETA( CharFontName ) ) {
1181 80 : const char* pitch = NULL;
1182 80 : const char* charset = NULL;
1183 80 : OUString usTypeface;
1184 :
1185 80 : mAny >>= usTypeface;
1186 160 : OUString aSubstName( GetSubsFontName( usTypeface, SUBSFONT_ONLYONE | SUBSFONT_MS ) );
1187 :
1188 : mpFS->singleElementNS( XML_a, XML_latin,
1189 80 : XML_typeface, USS(aSubstName.getLength() ? aSubstName : usTypeface),
1190 : XML_pitchFamily, pitch,
1191 : XML_charset, charset,
1192 160 : FSEND );
1193 : }
1194 :
1195 80 : if( ( bComplex && GETAD( CharFontNameComplex ) ) || ( !bComplex && GETAD( CharFontNameAsian ) ) ) {
1196 1 : const char* pitch = NULL;
1197 1 : const char* charset = NULL;
1198 1 : OUString usTypeface;
1199 :
1200 1 : mAny >>= usTypeface;
1201 2 : OUString aSubstName( GetSubsFontName( usTypeface, SUBSFONT_ONLYONE | SUBSFONT_MS ) );
1202 :
1203 : mpFS->singleElementNS( XML_a, bComplex ? XML_cs : XML_ea,
1204 1 : XML_typeface, USS(aSubstName.getLength() ? aSubstName : usTypeface),
1205 : XML_pitchFamily, pitch,
1206 : XML_charset, charset,
1207 2 : FSEND );
1208 : }
1209 :
1210 80 : if( bIsField ) {
1211 12 : Reference< XTextField > rXTextField;
1212 12 : GET( rXTextField, TextField );
1213 12 : if( rXTextField.is() )
1214 12 : rRun.set( rXTextField, UNO_QUERY );
1215 : }
1216 :
1217 : // field properties starts here
1218 80 : if( GETA( URL ) ) {
1219 0 : OUString sURL;
1220 :
1221 0 : mAny >>= sURL;
1222 0 : if( !sURL.isEmpty() ) {
1223 : OUString sRelId = mpFB->addRelation( mpFS->getOutputStream(),
1224 : "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink",
1225 0 : sURL, true );
1226 :
1227 : mpFS->singleElementNS( XML_a, XML_hlinkClick,
1228 : FSNS( XML_r,XML_id ), USS( sRelId ),
1229 0 : FSEND );
1230 0 : }
1231 : }
1232 :
1233 160 : mpFS->endElementNS( XML_a, XML_rPr );
1234 80 : }
1235 :
1236 58 : const char* DrawingML::GetFieldType( ::com::sun::star::uno::Reference< ::com::sun::star::text::XTextRange > rRun, bool& bIsField )
1237 : {
1238 58 : const char* sType = NULL;
1239 58 : Reference< XPropertySet > rXPropSet( rRun, UNO_QUERY );
1240 116 : OUString aFieldType;
1241 :
1242 58 : if( GETA( TextPortionType ) ) {
1243 58 : aFieldType = OUString( *(OUString*)mAny.getValue() );
1244 : DBG(fprintf (stderr, "field type: %s\n", USS(aFieldType) ));
1245 : }
1246 :
1247 58 : if( aFieldType == "TextField" ) {
1248 12 : Reference< XTextField > rXTextField;
1249 12 : GET( rXTextField, TextField );
1250 12 : if( rXTextField.is() ) {
1251 12 : bIsField = true;
1252 12 : rXPropSet.set( rXTextField, UNO_QUERY );
1253 12 : if( rXPropSet.is() ) {
1254 12 : OUString aFieldKind( rXTextField->getPresentation( true ) );
1255 : DBG(fprintf (stderr, "field kind: %s\n", USS(aFieldKind) ));
1256 12 : if( aFieldKind == "Page" ) {
1257 4 : return "slidenum";
1258 8 : }
1259 : // else if( aFieldKind == "URL" ) {
1260 : // do not return here
1261 : // and make URL field text run with hyperlink property later
1262 : // }
1263 : }
1264 8 : }
1265 : }
1266 :
1267 112 : return sType;
1268 : }
1269 :
1270 4 : void DrawingML::GetUUID( OStringBuffer& rBuffer )
1271 : {
1272 4 : Sequence< sal_uInt8 > aSeq( 16 );
1273 : static const char cDigits[17] = "0123456789ABCDEF";
1274 4 : rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, true );
1275 : int i;
1276 :
1277 4 : rBuffer.append( '{' );
1278 20 : for( i = 0; i < 4; i++ ) {
1279 16 : rBuffer.append( cDigits[ aSeq[i] >> 4 ] );
1280 16 : rBuffer.append( cDigits[ aSeq[i] & 0xf ] );
1281 : }
1282 4 : rBuffer.append( '-' );
1283 12 : for( ; i < 6; i++ ) {
1284 8 : rBuffer.append( cDigits[ aSeq[i] >> 4 ] );
1285 8 : rBuffer.append( cDigits[ aSeq[i] & 0xf ] );
1286 : }
1287 4 : rBuffer.append( '-' );
1288 12 : for( ; i < 8; i++ ) {
1289 8 : rBuffer.append( cDigits[ aSeq[i] >> 4 ] );
1290 8 : rBuffer.append( cDigits[ aSeq[i] & 0xf ] );
1291 : }
1292 4 : rBuffer.append( '-' );
1293 12 : for( ; i < 10; i++ ) {
1294 8 : rBuffer.append( cDigits[ aSeq[i] >> 4 ] );
1295 8 : rBuffer.append( cDigits[ aSeq[i] & 0xf ] );
1296 : }
1297 4 : rBuffer.append( '-' );
1298 28 : for( ; i < 16; i++ ) {
1299 24 : rBuffer.append( cDigits[ aSeq[i] >> 4 ] );
1300 24 : rBuffer.append( cDigits[ aSeq[i] & 0xf ] );
1301 : }
1302 4 : rBuffer.append( '}' );
1303 4 : }
1304 :
1305 189 : void DrawingML::WriteRun( Reference< XTextRange > rRun )
1306 : {
1307 : const char* sFieldType;
1308 189 : bool bIsField = false;
1309 189 : OUString sText = rRun->getString();
1310 :
1311 189 : if( sText.isEmpty()) {
1312 131 : Reference< XPropertySet > xPropSet( rRun, UNO_QUERY );
1313 :
1314 : try {
1315 262 : if( !xPropSet.is() || !( xPropSet->getPropertyValue( "PlaceholderText" ) >>= sText ) )
1316 0 : return;
1317 0 : if( sText.isEmpty() )
1318 0 : return;
1319 : }
1320 262 : catch (const Exception &) {
1321 131 : return;
1322 0 : }
1323 : }
1324 :
1325 58 : sFieldType = GetFieldType( rRun, bIsField );
1326 58 : if( ( sFieldType != NULL ) ) {
1327 4 : OStringBuffer sUUID(39);
1328 :
1329 4 : GetUUID( sUUID );
1330 : mpFS->startElementNS( XML_a, XML_fld,
1331 : XML_id, sUUID.getStr(),
1332 : XML_type, sFieldType,
1333 4 : FSEND );
1334 : } else
1335 54 : mpFS->startElementNS( XML_a, XML_r, FSEND );
1336 :
1337 116 : Reference< XPropertySet > xPropSet( rRun, uno::UNO_QUERY );
1338 58 : WriteRunProperties( xPropSet, bIsField );
1339 :
1340 58 : mpFS->startElementNS( XML_a, XML_t, FSEND );
1341 58 : mpFS->writeEscaped( sText );
1342 58 : mpFS->endElementNS( XML_a, XML_t );
1343 :
1344 58 : if( sFieldType )
1345 4 : mpFS->endElementNS( XML_a, XML_fld );
1346 : else
1347 112 : mpFS->endElementNS( XML_a, XML_r );
1348 : }
1349 :
1350 : #define AUTONUM(x) \
1351 : if( bPBoth ) \
1352 : pAutoNumType = #x "ParenBoth"; \
1353 : else if( bPBehind ) \
1354 : pAutoNumType = #x "ParenR"; \
1355 : else if( bSDot ) \
1356 : pAutoNumType = #x "Period";
1357 :
1358 32 : inline static const char* GetAutoNumType( sal_Int16 nNumberingType, bool bSDot, bool bPBehind, bool bPBoth )
1359 : {
1360 32 : const char* pAutoNumType = NULL;
1361 :
1362 32 : switch( (SvxExtNumType)nNumberingType )
1363 : {
1364 : case SVX_NUM_CHARS_UPPER_LETTER_N :
1365 : case SVX_NUM_CHARS_UPPER_LETTER :
1366 0 : AUTONUM( alphaUc );
1367 0 : break;
1368 : case SVX_NUM_CHARS_LOWER_LETTER_N :
1369 : case SVX_NUM_CHARS_LOWER_LETTER :
1370 0 : AUTONUM( alphaLc );
1371 0 : break;
1372 : case SVX_NUM_ROMAN_UPPER :
1373 0 : AUTONUM( romanUc );
1374 0 : break;
1375 : case SVX_NUM_ROMAN_LOWER :
1376 0 : AUTONUM( romanLc );
1377 0 : break;
1378 : case SVX_NUM_ARABIC :
1379 0 : AUTONUM( arabic )
1380 : else
1381 0 : pAutoNumType = "arabicPlain";
1382 0 : break;
1383 : default:
1384 32 : break;
1385 : }
1386 :
1387 32 : return pAutoNumType;
1388 : }
1389 :
1390 76 : void DrawingML::WriteParagraphNumbering( Reference< XPropertySet > rXPropSet, sal_Int16 nLevel )
1391 : {
1392 76 : if( nLevel >= 0 && GETA( NumberingRules ) )
1393 : {
1394 32 : Reference< XIndexAccess > rXIndexAccess;
1395 :
1396 32 : if ( ( mAny >>= rXIndexAccess ) && nLevel < rXIndexAccess->getCount() )
1397 : {
1398 : DBG(fprintf (stderr, "numbering rules\n"));
1399 :
1400 32 : Sequence< PropertyValue > aPropertySequence;
1401 32 : rXIndexAccess->getByIndex( nLevel ) >>= aPropertySequence;
1402 :
1403 32 : const PropertyValue* pPropValue = aPropertySequence.getArray();
1404 :
1405 32 : sal_Int32 nPropertyCount = aPropertySequence.getLength();
1406 :
1407 32 : if ( nPropertyCount ) {
1408 :
1409 32 : sal_Int16 nNumberingType = -1;
1410 32 : bool bSDot = false;
1411 32 : bool bPBehind = false;
1412 32 : bool bPBoth = false;
1413 32 : sal_Unicode aBulletChar = 0x2022; // a bullet
1414 32 : awt::FontDescriptor aFontDesc;
1415 32 : bool bHasFontDesc = false;
1416 64 : OUString aGraphicURL;
1417 32 : sal_Int16 nBulletRelSize = 0;
1418 :
1419 448 : for ( sal_Int32 i = 0; i < nPropertyCount; i++ ) {
1420 416 : const void* pValue = pPropValue[ i ].Value.getValue();
1421 416 : if ( pValue ) {
1422 416 : OUString aPropName( pPropValue[ i ].Name );
1423 : DBG(fprintf (stderr, "pro name: %s\n", OUStringToOString( aPropName, RTL_TEXTENCODING_UTF8 ).getStr()));
1424 416 : if ( aPropName == "NumberingType" )
1425 32 : nNumberingType = *( (sal_Int16*)pValue );
1426 384 : else if ( aPropName == "Prefix" ) {
1427 32 : if( *(OUString*)pValue == ")")
1428 0 : bPBoth = true;
1429 352 : } else if ( aPropName == "Suffix" ) {
1430 32 : if( *(OUString*)pValue == ".")
1431 0 : bSDot = true;
1432 32 : else if( *(OUString*)pValue == ")")
1433 0 : bPBehind = true;
1434 320 : } else if ( aPropName == "BulletChar" )
1435 : {
1436 32 : aBulletChar = OUString ( *( (OUString*)pValue ) )[ 0 ];
1437 : //printf ("bullet char: %d\n", aBulletChar.getStr());
1438 : }
1439 288 : else if ( aPropName == "BulletFont" )
1440 : {
1441 32 : aFontDesc = *( (awt::FontDescriptor*)pValue );
1442 32 : bHasFontDesc = true;
1443 :
1444 : // Our numbullet dialog has set the wrong textencoding for our "StarSymbol" font,
1445 : // instead of a Unicode encoding the encoding RTL_TEXTENCODING_SYMBOL was used.
1446 : // Because there might exist a lot of damaged documemts I added this two lines
1447 : // which fixes the bullet problem for the export.
1448 32 : if ( aFontDesc.Name.equalsIgnoreAsciiCase("StarSymbol") )
1449 25 : aFontDesc.CharSet = RTL_TEXTENCODING_MS_1252;
1450 :
1451 256 : } else if ( aPropName == "BulletRelSize" ) {
1452 32 : nBulletRelSize = *( (sal_Int16*)pValue );
1453 224 : } else if ( aPropName == "GraphicURL" ) {
1454 0 : aGraphicURL = ( *(OUString*)pValue );
1455 : DBG(fprintf (stderr, "graphic url: %s\n", OUStringToOString( aGraphicURL, RTL_TEXTENCODING_UTF8 ).getStr()));
1456 224 : } else if ( aPropName == "GraphicSize" )
1457 : {
1458 32 : if ( pPropValue[ i ].Value.getValueType() == ::getCppuType( (awt::Size*)0) )
1459 : {
1460 : // don't cast awt::Size to Size as on 64-bits they are not the same.
1461 32 : ::com::sun::star::awt::Size aSize;
1462 32 : pPropValue[ i ].Value >>= aSize;
1463 : //aBuGraSize.nA = aSize.Width;
1464 : //aBuGraSize.nB = aSize.Height;
1465 : DBG(fprintf(stderr, "graphic size: %dx%d\n", int( aSize.Width ), int( aSize.Height )));
1466 : }
1467 416 : }
1468 : }
1469 : }
1470 :
1471 32 : const char* pAutoNumType = GetAutoNumType( nNumberingType, bSDot, bPBehind, bPBoth );
1472 :
1473 32 : if( nLevel >= 0 ) {
1474 32 : if( !aGraphicURL.isEmpty() ) {
1475 0 : OUString sRelId = WriteImage( aGraphicURL );
1476 :
1477 0 : mpFS->startElementNS( XML_a, XML_buBlip, FSEND );
1478 0 : mpFS->singleElementNS( XML_a, XML_blip, FSNS( XML_r, XML_embed ), USS( sRelId ), FSEND );
1479 0 : mpFS->endElementNS( XML_a, XML_buBlip );
1480 : } else {
1481 32 : if( nBulletRelSize && nBulletRelSize != 100 )
1482 : mpFS->singleElementNS( XML_a, XML_buSzPct,
1483 32 : XML_val, IS( std::max( (sal_Int32)25000, std::min( (sal_Int32)400000, 1000*( (sal_Int32)nBulletRelSize ) ) ) ), FSEND );
1484 32 : if( bHasFontDesc )
1485 : mpFS->singleElementNS( XML_a, XML_buFont,
1486 : XML_typeface, OUStringToOString( aFontDesc.Name, RTL_TEXTENCODING_UTF8 ).getStr(),
1487 32 : XML_charset, (aFontDesc.CharSet == awt::CharSet::SYMBOL) ? "2" : NULL,
1488 32 : FSEND );
1489 :
1490 32 : if( pAutoNumType )
1491 0 : mpFS->singleElementNS( XML_a, XML_buAutoNum, XML_type, pAutoNumType, FSEND );
1492 : else {
1493 32 : aBulletChar = SubstituteBullet( aBulletChar, aFontDesc );
1494 32 : mpFS->singleElementNS( XML_a, XML_buChar, XML_char, USS( OUString( aBulletChar ) ), FSEND );
1495 : }
1496 : }
1497 32 : }
1498 32 : }
1499 32 : }
1500 : }
1501 76 : }
1502 :
1503 76 : const char* DrawingML::GetAlignment( sal_Int32 nAlignment )
1504 : {
1505 76 : const char* sAlignment = NULL;
1506 :
1507 76 : switch( nAlignment ) {
1508 : case style::ParagraphAdjust_CENTER:
1509 37 : sAlignment = "ctr";
1510 37 : break;
1511 : case style::ParagraphAdjust_RIGHT:
1512 5 : sAlignment = "r";
1513 5 : break;
1514 : case style::ParagraphAdjust_BLOCK:
1515 0 : sAlignment = "just";
1516 0 : break;
1517 : default:
1518 : ;
1519 : }
1520 :
1521 76 : return sAlignment;
1522 : }
1523 :
1524 4 : void DrawingML::WriteLinespacing( LineSpacing& rSpacing )
1525 : {
1526 4 : if( rSpacing.Mode == LineSpacingMode::PROP )
1527 : mpFS->singleElementNS( XML_a, XML_spcPct,
1528 : XML_val, I32S( ((sal_Int32)rSpacing.Height)*1000 ),
1529 4 : FSEND );
1530 : else
1531 : mpFS->singleElementNS( XML_a, XML_spcPts,
1532 : XML_val, I32S( rSpacing.Height ),
1533 0 : FSEND );
1534 4 : }
1535 :
1536 185 : void DrawingML::WriteParagraphProperties( Reference< XTextContent > rParagraph )
1537 : {
1538 185 : Reference< XPropertySet > rXPropSet( rParagraph, UNO_QUERY );
1539 370 : Reference< XPropertyState > rXPropState( rParagraph, UNO_QUERY );
1540 : PropertyState eState;
1541 :
1542 185 : if( !rXPropSet.is() || !rXPropState.is() )
1543 185 : return;
1544 :
1545 185 : sal_Int16 nLevel = -1;
1546 185 : GET( nLevel, NumberingLevel );
1547 :
1548 185 : sal_Int16 nAlignment( style::ParagraphAdjust_LEFT );
1549 185 : GET( nAlignment, ParaAdjust );
1550 :
1551 185 : bool bHasLinespacing = false;
1552 185 : LineSpacing aLineSpacing;
1553 185 : if( GETAD( ParaLineSpacing ) )
1554 4 : bHasLinespacing = ( mAny >>= aLineSpacing );
1555 :
1556 185 : if( nLevel != -1
1557 153 : || nAlignment != style::ParagraphAdjust_LEFT
1558 111 : || bHasLinespacing ) {
1559 : mpFS->startElementNS( XML_a, XML_pPr,
1560 206 : XML_lvl, nLevel > 0 ? I32S( nLevel ) : NULL,
1561 : XML_marL, NULL,
1562 : XML_algn, GetAlignment( nAlignment ),
1563 228 : FSEND );
1564 :
1565 76 : if( bHasLinespacing ) {
1566 4 : mpFS->startElementNS( XML_a, XML_lnSpc, FSEND );
1567 4 : WriteLinespacing( aLineSpacing );
1568 4 : mpFS->endElementNS( XML_a, XML_lnSpc );
1569 : }
1570 :
1571 76 : WriteParagraphNumbering( rXPropSet, nLevel );
1572 :
1573 76 : mpFS->endElementNS( XML_a, XML_pPr );
1574 185 : }
1575 : }
1576 :
1577 185 : void DrawingML::WriteParagraph( Reference< XTextContent > rParagraph )
1578 : {
1579 185 : Reference< XEnumerationAccess > access( rParagraph, UNO_QUERY );
1580 185 : if( !access.is() )
1581 0 : return;
1582 :
1583 370 : Reference< XEnumeration > enumeration( access->createEnumeration() );
1584 185 : if( !enumeration.is() )
1585 0 : return;
1586 :
1587 185 : mpFS->startElementNS( XML_a, XML_p, FSEND );
1588 :
1589 185 : bool bPropertiesWritten = false;
1590 559 : while( enumeration->hasMoreElements() ) {
1591 189 : Reference< XTextRange > run;
1592 378 : Any any ( enumeration->nextElement() );
1593 :
1594 189 : if (any >>= run) {
1595 189 : if( !bPropertiesWritten ) {
1596 185 : WriteParagraphProperties( rParagraph );
1597 185 : bPropertiesWritten = true;
1598 : }
1599 189 : WriteRun( run );
1600 : }
1601 189 : }
1602 185 : mpFS->singleElementNS( XML_a, XML_endParaRPr, FSEND );
1603 :
1604 370 : mpFS->endElementNS( XML_a, XML_p );
1605 : }
1606 :
1607 352 : void DrawingML::WriteText( Reference< XInterface > rXIface, bool bBodyPr, bool bText, sal_Int32 nXmlNamespace )
1608 : {
1609 352 : Reference< XText > xXText( rXIface, UNO_QUERY );
1610 510 : Reference< XPropertySet > rXPropSet( rXIface, UNO_QUERY );
1611 :
1612 352 : if( !xXText.is() )
1613 0 : return;
1614 :
1615 : #define DEFLRINS 254
1616 : #define DEFTBINS 127
1617 : sal_Int32 nLeft, nRight, nTop, nBottom;
1618 352 : nLeft = nRight = DEFLRINS;
1619 352 : nTop = nBottom = DEFTBINS;
1620 :
1621 : // top inset looks a bit different compared to ppt export
1622 : // check if something related doesn't work as expected
1623 352 : GET( nLeft, TextLeftDistance );
1624 352 : GET( nRight, TextRightDistance );
1625 352 : GET( nTop, TextUpperDistance );
1626 352 : GET( nBottom, TextLowerDistance );
1627 :
1628 352 : TextVerticalAdjust eVerticalAlignment( TextVerticalAdjust_TOP );
1629 352 : const char* sVerticalAlignment = NULL;
1630 352 : GET( eVerticalAlignment, TextVerticalAdjust );
1631 352 : if( eVerticalAlignment != TextVerticalAdjust_TOP )
1632 72 : sVerticalAlignment = GetTextVerticalAdjust(eVerticalAlignment);
1633 :
1634 352 : const char* sWritingMode = NULL;
1635 352 : bool bVertical = false;
1636 352 : if( GETA( TextWritingMode ) ) {
1637 : WritingMode eMode;
1638 :
1639 352 : if( ( mAny >>= eMode ) && eMode == WritingMode_TB_RL ) {
1640 0 : sWritingMode = "vert";
1641 0 : bVertical = true;
1642 : }
1643 : }
1644 :
1645 352 : if ( GETA( CustomShapeGeometry ) )
1646 : {
1647 34 : Sequence< PropertyValue > aProps;
1648 34 : if ( mAny >>= aProps )
1649 : {
1650 252 : for ( sal_Int32 i = 0, nElems = aProps.getLength(); i < nElems; ++i )
1651 : {
1652 242 : sal_Int32 nTextRotateAngle = 0;
1653 242 : if ( aProps[ i ].Name.equals( "TextPreRotateAngle" ) && ( aProps[ i ].Value >>= nTextRotateAngle ) )
1654 : {
1655 24 : if ( nTextRotateAngle == -90 )
1656 : {
1657 0 : sWritingMode = "vert";
1658 0 : bVertical = true;
1659 : }
1660 24 : break;
1661 : }
1662 : }
1663 34 : }
1664 : }
1665 :
1666 352 : TextHorizontalAdjust eHorizontalAlignment( TextHorizontalAdjust_CENTER );
1667 352 : bool bHorizontalCenter = false;
1668 352 : GET( eHorizontalAlignment, TextHorizontalAdjust );
1669 352 : if( eHorizontalAlignment == TextHorizontalAdjust_CENTER )
1670 2 : bHorizontalCenter = true;
1671 350 : else if( bVertical && eHorizontalAlignment == TextHorizontalAdjust_LEFT )
1672 0 : sVerticalAlignment = "b";
1673 :
1674 352 : bool bHasWrap = false;
1675 352 : bool bWrap = false;
1676 : // Only custom shapes obey the TextWordWrap option, normal text always wraps.
1677 352 : if( dynamic_cast<SvxCustomShape*>(rXIface.get()) && GETA( TextWordWrap ) ) {
1678 2 : mAny >>= bWrap;
1679 2 : bHasWrap = true;
1680 : }
1681 :
1682 352 : if (bBodyPr)
1683 : {
1684 255 : const char* pWrap = bHasWrap && !bWrap ? "none" : NULL;
1685 255 : if (GetDocumentType() == DOCUMENT_DOCX)
1686 : {
1687 : // In case of DOCX, if we want to have the same effect as
1688 : // TextShape's automatic word wrapping, then we need to set
1689 : // wrapping to square.
1690 97 : uno::Reference<lang::XServiceInfo> xServiceInfo(rXIface, uno::UNO_QUERY);
1691 97 : if (xServiceInfo.is() && xServiceInfo->supportsService("com.sun.star.drawing.TextShape"))
1692 80 : pWrap = "square";
1693 : }
1694 : mpFS->singleElementNS( (nXmlNamespace ? nXmlNamespace : XML_a), XML_bodyPr,
1695 : XML_wrap, pWrap,
1696 733 : XML_lIns, (nLeft != DEFLRINS) ? IS( MM100toEMU( nLeft ) ) : NULL,
1697 732 : XML_rIns, (nRight != DEFLRINS) ? IS( MM100toEMU( nRight ) ) : NULL,
1698 732 : XML_tIns, (nTop != DEFTBINS) ? IS( MM100toEMU( nTop ) ) : NULL,
1699 954 : XML_bIns, (nBottom != DEFTBINS) ? IS( MM100toEMU( nBottom ) ) : NULL,
1700 : XML_anchor, sVerticalAlignment,
1701 : XML_anchorCtr, bHorizontalCenter ? "1" : NULL,
1702 : XML_vert, sWritingMode,
1703 2197 : FSEND );
1704 : }
1705 :
1706 510 : Reference< XEnumerationAccess > access( xXText, UNO_QUERY );
1707 352 : if( !access.is() || !bText )
1708 97 : return;
1709 :
1710 413 : Reference< XEnumeration > enumeration( access->createEnumeration() );
1711 255 : if( !enumeration.is() )
1712 0 : return;
1713 :
1714 255 : SdrObject* pSdrObject = GetSdrObjectFromXShape(uno::Reference<drawing::XShape>(rXIface, uno::UNO_QUERY_THROW));
1715 255 : const SdrTextObj* pTxtObj = PTR_CAST(SdrTextObj, pSdrObject);
1716 255 : if (pTxtObj && mpTextExport)
1717 : {
1718 97 : const OutlinerParaObject* pParaObj = 0;
1719 97 : bool bOwnParaObj = false;
1720 :
1721 : /*
1722 : #i13885#
1723 : When the object is actively being edited, that text is not set into
1724 : the objects normal text object, but lives in a separate object.
1725 : */
1726 97 : if (pTxtObj->IsTextEditActive())
1727 : {
1728 0 : pParaObj = pTxtObj->GetEditOutlinerParaObject();
1729 0 : bOwnParaObj = true;
1730 : }
1731 : else
1732 97 : pParaObj = pTxtObj->GetOutlinerParaObject();
1733 :
1734 97 : if (pParaObj)
1735 : {
1736 : // this is reached only in case some text is attached to the shape
1737 97 : mpTextExport->WriteOutliner(*pParaObj);
1738 97 : if (bOwnParaObj)
1739 0 : delete pParaObj;
1740 : }
1741 97 : return;
1742 : }
1743 :
1744 501 : while( enumeration->hasMoreElements() ) {
1745 185 : Reference< XTextContent > paragraph;
1746 370 : Any any ( enumeration->nextElement() );
1747 :
1748 185 : if( any >>= paragraph)
1749 185 : WriteParagraph( paragraph );
1750 343 : }
1751 :
1752 : }
1753 :
1754 296 : void DrawingML::WritePresetShape( const char* pShape )
1755 : {
1756 : mpFS->startElementNS( XML_a, XML_prstGeom,
1757 : XML_prst, pShape,
1758 296 : FSEND );
1759 296 : mpFS->singleElementNS( XML_a, XML_avLst, FSEND );
1760 296 : mpFS->endElementNS( XML_a, XML_prstGeom );
1761 296 : }
1762 :
1763 139 : void DrawingML::WritePresetShape( const char* pShape, MSO_SPT eShapeType, bool bPredefinedHandlesUsed, sal_Int32 nAdjustmentsWhichNeedsToBeConverted, const PropertyValue& rProp )
1764 : {
1765 139 : static std::map< OString, std::vector<OString> > aAdjMap = ooxDrawingMLGetAdjNames();
1766 : // If there are predefined adj names for this shape type, look them up now.
1767 139 : std::vector<OString> aAdjustments;
1768 139 : if (aAdjMap.find(OString(pShape)) != aAdjMap.end())
1769 26 : aAdjustments = aAdjMap[OString(pShape)];
1770 :
1771 : mpFS->startElementNS( XML_a, XML_prstGeom,
1772 : XML_prst, pShape,
1773 139 : FSEND );
1774 139 : mpFS->startElementNS( XML_a, XML_avLst, FSEND );
1775 :
1776 278 : Sequence< drawing::EnhancedCustomShapeAdjustmentValue > aAdjustmentSeq;
1777 417 : if ( ( rProp.Value >>= aAdjustmentSeq )
1778 139 : && eShapeType != mso_sptActionButtonForwardNext // we have adjustments values for these type of shape, but MSO doesn't like them
1779 139 : && eShapeType != mso_sptActionButtonBackPrevious // so they are now disabled
1780 695 : && OString(pShape) != "rect" //some shape types are commented out in pCustomShapeTypeTranslationTable[] & are being defaulted to rect & rect does not have adjustment values/name.
1781 : ) {
1782 : DBG(fprintf(stderr, "adj seq len: %d\n", int( aAdjustmentSeq.getLength() )));
1783 78 : if ( bPredefinedHandlesUsed )
1784 60 : EscherPropertyContainer::LookForPolarHandles( eShapeType, nAdjustmentsWhichNeedsToBeConverted );
1785 :
1786 78 : sal_Int32 nValue, nLength = aAdjustmentSeq.getLength();
1787 : //aAdjustments will give info about the number of adj values for a particular geomtery.For example for hexagon aAdjustments.size() will be 2 and for circular arrow it will be 5 as per ooxDrawingMLGetAdjNames.
1788 78 : if(aAdjustments.size() == static_cast<sal_uInt32>(nLength))// In case there is a mismatch do not write the XML_gd tag.
1789 : {
1790 121 : for( sal_Int32 i=0; i < nLength; i++ )
1791 44 : if( EscherPropertyContainer::GetAdjustmentValue( aAdjustmentSeq[ i ], i, nAdjustmentsWhichNeedsToBeConverted, nValue ) )
1792 : {
1793 : // If the document model doesn't have an adjustment name (e.g. shape was created from VML), then take it from the predefined list.
1794 44 : OString aAdjName;
1795 44 : if (aAdjustmentSeq[i].Name.isEmpty() && static_cast<sal_uInt32>(i) < aAdjustments.size())
1796 13 : aAdjName = aAdjustments[i];
1797 :
1798 : mpFS->singleElementNS( XML_a, XML_gd,
1799 119 : XML_name, aAdjustmentSeq[ i ].Name.getLength() > 0 ? USS(aAdjustmentSeq[ i ].Name) : aAdjName.getStr(),
1800 88 : XML_fmla, OString("val " + OString::number( nValue )).getStr(),
1801 207 : FSEND );
1802 : }
1803 : }
1804 : }
1805 :
1806 139 : mpFS->endElementNS( XML_a, XML_avLst );
1807 278 : mpFS->endElementNS( XML_a, XML_prstGeom );
1808 139 : }
1809 :
1810 65 : void DrawingML::WritePolyPolygon( const PolyPolygon& rPolyPolygon )
1811 : {
1812 65 : if( rPolyPolygon.Count() < 1 )
1813 65 : return;
1814 :
1815 65 : mpFS->startElementNS( XML_a, XML_custGeom, FSEND );
1816 65 : mpFS->singleElementNS( XML_a, XML_avLst, FSEND );
1817 65 : mpFS->singleElementNS( XML_a, XML_gdLst, FSEND );
1818 65 : mpFS->singleElementNS( XML_a, XML_ahLst, FSEND );
1819 : mpFS->singleElementNS( XML_a, XML_rect,
1820 : XML_l, "0",
1821 : XML_t, "0",
1822 : XML_r, "r",
1823 : XML_b, "b",
1824 65 : FSEND );
1825 :
1826 65 : mpFS->startElementNS( XML_a, XML_pathLst, FSEND );
1827 :
1828 168 : for( sal_uInt16 i = 0; i < rPolyPolygon.Count(); i ++ ) {
1829 :
1830 103 : const Polygon& rPoly = rPolyPolygon[ i ];
1831 103 : Rectangle aRect( rPoly.GetBoundRect() );
1832 :
1833 : mpFS->startElementNS( XML_a, XML_path,
1834 103 : XML_w, I64S( aRect.GetWidth() ),
1835 103 : XML_h, I64S( aRect.GetHeight() ),
1836 206 : FSEND );
1837 :
1838 103 : if( rPoly.GetSize() > 0 )
1839 : {
1840 103 : mpFS->startElementNS( XML_a, XML_moveTo, FSEND );
1841 :
1842 : mpFS->singleElementNS( XML_a, XML_pt,
1843 206 : XML_x, I64S( rPoly[ 0 ].X() - aRect.Left() ),
1844 206 : XML_y, I64S( rPoly[ 0 ].Y() - aRect.Top() ),
1845 412 : FSEND );
1846 :
1847 103 : mpFS->endElementNS( XML_a, XML_moveTo );
1848 : }
1849 :
1850 1016 : for( sal_uInt16 j = 1; j < rPoly.GetSize(); j ++ )
1851 : {
1852 913 : enum PolyFlags flags = rPoly.GetFlags(j);
1853 913 : if( flags == POLY_CONTROL )
1854 : {
1855 : // a:cubicBezTo can only contain 3 a:pt elements, so we need to make sure of this
1856 203 : if( j+2 < rPoly.GetSize() && rPoly.GetFlags(j+1) == POLY_CONTROL && rPoly.GetFlags(j+2) != POLY_CONTROL )
1857 : {
1858 :
1859 203 : mpFS->startElementNS( XML_a, XML_cubicBezTo, FSEND );
1860 812 : for( sal_uInt8 k = 0; k <= 2; ++k )
1861 : {
1862 : mpFS->singleElementNS( XML_a, XML_pt,
1863 1218 : XML_x, I64S( rPoly[j+k].X() - aRect.Left() ),
1864 1218 : XML_y, I64S( rPoly[j+k].Y() - aRect.Top() ),
1865 2436 : FSEND );
1866 :
1867 : }
1868 203 : mpFS->endElementNS( XML_a, XML_cubicBezTo );
1869 203 : j += 2;
1870 : }
1871 : }
1872 710 : else if( flags == POLY_NORMAL )
1873 : {
1874 710 : mpFS->startElementNS( XML_a, XML_lnTo, FSEND );
1875 : mpFS->singleElementNS( XML_a, XML_pt,
1876 1420 : XML_x, I64S( rPoly[j].X() - aRect.Left() ),
1877 1420 : XML_y, I64S( rPoly[j].Y() - aRect.Top() ),
1878 2840 : FSEND );
1879 710 : mpFS->endElementNS( XML_a, XML_lnTo );
1880 : }
1881 : }
1882 :
1883 103 : mpFS->endElementNS( XML_a, XML_path );
1884 : }
1885 :
1886 65 : mpFS->endElementNS( XML_a, XML_pathLst );
1887 :
1888 65 : mpFS->endElementNS( XML_a, XML_custGeom );
1889 : }
1890 :
1891 0 : void DrawingML::WriteConnectorConnections( EscherConnectorListEntry& rConnectorEntry, sal_Int32 nStartID, sal_Int32 nEndID )
1892 : {
1893 0 : if( nStartID != -1 )
1894 : mpFS->singleElementNS( XML_a, XML_stCxn,
1895 : XML_id, I32S( nStartID ),
1896 0 : XML_idx, I64S( rConnectorEntry.GetConnectorRule( true ) ),
1897 0 : FSEND );
1898 0 : if( nEndID != -1 )
1899 : mpFS->singleElementNS( XML_a, XML_endCxn,
1900 : XML_id, I32S( nEndID ),
1901 0 : XML_idx, I64S( rConnectorEntry.GetConnectorRule( false ) ),
1902 0 : FSEND );
1903 0 : }
1904 :
1905 32 : sal_Unicode DrawingML::SubstituteBullet( sal_Unicode cBulletId, ::com::sun::star::awt::FontDescriptor& rFontDesc )
1906 : {
1907 32 : if ( IsStarSymbol(rFontDesc.Name) )
1908 : {
1909 25 : rtl_TextEncoding eCharSet = rFontDesc.CharSet;
1910 25 : cBulletId = msfilter::util::bestFitOpenSymbolToMSFont(cBulletId, eCharSet, rFontDesc.Name);
1911 25 : rFontDesc.CharSet = eCharSet;
1912 : }
1913 :
1914 32 : return cBulletId;
1915 : }
1916 :
1917 6 : sax_fastparser::FSHelperPtr DrawingML::CreateOutputStream (
1918 : const OUString& sFullStream,
1919 : const OUString& sRelativeStream,
1920 : const Reference< XOutputStream >& xParentRelation,
1921 : const char* sContentType,
1922 : const char* sRelationshipType,
1923 : OUString* pRelationshipId )
1924 : {
1925 6 : OUString sRelationshipId;
1926 6 : if (xParentRelation.is())
1927 6 : sRelationshipId = GetFB()->addRelation( xParentRelation, OUString::createFromAscii( sRelationshipType), sRelativeStream );
1928 : else
1929 0 : sRelationshipId = GetFB()->addRelation( OUString::createFromAscii( sRelationshipType ), sRelativeStream );
1930 :
1931 6 : if( pRelationshipId )
1932 6 : *pRelationshipId = sRelationshipId;
1933 :
1934 6 : sax_fastparser::FSHelperPtr p = GetFB()->openFragmentStreamWithSerializer( sFullStream, OUString::createFromAscii( sContentType ) );
1935 :
1936 6 : return p;
1937 : }
1938 :
1939 578 : void DrawingML::WriteFill( Reference< XPropertySet > xPropSet )
1940 : {
1941 578 : if ( !GetProperty( xPropSet, "FillStyle" ) )
1942 82 : return;
1943 496 : FillStyle aFillStyle( FillStyle_NONE );
1944 496 : xPropSet->getPropertyValue( "FillStyle" ) >>= aFillStyle;
1945 :
1946 496 : if ( aFillStyle == FillStyle_SOLID && GetProperty( xPropSet, "FillTransparence" ) )
1947 : {
1948 : // map full transparent background to no fill
1949 261 : sal_Int16 nVal = 0;
1950 261 : xPropSet->getPropertyValue( "FillTransparence" ) >>= nVal;
1951 261 : if ( nVal == 100 )
1952 0 : aFillStyle = FillStyle_NONE;
1953 : }
1954 :
1955 496 : switch( aFillStyle )
1956 : {
1957 : case FillStyle_SOLID :
1958 262 : WriteSolidFill( xPropSet );
1959 262 : break;
1960 : case FillStyle_GRADIENT :
1961 4 : WriteGradientFill( xPropSet );
1962 4 : break;
1963 : case FillStyle_BITMAP :
1964 2 : WriteBlipFill( xPropSet, "FillBitmapURL" );
1965 2 : break;
1966 : case FillStyle_HATCH :
1967 14 : WritePattFill( xPropSet );
1968 14 : break;
1969 : case FillStyle_NONE:
1970 214 : mpFS->singleElementNS( XML_a, XML_noFill, FSEND );
1971 214 : break;
1972 : default:
1973 : ;
1974 : }
1975 :
1976 496 : return;
1977 : }
1978 :
1979 489 : void DrawingML::WriteStyleProperties( sal_Int32 nTokenId, Sequence< PropertyValue > aProperties )
1980 : {
1981 489 : if( aProperties.getLength() > 0 )
1982 : {
1983 141 : OUString sSchemeClr;
1984 141 : sal_uInt32 nIdx = 0;
1985 282 : Sequence< PropertyValue > aTransformations;
1986 815 : for( sal_Int32 i=0; i < aProperties.getLength(); ++i)
1987 674 : if( aProperties[i].Name == "SchemeClr" )
1988 141 : aProperties[i].Value >>= sSchemeClr;
1989 533 : else if( aProperties[i].Name == "Idx" )
1990 141 : aProperties[i].Value >>= nIdx;
1991 392 : else if( aProperties[i].Name == "Transformations" )
1992 141 : aProperties[i].Value >>= aTransformations;
1993 141 : mpFS->startElementNS( XML_a, nTokenId, XML_idx, I32S( nIdx ), FSEND );
1994 141 : WriteColor( sSchemeClr, aTransformations );
1995 282 : mpFS->endElementNS( XML_a, nTokenId );
1996 : }
1997 : else
1998 : // write mock <a:*Ref> tag
1999 348 : mpFS->singleElementNS( XML_a, nTokenId, XML_idx, I32S( 0 ), FSEND );
2000 489 : }
2001 :
2002 163 : void DrawingML::WriteShapeStyle( Reference< XPropertySet > xPropSet )
2003 : {
2004 : // check existence of the grab bag
2005 163 : if ( !GetProperty( xPropSet, "InteropGrabBag" ) )
2006 163 : return;
2007 :
2008 : // extract the relevant properties from the grab bag
2009 163 : Sequence< PropertyValue > aGrabBag;
2010 326 : Sequence< PropertyValue > aFillRefProperties, aLnRefProperties, aEffectRefProperties;
2011 163 : mAny >>= aGrabBag;
2012 699 : for( sal_Int32 i=0; i < aGrabBag.getLength(); ++i)
2013 536 : if( aGrabBag[i].Name == "StyleFillRef" )
2014 31 : aGrabBag[i].Value >>= aFillRefProperties;
2015 505 : else if( aGrabBag[i].Name == "StyleLnRef" )
2016 55 : aGrabBag[i].Value >>= aLnRefProperties;
2017 450 : else if( aGrabBag[i].Name == "StyleEffectRef" )
2018 55 : aGrabBag[i].Value >>= aEffectRefProperties;
2019 :
2020 163 : WriteStyleProperties( XML_lnRef, aLnRefProperties );
2021 163 : WriteStyleProperties( XML_fillRef, aFillRefProperties );
2022 163 : WriteStyleProperties( XML_effectRef, aEffectRefProperties );
2023 :
2024 : // write mock <a:fontRef>
2025 326 : mpFS->singleElementNS( XML_a, XML_fontRef, XML_idx, "minor", FSEND );
2026 : }
2027 :
2028 : }
2029 177 : }
2030 :
2031 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|