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 0 : void DrawingML::ResetCounters()
123 : {
124 0 : mnImageCounter = 1;
125 0 : }
126 :
127 0 : bool DrawingML::GetProperty( Reference< XPropertySet > rXPropSet, const OUString& aName )
128 : {
129 0 : bool bRetValue = false;
130 :
131 : try {
132 0 : mAny = rXPropSet->getPropertyValue( aName );
133 0 : if ( mAny.hasValue() )
134 0 : bRetValue = true;
135 0 : } catch( const Exception& ) { /* printf ("exception when trying to get value of property: %s\n", USS(aName)); */ }
136 :
137 0 : return bRetValue;
138 : }
139 :
140 0 : bool DrawingML::GetPropertyAndState( Reference< XPropertySet > rXPropSet, Reference< XPropertyState > rXPropState, const OUString& aName, PropertyState& eState )
141 : {
142 0 : bool bRetValue = false;
143 :
144 : try {
145 0 : mAny = rXPropSet->getPropertyValue( aName );
146 0 : if ( mAny.hasValue() ) {
147 0 : bRetValue = true;
148 0 : 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 0 : return bRetValue;
153 : }
154 :
155 0 : void DrawingML::WriteColor( sal_uInt32 nColor, sal_Int32 nAlpha )
156 : {
157 0 : OString sColor = OString::number( nColor, 16 );
158 0 : if( sColor.getLength() < 6 ) {
159 0 : OStringBuffer sBuf( "0" );
160 0 : int remains = 5 - sColor.getLength();
161 :
162 0 : while( remains > 0 ) {
163 0 : sBuf.append( "0" );
164 0 : remains--;
165 : }
166 :
167 0 : sBuf.append( sColor );
168 :
169 0 : sColor = sBuf.getStr();
170 : }
171 0 : if( nAlpha < MAX_PERCENT )
172 : {
173 0 : mpFS->startElementNS( XML_a, XML_srgbClr, XML_val, sColor.getStr(), FSEND );
174 0 : mpFS->singleElementNS( XML_a, XML_alpha, XML_val, OString::number(nAlpha), FSEND );
175 0 : mpFS->endElementNS( XML_a, XML_srgbClr );
176 :
177 : }
178 : else
179 : {
180 0 : mpFS->singleElementNS( XML_a, XML_srgbClr, XML_val, sColor.getStr(), FSEND );
181 0 : }
182 0 : }
183 :
184 0 : void DrawingML::WriteColor( const OUString& sColorSchemeName, Sequence< PropertyValue > aTransformations )
185 : {
186 : // prevent writing a tag with empty val attribute
187 0 : if( sColorSchemeName.isEmpty() )
188 0 : return;
189 :
190 0 : if( aTransformations.hasElements() )
191 : {
192 : mpFS->startElementNS( XML_a, XML_schemeClr,
193 : XML_val, USS( sColorSchemeName ),
194 0 : FSEND );
195 0 : WriteColorTransformations( aTransformations );
196 0 : mpFS->endElementNS( XML_a, XML_schemeClr );
197 : }
198 : else
199 : mpFS->singleElementNS( XML_a, XML_schemeClr,
200 : XML_val, USS( sColorSchemeName ),
201 0 : FSEND );
202 : }
203 :
204 0 : void DrawingML::WriteColorTransformations( Sequence< PropertyValue > aTransformations )
205 : {
206 0 : for( sal_Int32 i = 0; i < aTransformations.getLength(); i++ )
207 : {
208 0 : sal_Int32 nToken = Color::getColorTransformationToken( aTransformations[i].Name );
209 0 : if( nToken != XML_TOKEN_INVALID && aTransformations[i].Value.hasValue() )
210 : {
211 0 : sal_Int32 nValue = aTransformations[i].Value.get<sal_Int32>();
212 0 : mpFS->singleElementNS( XML_a, nToken, XML_val, I32S( nValue ), FSEND );
213 : }
214 : }
215 0 : }
216 :
217 0 : void DrawingML::WriteSolidFill( sal_uInt32 nColor, sal_Int32 nAlpha )
218 : {
219 0 : mpFS->startElementNS( XML_a, XML_solidFill, FSEND );
220 0 : WriteColor( nColor, nAlpha );
221 0 : mpFS->endElementNS( XML_a, XML_solidFill );
222 0 : }
223 :
224 0 : void DrawingML::WriteSolidFill( const OUString& sSchemeName, Sequence< PropertyValue > aTransformations )
225 : {
226 0 : mpFS->startElementNS( XML_a, XML_solidFill, FSEND );
227 0 : WriteColor( sSchemeName, aTransformations );
228 0 : mpFS->endElementNS( XML_a, XML_solidFill );
229 0 : }
230 :
231 0 : void DrawingML::WriteSolidFill( Reference< XPropertySet > rXPropSet )
232 : {
233 : // get fill color
234 0 : if ( !GetProperty( rXPropSet, "FillColor" ) )
235 0 : return;
236 0 : sal_uInt32 nFillColor = mAny.get<sal_uInt32>();
237 :
238 : // get InteropGrabBag and search the relevant attributes
239 0 : OUString sColorFillScheme;
240 0 : sal_uInt32 nOriginalColor = 0;
241 0 : Sequence< PropertyValue > aStyleProperties, aTransformations;
242 0 : if ( GetProperty( rXPropSet, "InteropGrabBag" ) )
243 : {
244 0 : Sequence< PropertyValue > aGrabBag;
245 0 : mAny >>= aGrabBag;
246 0 : for( sal_Int32 i=0; i < aGrabBag.getLength(); ++i )
247 0 : if( aGrabBag[i].Name == "SpPrSolidFillSchemeClr" )
248 0 : aGrabBag[i].Value >>= sColorFillScheme;
249 0 : else if( aGrabBag[i].Name == "OriginalSolidFillClr" )
250 0 : aGrabBag[i].Value >>= nOriginalColor;
251 0 : else if( aGrabBag[i].Name == "StyleFillRef" )
252 0 : aGrabBag[i].Value >>= aStyleProperties;
253 0 : else if( aGrabBag[i].Name == "SpPrSolidFillSchemeClrTransformations" )
254 0 : aGrabBag[i].Value >>= aTransformations;
255 : }
256 :
257 0 : sal_Int32 nAlpha = MAX_PERCENT;
258 0 : if( GetProperty( rXPropSet, "FillTransparence" ) )
259 : {
260 0 : sal_Int32 nTransparency = 0;
261 0 : mAny >>= nTransparency;
262 : // Calculate alpha value (see oox/source/drawingml/color.cxx : getTransparency())
263 0 : nAlpha = (MAX_PERCENT - ( PER_PERCENT * nTransparency ) );
264 : }
265 :
266 : // write XML
267 0 : if ( nFillColor != nOriginalColor )
268 : // the user has set a different color for the shape
269 0 : WriteSolidFill( nFillColor & 0xffffff, nAlpha );
270 0 : else if ( !sColorFillScheme.isEmpty() )
271 : // the shape had a scheme color and the user didn't change it
272 0 : WriteSolidFill( sColorFillScheme, aTransformations );
273 0 : else if ( aStyleProperties.hasElements() )
274 : {
275 0 : sal_uInt32 nThemeColor = 0;
276 0 : for( sal_Int32 i=0; i < aStyleProperties.getLength(); ++i )
277 0 : if( aStyleProperties[i].Name == "Color" )
278 : {
279 0 : aStyleProperties[i].Value >>= nThemeColor;
280 0 : break;
281 : }
282 0 : if ( nFillColor != nThemeColor )
283 : // the shape contains a theme but it wasn't being used
284 0 : 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 0 : WriteSolidFill( nFillColor & 0xffffff, nAlpha );
291 : }
292 :
293 0 : void DrawingML::WriteGradientStop( sal_uInt16 nStop, sal_uInt32 nColor )
294 : {
295 : mpFS->startElementNS( XML_a, XML_gs,
296 : XML_pos, I32S( nStop * 1000 ),
297 0 : FSEND );
298 0 : WriteColor( nColor );
299 0 : mpFS->endElementNS( XML_a, XML_gs );
300 0 : }
301 :
302 0 : sal_uInt32 DrawingML::ColorWithIntensity( sal_uInt32 nColor, sal_uInt32 nIntensity )
303 : {
304 0 : return ( ( ( nColor & 0xff ) * nIntensity ) / 100 )
305 0 : | ( ( ( ( ( nColor & 0xff00 ) >> 8 ) * nIntensity ) / 100 ) << 8 )
306 0 : | ( ( ( ( ( nColor & 0xff0000 ) >> 8 ) * nIntensity ) / 100 ) << 8 );
307 : }
308 :
309 0 : bool DrawingML::EqualGradients( awt::Gradient aGradient1, awt::Gradient aGradient2 )
310 : {
311 0 : return aGradient1.Style == aGradient2.Style &&
312 0 : aGradient1.StartColor == aGradient2.StartColor &&
313 0 : aGradient1.EndColor == aGradient2.EndColor &&
314 0 : aGradient1.Angle == aGradient2.Angle &&
315 0 : aGradient1.Border == aGradient2.Border &&
316 0 : aGradient1.XOffset == aGradient2.XOffset &&
317 0 : aGradient1.YOffset == aGradient2.YOffset &&
318 0 : aGradient1.StartIntensity == aGradient2.StartIntensity &&
319 0 : aGradient1.EndIntensity == aGradient2.EndIntensity &&
320 0 : aGradient1.StepCount == aGradient2.StepCount;
321 : }
322 :
323 0 : void DrawingML::WriteGradientFill( Reference< XPropertySet > rXPropSet )
324 : {
325 0 : awt::Gradient aGradient;
326 0 : if( GETA( FillGradient ) ) {
327 0 : aGradient = *static_cast< const awt::Gradient* >( mAny.getValue() );
328 :
329 : // get InteropGrabBag and search the relevant attributes
330 0 : awt::Gradient aOriginalGradient;
331 0 : Sequence< PropertyValue > aGradientStops;
332 0 : if ( GetProperty( rXPropSet, "InteropGrabBag" ) )
333 : {
334 0 : Sequence< PropertyValue > aGrabBag;
335 0 : mAny >>= aGrabBag;
336 0 : for( sal_Int32 i=0; i < aGrabBag.getLength(); ++i )
337 0 : if( aGrabBag[i].Name == "GradFillDefinition" )
338 0 : aGrabBag[i].Value >>= aGradientStops;
339 0 : else if( aGrabBag[i].Name == "OriginalGradFill" )
340 0 : aGrabBag[i].Value >>= aOriginalGradient;
341 : }
342 :
343 : // check if an ooxml gradient had been imported and if the user has modified it
344 0 : if( EqualGradients( aOriginalGradient, aGradient ) )
345 : {
346 : // If we have no gradient stops that means original gradient were defined by a theme.
347 0 : if( aGradientStops.hasElements() )
348 : {
349 0 : mpFS->startElementNS( XML_a, XML_gradFill, FSEND );
350 0 : WriteGrabBagGradientFill(aGradientStops, aGradient);
351 0 : mpFS->endElementNS( XML_a, XML_gradFill );
352 : }
353 : }
354 : else
355 : {
356 0 : mpFS->startElementNS( XML_a, XML_gradFill, FSEND );
357 0 : WriteGradientFill(aGradient);
358 0 : mpFS->endElementNS( XML_a, XML_gradFill );
359 0 : }
360 : }
361 0 : }
362 :
363 0 : void DrawingML::WriteGrabBagGradientFill( Sequence< PropertyValue > aGradientStops, awt::Gradient rGradient )
364 : {
365 : // write back the original gradient
366 0 : mpFS->startElementNS( XML_a, XML_gsLst, FSEND );
367 :
368 : // get original stops and write them
369 0 : for( sal_Int32 i=0; i < aGradientStops.getLength(); ++i )
370 : {
371 0 : Sequence< PropertyValue > aGradientStop;
372 0 : aGradientStops[i].Value >>= aGradientStop;
373 :
374 : // get values
375 0 : OUString sSchemeClr;
376 0 : double nPos = 0;
377 0 : sal_Int16 nTransparency = 0;
378 0 : sal_Int32 nRgbClr = 0;
379 0 : Sequence< PropertyValue > aTransformations;
380 0 : for( sal_Int32 j=0; j < aGradientStop.getLength(); ++j )
381 0 : if( aGradientStop[j].Name == "SchemeClr" )
382 0 : aGradientStop[j].Value >>= sSchemeClr;
383 0 : else if( aGradientStop[j].Name == "RgbClr" )
384 0 : aGradientStop[j].Value >>= nRgbClr;
385 0 : else if( aGradientStop[j].Name == "Pos" )
386 0 : aGradientStop[j].Value >>= nPos;
387 0 : else if( aGradientStop[j].Name == "Transparency" )
388 0 : aGradientStop[j].Value >>= nTransparency;
389 0 : else if( aGradientStop[j].Name == "Transformations" )
390 0 : 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 0 : FSEND );
396 0 : if( sSchemeClr.isEmpty() )
397 : {
398 : // Calculate alpha value (see oox/source/drawingml/color.cxx : getTransparency())
399 0 : sal_Int32 nAlpha = (MAX_PERCENT - ( PER_PERCENT * nTransparency ) );
400 0 : WriteColor( nRgbClr, nAlpha );
401 : }
402 : else
403 0 : WriteColor( sSchemeClr, aTransformations );
404 0 : mpFS->endElementNS( XML_a, XML_gs );
405 0 : }
406 0 : mpFS->endElementNS( XML_a, XML_gsLst );
407 :
408 : mpFS->singleElementNS( XML_a, XML_lin,
409 0 : XML_ang, I32S( ( ( ( 3600 - rGradient.Angle + 900 ) * 6000 ) % 21600000 ) ),
410 0 : FSEND );
411 0 : }
412 :
413 0 : void DrawingML::WriteGradientFill( awt::Gradient rGradient )
414 : {
415 0 : switch( rGradient.Style ) {
416 : default:
417 : case GradientStyle_LINEAR:
418 0 : mpFS->startElementNS( XML_a, XML_gsLst, FSEND );
419 0 : WriteGradientStop( 0, ColorWithIntensity( rGradient.StartColor, rGradient.StartIntensity ) );
420 0 : WriteGradientStop( 100, ColorWithIntensity( rGradient.EndColor, rGradient.EndIntensity ) );
421 0 : mpFS->endElementNS( XML_a, XML_gsLst );
422 : mpFS->singleElementNS( XML_a, XML_lin,
423 0 : XML_ang, I32S( ( ( ( 3600 - rGradient.Angle + 900 ) * 6000 ) % 21600000 ) ),
424 0 : FSEND );
425 0 : break;
426 :
427 : case GradientStyle_AXIAL:
428 0 : mpFS->startElementNS( XML_a, XML_gsLst, FSEND );
429 0 : WriteGradientStop( 0, ColorWithIntensity( rGradient.EndColor, rGradient.EndIntensity ) );
430 0 : WriteGradientStop( 50, ColorWithIntensity( rGradient.StartColor, rGradient.StartIntensity ) );
431 0 : WriteGradientStop( 100, ColorWithIntensity( rGradient.EndColor, rGradient.EndIntensity ) );
432 0 : mpFS->endElementNS( XML_a, XML_gsLst );
433 : mpFS->singleElementNS( XML_a, XML_lin,
434 0 : XML_ang, I32S( ( ( ( 3600 - rGradient.Angle + 900 ) * 6000 ) % 21600000 ) ),
435 0 : FSEND );
436 0 : 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 0 : }
455 :
456 0 : void DrawingML::WriteLineArrow( Reference< XPropertySet > rXPropSet, bool bLineStart )
457 : {
458 : ESCHER_LineEnd eLineEnd;
459 : sal_Int32 nArrowLength;
460 : sal_Int32 nArrowWidth;
461 :
462 0 : if ( EscherPropertyContainer::GetLineArrow( bLineStart, rXPropSet, eLineEnd, nArrowLength, nArrowWidth ) ) {
463 : const char* len;
464 : const char* type;
465 : const char* width;
466 :
467 0 : switch( nArrowLength ) {
468 : case ESCHER_LineShortArrow:
469 0 : len = "sm";
470 0 : break;
471 : default:
472 : case ESCHER_LineMediumLenArrow:
473 0 : len = "med";
474 0 : break;
475 : case ESCHER_LineLongArrow:
476 0 : len = "lg";
477 0 : break;
478 : }
479 :
480 0 : switch( eLineEnd ) {
481 : default:
482 : case ESCHER_LineNoEnd:
483 0 : type = "none";
484 0 : break;
485 : case ESCHER_LineArrowEnd:
486 0 : type = "triangle";
487 0 : break;
488 : case ESCHER_LineArrowStealthEnd:
489 0 : type = "stealth";
490 0 : break;
491 : case ESCHER_LineArrowDiamondEnd:
492 0 : type = "diamond";
493 0 : break;
494 : case ESCHER_LineArrowOvalEnd:
495 0 : type = "oval";
496 0 : break;
497 : case ESCHER_LineArrowOpenEnd:
498 0 : type = "arrow";
499 0 : break;
500 : }
501 :
502 0 : switch( nArrowWidth ) {
503 : case ESCHER_LineNarrowArrow:
504 0 : width = "sm";
505 0 : break;
506 : default:
507 : case ESCHER_LineMediumWidthArrow:
508 0 : width = "med";
509 0 : 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 0 : FSEND );
520 : }
521 0 : }
522 :
523 0 : void DrawingML::WriteOutline( Reference< XPropertySet > rXPropSet )
524 : {
525 0 : drawing::LineStyle aLineStyle( drawing::LineStyle_NONE );
526 :
527 0 : GET( aLineStyle, LineStyle );
528 :
529 0 : sal_uInt32 nLineWidth = 0;
530 0 : sal_uInt32 nColor = 0;
531 0 : bool bColorSet = false;
532 0 : const char* cap = NULL;
533 0 : drawing::LineDash aLineDash;
534 0 : bool bDashSet = false;
535 0 : bool bNoFill = false;
536 :
537 : // get InteropGrabBag and search the relevant attributes
538 0 : OUString sColorFillScheme;
539 0 : sal_uInt32 nOriginalColor( 0 ), nStyleColor( 0 ), nStyleLineWidth( 0 );
540 0 : Sequence< PropertyValue > aStyleProperties, aTransformations;
541 0 : drawing::LineStyle aStyleLineStyle( drawing::LineStyle_NONE );
542 0 : drawing::LineJoint aStyleLineJoint( drawing::LineJoint_NONE );
543 0 : if ( GetProperty( rXPropSet, "InteropGrabBag" ) )
544 : {
545 0 : Sequence< PropertyValue > aGrabBag;
546 0 : mAny >>= aGrabBag;
547 0 : for( sal_Int32 i=0; i < aGrabBag.getLength(); ++i )
548 0 : if( aGrabBag[i].Name == "SpPrLnSolidFillSchemeClr" )
549 0 : aGrabBag[i].Value >>= sColorFillScheme;
550 0 : else if( aGrabBag[i].Name == "OriginalLnSolidFillClr" )
551 0 : aGrabBag[i].Value >>= nOriginalColor;
552 0 : else if( aGrabBag[i].Name == "StyleLnRef" )
553 0 : aGrabBag[i].Value >>= aStyleProperties;
554 0 : else if( aGrabBag[i].Name == "SpPrLnSolidFillSchemeClrTransformations" )
555 0 : aGrabBag[i].Value >>= aTransformations;
556 0 : if( aStyleProperties.hasElements() )
557 : {
558 0 : for( sal_Int32 i=0; i < aStyleProperties.getLength(); ++i )
559 0 : if( aStyleProperties[i].Name == "Color" )
560 0 : aStyleProperties[i].Value >>= nStyleColor;
561 0 : else if( aStyleProperties[i].Name == "LineStyle" )
562 0 : aStyleProperties[i].Value >>= aStyleLineStyle;
563 0 : else if( aStyleProperties[i].Name == "LineJoint" )
564 0 : aStyleProperties[i].Value >>= aStyleLineJoint;
565 0 : else if( aStyleProperties[i].Name == "LineWidth" )
566 0 : aStyleProperties[i].Value >>= nStyleLineWidth;
567 0 : }
568 : }
569 :
570 0 : GET( nLineWidth, LineWidth );
571 :
572 0 : switch( aLineStyle ) {
573 : case drawing::LineStyle_NONE:
574 0 : bNoFill = true;
575 0 : break;
576 : case drawing::LineStyle_DASH:
577 0 : if( GETA( LineDash ) ) {
578 0 : aLineDash = *(drawing::LineDash*) mAny.getValue();
579 0 : bDashSet = true;
580 0 : if( aLineDash.Style == DashStyle_ROUND || aLineDash.Style == DashStyle_ROUNDRELATIVE )
581 0 : 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 0 : if ( GETA( LineColor ) ) {
590 0 : nColor = *((sal_uInt32*) mAny.getValue()) & 0xffffff;
591 0 : bColorSet = true;
592 : }
593 0 : break;
594 : }
595 :
596 : mpFS->startElementNS( XML_a, XML_ln,
597 : XML_cap, cap,
598 0 : XML_w, nLineWidth > 1 && nStyleLineWidth != nLineWidth ?
599 0 : I64S( MM100toEMU( nLineWidth ) ) :NULL,
600 0 : FSEND );
601 :
602 0 : if( bColorSet )
603 : {
604 0 : if( nColor != nOriginalColor )
605 : // the user has set a different color for the line
606 0 : WriteSolidFill( nColor );
607 0 : else if( !sColorFillScheme.isEmpty() )
608 : // the line had a scheme color and the user didn't change it
609 0 : WriteSolidFill( sColorFillScheme, aTransformations );
610 0 : else if( aStyleProperties.hasElements() )
611 : {
612 0 : if( nColor != nStyleColor )
613 : // the line style defines some color but it wasn't being used
614 0 : 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 0 : WriteSolidFill( nColor );
620 : }
621 :
622 0 : 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 0 : mpFS->startElementNS( XML_a, XML_custDash, FSEND );
626 : int i;
627 0 : 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 0 : 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 0 : FSEND );
637 0 : mpFS->endElementNS( XML_a, XML_custDash );
638 : }
639 :
640 0 : if( !bNoFill && nLineWidth > 1 && GETA( LineJoint ) ) {
641 : LineJoint eLineJoint;
642 :
643 0 : mAny >>= eLineJoint;
644 0 : if( aStyleLineJoint == LineJoint_NONE || aStyleLineJoint != eLineJoint )
645 : // style-defined line joint does not exist, or is different from the shape's joint
646 0 : switch( eLineJoint ) {
647 : case LineJoint_NONE:
648 : case LineJoint_MIDDLE:
649 : case LineJoint_BEVEL:
650 0 : mpFS->singleElementNS( XML_a, XML_bevel, FSEND );
651 0 : break;
652 : default:
653 : case LineJoint_MITER:
654 0 : mpFS->singleElementNS( XML_a, XML_miter, FSEND );
655 0 : break;
656 : case LineJoint_ROUND:
657 0 : mpFS->singleElementNS( XML_a, XML_round, FSEND );
658 0 : break;
659 : }
660 : }
661 :
662 0 : if( !bNoFill )
663 : {
664 0 : WriteLineArrow( rXPropSet, true );
665 0 : WriteLineArrow( rXPropSet, false );
666 : }
667 : else
668 : {
669 0 : mpFS->singleElementNS( XML_a, XML_noFill, FSEND );
670 : }
671 :
672 0 : mpFS->endElementNS( XML_a, XML_ln );
673 0 : }
674 :
675 0 : OUString DrawingML::WriteImage( const OUString& rURL, bool bRelPathToMedia )
676 : {
677 0 : OString aURLBS(OUStringToOString(rURL, RTL_TEXTENCODING_UTF8));
678 :
679 0 : const char aURLBegin[] = "vnd.sun.star.GraphicObject:";
680 0 : sal_Int32 index = aURLBS.indexOf(aURLBegin);
681 :
682 0 : if ( index != -1 )
683 : {
684 : DBG(fprintf (stderr, "begin: %ld %s\n", long( sizeof( aURLBegin ) ), USS( rURL ) + RTL_CONSTASCII_LENGTH( aURLBegin ) ));
685 0 : Graphic aGraphic = GraphicObject( aURLBS.copy(RTL_CONSTASCII_LENGTH(aURLBegin)) ).GetTransformedGraphic ();
686 :
687 0 : return WriteImage( aGraphic , bRelPathToMedia );
688 : } else {
689 : // add link to relations
690 : }
691 :
692 0 : return OUString();
693 : }
694 :
695 0 : const char* DrawingML::GetComponentDir()
696 : {
697 0 : switch ( meDocumentType )
698 : {
699 0 : case DOCUMENT_DOCX: return "word";
700 0 : case DOCUMENT_PPTX: return "ppt";
701 0 : case DOCUMENT_XLSX: return "xl";
702 : }
703 :
704 0 : return "unknown";
705 : }
706 :
707 0 : const char* DrawingML::GetRelationCompPrefix()
708 : {
709 0 : switch ( meDocumentType )
710 : {
711 0 : case DOCUMENT_DOCX: return "";
712 : case DOCUMENT_PPTX:
713 0 : case DOCUMENT_XLSX: return "../";
714 : }
715 :
716 0 : return "unknown";
717 : }
718 :
719 0 : OUString DrawingML::WriteImage( const Graphic& rGraphic , bool bRelPathToMedia )
720 : {
721 0 : GfxLink aLink = rGraphic.GetLink ();
722 0 : OUString sMediaType;
723 0 : const char* pExtension = "";
724 0 : OUString sRelId;
725 :
726 0 : SvMemoryStream aStream;
727 0 : const void* aData = aLink.GetData();
728 0 : sal_Size nDataSize = aLink.GetDataSize();
729 :
730 0 : switch ( aLink.GetType() ) {
731 : case GFX_LINK_TYPE_NATIVE_GIF:
732 0 : sMediaType = "image/gif";
733 0 : pExtension = ".gif";
734 0 : 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 0 : sMediaType = "image/bmp";
740 0 : pExtension = ".bmp";
741 0 : break;
742 :
743 : case GFX_LINK_TYPE_NATIVE_JPG:
744 0 : sMediaType = "image/jpeg";
745 0 : pExtension = ".jpeg";
746 0 : break;
747 : case GFX_LINK_TYPE_NATIVE_PNG:
748 0 : sMediaType = "image/png";
749 0 : pExtension = ".png";
750 0 : 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 0 : sMediaType = "image/x-wmf";
757 0 : pExtension = ".wmf";
758 0 : 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 0 : GraphicType aType = rGraphic.GetType();
773 0 : if ( aType == GRAPHIC_BITMAP ) {
774 0 : GraphicConverter::Export( aStream, rGraphic, CVT_PNG );
775 0 : sMediaType = "image/png";
776 0 : pExtension = ".png";
777 0 : } else if ( aType == GRAPHIC_GDIMETAFILE ) {
778 0 : GraphicConverter::Export( aStream, rGraphic, CVT_EMF );
779 0 : sMediaType = "image/x-emf";
780 0 : 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 0 : return sRelId;
789 : }
790 :
791 0 : aData = aStream.GetData();
792 0 : nDataSize = aStream.GetEndOfData();
793 0 : break;
794 : }
795 : }
796 :
797 : Reference< XOutputStream > xOutStream = mpFB->openFragmentStream( OUStringBuffer()
798 0 : .appendAscii( GetComponentDir() )
799 0 : .appendAscii( "/media/image" )
800 0 : .append( (sal_Int32) mnImageCounter )
801 0 : .appendAscii( pExtension )
802 : .makeStringAndClear(),
803 0 : sMediaType );
804 0 : xOutStream->writeBytes( Sequence< sal_Int8 >( (const sal_Int8*) aData, nDataSize ) );
805 0 : xOutStream->closeOutput();
806 :
807 0 : OString sRelPathToMedia = "media/image";
808 0 : if ( bRelPathToMedia )
809 0 : sRelPathToMedia = "../" + sRelPathToMedia;
810 0 : sRelId = mpFB->addRelation( mpFS->getOutputStream(),
811 : "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",
812 : OUStringBuffer()
813 0 : .appendAscii( GetRelationCompPrefix() )
814 0 : .appendAscii( sRelPathToMedia.getStr() )
815 0 : .append( (sal_Int32) mnImageCounter ++ )
816 0 : .appendAscii( pExtension )
817 0 : .makeStringAndClear() );
818 :
819 0 : return sRelId;
820 : }
821 :
822 0 : OUString DrawingML::WriteBlip( Reference< XPropertySet > rXPropSet, const OUString& rURL, bool bRelPathToMedia, const Graphic *pGraphic )
823 : {
824 0 : OUString sRelId = pGraphic ? WriteImage( *pGraphic, bRelPathToMedia ) : WriteImage( rURL, bRelPathToMedia );
825 0 : sal_Int16 nBright = 0;
826 0 : sal_Int32 nContrast = 0;
827 :
828 0 : GET( nBright, AdjustLuminance );
829 0 : GET( nContrast, AdjustContrast );
830 :
831 : mpFS->startElementNS( XML_a, XML_blip,
832 : FSNS( XML_r, XML_embed), OUStringToOString( sRelId, RTL_TEXTENCODING_UTF8 ).getStr(),
833 0 : FSEND );
834 0 : 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 0 : FSEND );
839 :
840 0 : mpFS->endElementNS( XML_a, XML_blip );
841 :
842 0 : return sRelId;
843 : }
844 :
845 0 : void DrawingML::WriteBlipMode( Reference< XPropertySet > rXPropSet, const OUString& rURL )
846 : {
847 0 : BitmapMode eBitmapMode( BitmapMode_NO_REPEAT );
848 0 : if (GetProperty( rXPropSet, "FillBitmapMode" ) )
849 0 : mAny >>= eBitmapMode;
850 :
851 : DBG(fprintf(stderr, "fill bitmap mode: %d\n", eBitmapMode));
852 :
853 0 : switch (eBitmapMode) {
854 : case BitmapMode_REPEAT:
855 0 : mpFS->singleElementNS( XML_a, XML_tile, FSEND );
856 0 : break;
857 : case BitmapMode_STRETCH:
858 0 : WriteStretch( rXPropSet, rURL );
859 0 : break;
860 : default:
861 : ;
862 : }
863 0 : }
864 :
865 0 : 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 0 : if (GetProperty ( xPropSet, rURLPropName ))
871 0 : WriteBlipFill( xPropSet, rURLPropName );
872 : else
873 0 : WriteFill(xPropSet);
874 0 : }
875 :
876 0 : void DrawingML::WriteBlipFill( Reference< XPropertySet > rXPropSet, const OUString& sURLPropName )
877 : {
878 0 : WriteBlipFill( rXPropSet, sURLPropName, XML_a );
879 0 : }
880 :
881 0 : void DrawingML::WriteBlipFill( Reference< XPropertySet > rXPropSet, const OUString& sURLPropName, sal_Int32 nXmlNamespace )
882 : {
883 0 : if ( GetProperty( rXPropSet, sURLPropName ) ) {
884 0 : OUString aURL;
885 0 : mAny >>= aURL;
886 0 : bool bWriteMode = false;
887 0 : if( sURLPropName == "FillBitmapURL" || sURLPropName == "BackGraphicURL")
888 0 : bWriteMode = true;
889 0 : WriteBlipFill( rXPropSet, aURL, nXmlNamespace, bWriteMode );
890 : }
891 0 : }
892 :
893 0 : void DrawingML::WriteBlipFill( Reference< XPropertySet > rXPropSet, const OUString& sBitmapURL, sal_Int32 nXmlNamespace, bool bWriteMode, bool bRelPathToMedia )
894 : {
895 0 : if ( !sBitmapURL.isEmpty() ) {
896 : DBG(fprintf (stderr, "URL: %s\n", OUStringToOString( sBitmapURL, RTL_TEXTENCODING_UTF8 ).getStr() ));
897 :
898 0 : mpFS->startElementNS( nXmlNamespace , XML_blipFill, FSEND );
899 :
900 0 : WriteBlip( rXPropSet, sBitmapURL, bRelPathToMedia );
901 :
902 0 : if( bWriteMode )
903 0 : 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 0 : mpFS->endElementNS( nXmlNamespace, XML_blipFill );
912 : }
913 0 : }
914 :
915 0 : void DrawingML::WritePattFill( Reference< XPropertySet > rXPropSet )
916 : {
917 0 : if ( GetProperty( rXPropSet, "FillHatch" ) )
918 : {
919 0 : drawing::Hatch aHatch;
920 0 : mAny >>= aHatch;
921 :
922 0 : mpFS->startElementNS( XML_a , XML_pattFill, XML_prst, GetHatchPattern(aHatch), FSEND );
923 :
924 0 : mpFS->startElementNS( XML_a , XML_fgClr, FSEND );
925 0 : WriteColor(aHatch.Color);
926 0 : mpFS->endElementNS( XML_a , XML_fgClr );
927 :
928 : // In Writer hatching has no background so use white as a default value.
929 0 : mpFS->startElementNS( XML_a , XML_bgClr, FSEND );
930 0 : WriteColor(COL_WHITE);
931 0 : mpFS->endElementNS( XML_a , XML_bgClr );
932 :
933 0 : mpFS->endElementNS( XML_a , XML_pattFill );
934 : }
935 0 : }
936 :
937 0 : void DrawingML::WriteSrcRect( Reference< XPropertySet > rXPropSet, const OUString& rURL )
938 : {
939 0 : Size aOriginalSize( GraphicObject::CreateGraphicObjectFromURL( rURL ).GetPrefSize() );
940 :
941 0 : if ( GetProperty( rXPropSet, "GraphicCrop" ) )
942 : {
943 0 : ::com::sun::star::text::GraphicCrop aGraphicCropStruct;
944 0 : mAny >>= aGraphicCropStruct;
945 :
946 0 : 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 0 : }
957 :
958 0 : void DrawingML::WriteStretch( ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > rXPropSet, const OUString& rURL )
959 : {
960 0 : mpFS->startElementNS( XML_a, XML_stretch, FSEND );
961 :
962 0 : bool bCrop = false;
963 0 : if ( GetProperty( rXPropSet, "GraphicCrop" ) )
964 : {
965 0 : ::com::sun::star::text::GraphicCrop aGraphicCropStruct;
966 0 : mAny >>= aGraphicCropStruct;
967 :
968 0 : if ( (0 != aGraphicCropStruct.Left) || (0 != aGraphicCropStruct.Top) || (0 != aGraphicCropStruct.Right) || (0 != aGraphicCropStruct.Bottom) )
969 : {
970 0 : Size aOriginalSize( GraphicObject::CreateGraphicObjectFromURL( rURL ).GetPrefSize() );
971 : mpFS->singleElementNS( XML_a, XML_fillRect,
972 0 : XML_l, I32S(((aGraphicCropStruct.Left) * 100000)/aOriginalSize.Width()),
973 0 : XML_t, I32S(((aGraphicCropStruct.Top) * 100000)/aOriginalSize.Height()),
974 0 : XML_r, I32S(((aGraphicCropStruct.Right) * 100000)/aOriginalSize.Width()),
975 0 : XML_b, I32S(((aGraphicCropStruct.Bottom) * 100000)/aOriginalSize.Height()),
976 0 : FSEND );
977 0 : bCrop = true;
978 : }
979 : }
980 :
981 0 : if( !bCrop )
982 : {
983 0 : mpFS->singleElementNS( XML_a, XML_fillRect, FSEND );
984 : }
985 :
986 0 : mpFS->endElementNS( XML_a, XML_stretch );
987 0 : }
988 :
989 0 : 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 0 : XML_rot, (nRotation % 21600000) ? I32S( nRotation ) : NULL,
996 0 : FSEND );
997 :
998 0 : sal_Int32 nLeft = rRect.Left();
999 0 : sal_Int32 nTop = rRect.Top();
1000 0 : if (GetDocumentType() == DOCUMENT_DOCX && !m_xParent.is())
1001 : {
1002 0 : nLeft = 0;
1003 0 : nTop = 0;
1004 : }
1005 :
1006 0 : mpFS->singleElementNS( XML_a, XML_off, XML_x, IS( MM100toEMU( nLeft ) ), XML_y, IS( MM100toEMU( nTop ) ), FSEND );
1007 0 : mpFS->singleElementNS( XML_a, XML_ext, XML_cx, IS( MM100toEMU( rRect.GetWidth() ) ), XML_cy, IS( MM100toEMU( rRect.GetHeight() ) ), FSEND );
1008 :
1009 0 : mpFS->endElementNS( nXmlNamespace, XML_xfrm );
1010 0 : }
1011 :
1012 0 : 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 0 : sal_Int32 nRotation=0;
1017 0 : awt::Point aPos = rXShape->getPosition();
1018 0 : awt::Size aSize = rXShape->getSize();
1019 :
1020 0 : if (m_xParent.is())
1021 : {
1022 0 : awt::Point aParentPos = m_xParent->getPosition();
1023 0 : aPos.X -= aParentPos.X;
1024 0 : aPos.Y -= aParentPos.Y;
1025 : }
1026 :
1027 0 : if ( aSize.Width < 0 )
1028 0 : aSize.Width = 1000;
1029 0 : if ( aSize.Height < 0 )
1030 0 : aSize.Height = 1000;
1031 0 : if (!bSuppressRotation)
1032 : {
1033 0 : SdrObject* pShape = (SdrObject*) GetSdrObjectFromXShape( rXShape );
1034 0 : nRotation=pShape->GetRotateAngle();
1035 0 : if (nRotation != 0 && nRotation != 18000)
1036 : {
1037 0 : int faccos=bFlipV ? -1 : 1;
1038 0 : int facsin=bFlipH ? -1 : 1;
1039 0 : aPos.X-=(1-faccos*cos(nRotation*F_PI18000))*aSize.Width/2-facsin*sin(nRotation*F_PI18000)*aSize.Height/2;
1040 0 : aPos.Y-=(1-faccos*cos(nRotation*F_PI18000))*aSize.Height/2+facsin*sin(nRotation*F_PI18000)*aSize.Width/2;
1041 : }
1042 : }
1043 0 : if (!bSuppressRotation)
1044 : {
1045 0 : if (bFlipV) {nRotation=(nRotation+18000)%36000;}
1046 : }
1047 0 : WriteTransformation( Rectangle( Point( aPos.X, aPos.Y ), Size( aSize.Width, aSize.Height ) ), nXmlNamespace, bFlipH, bFlipV, PPTX_EXPORT_ROTATE_CLOCKWISIFY(nRotation) );
1048 0 : }
1049 :
1050 0 : void DrawingML::WriteRunProperties( Reference< XPropertySet > rRun, bool bIsField )
1051 : {
1052 0 : Reference< XPropertySet > rXPropSet( rRun, UNO_QUERY );
1053 0 : Reference< XPropertyState > rXPropState( rRun, UNO_QUERY );
1054 0 : OUString usLanguage;
1055 : PropertyState eState;
1056 0 : sal_Int16 nScriptType = SvtLanguageOptions::GetScriptTypeOfLanguage( Application::GetSettings().GetLanguageTag().getLanguageType() );
1057 0 : bool bComplex = ( nScriptType == ScriptType::COMPLEX );
1058 0 : const char* bold = NULL;
1059 0 : const char* italic = NULL;
1060 0 : const char* underline = NULL;
1061 0 : sal_Int32 nSize = 1800;
1062 0 : sal_Int32 nCharEscapement = 0;
1063 :
1064 0 : if( GETA( CharHeight ) )
1065 0 : nSize = (sal_Int32) (100*(*((float*) mAny.getValue())));
1066 :
1067 0 : if ( ( bComplex && GETA( CharWeightComplex ) ) || GETA( CharWeight ) )
1068 0 : if ( *((float*) mAny.getValue()) >= awt::FontWeight::SEMIBOLD )
1069 0 : bold = "1";
1070 :
1071 0 : if ( ( bComplex && GETA( CharPostureComplex ) ) || GETA( CharPosture ) )
1072 0 : 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 0 : break;
1080 : }
1081 :
1082 0 : if ( GETAD( CharUnderline ) )
1083 0 : 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 0 : if( GETA( CharLocale ) ) {
1136 0 : com::sun::star::lang::Locale aLocale;
1137 0 : mAny >>= aLocale;
1138 0 : LanguageTag aLanguageTag( aLocale);
1139 0 : if (!aLanguageTag.isSystemLocale())
1140 0 : usLanguage = aLanguageTag.getBcp47();
1141 : }
1142 :
1143 0 : if( GETAD( CharEscapement ) )
1144 0 : mAny >>= nCharEscapement;
1145 :
1146 0 : if( nCharEscapement && GETAD( CharEscapementHeight ) ) {
1147 0 : sal_uInt32 nCharEscapementHeight = 0;
1148 0 : mAny >>= nCharEscapementHeight;
1149 0 : nSize = (nSize * nCharEscapementHeight) / 100;
1150 : // MSO uses default ~58% size
1151 0 : nSize = (nSize / 0.58);
1152 : }
1153 :
1154 : mpFS->startElementNS( XML_a, XML_rPr,
1155 : XML_b, bold,
1156 : XML_i, italic,
1157 0 : XML_lang, usLanguage.isEmpty() ? NULL : USS( usLanguage ),
1158 0 : XML_sz, nSize == 1800 ? NULL : IS( nSize ),
1159 : XML_u, underline,
1160 0 : XML_baseline, nCharEscapement == 0 ? NULL : IS( nCharEscapement*1000 ),
1161 0 : FSEND );
1162 :
1163 : // mso doesn't like text color to be placed after typeface
1164 0 : if( GETAD( CharColor ) ) {
1165 0 : 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 0 : 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 0 : color &= 0xffffff;
1174 :
1175 : // TODO: special handle embossed/engraved
1176 :
1177 0 : WriteSolidFill( color );
1178 : }
1179 :
1180 0 : if( GETA( CharFontName ) ) {
1181 0 : const char* pitch = NULL;
1182 0 : const char* charset = NULL;
1183 0 : OUString usTypeface;
1184 :
1185 0 : mAny >>= usTypeface;
1186 0 : OUString aSubstName( GetSubsFontName( usTypeface, SUBSFONT_ONLYONE | SUBSFONT_MS ) );
1187 :
1188 : mpFS->singleElementNS( XML_a, XML_latin,
1189 0 : XML_typeface, USS(aSubstName.getLength() ? aSubstName : usTypeface),
1190 : XML_pitchFamily, pitch,
1191 : XML_charset, charset,
1192 0 : FSEND );
1193 : }
1194 :
1195 0 : if( ( bComplex && GETAD( CharFontNameComplex ) ) || ( !bComplex && GETAD( CharFontNameAsian ) ) ) {
1196 0 : const char* pitch = NULL;
1197 0 : const char* charset = NULL;
1198 0 : OUString usTypeface;
1199 :
1200 0 : mAny >>= usTypeface;
1201 0 : OUString aSubstName( GetSubsFontName( usTypeface, SUBSFONT_ONLYONE | SUBSFONT_MS ) );
1202 :
1203 : mpFS->singleElementNS( XML_a, bComplex ? XML_cs : XML_ea,
1204 0 : XML_typeface, USS(aSubstName.getLength() ? aSubstName : usTypeface),
1205 : XML_pitchFamily, pitch,
1206 : XML_charset, charset,
1207 0 : FSEND );
1208 : }
1209 :
1210 0 : if( bIsField ) {
1211 0 : Reference< XTextField > rXTextField;
1212 0 : GET( rXTextField, TextField );
1213 0 : if( rXTextField.is() )
1214 0 : rRun.set( rXTextField, UNO_QUERY );
1215 : }
1216 :
1217 : // field properties starts here
1218 0 : 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 0 : mpFS->endElementNS( XML_a, XML_rPr );
1234 0 : }
1235 :
1236 0 : const char* DrawingML::GetFieldType( ::com::sun::star::uno::Reference< ::com::sun::star::text::XTextRange > rRun, bool& bIsField )
1237 : {
1238 0 : const char* sType = NULL;
1239 0 : Reference< XPropertySet > rXPropSet( rRun, UNO_QUERY );
1240 0 : OUString aFieldType;
1241 :
1242 0 : if( GETA( TextPortionType ) ) {
1243 0 : aFieldType = OUString( *(OUString*)mAny.getValue() );
1244 : DBG(fprintf (stderr, "field type: %s\n", USS(aFieldType) ));
1245 : }
1246 :
1247 0 : if( aFieldType == "TextField" ) {
1248 0 : Reference< XTextField > rXTextField;
1249 0 : GET( rXTextField, TextField );
1250 0 : if( rXTextField.is() ) {
1251 0 : bIsField = true;
1252 0 : rXPropSet.set( rXTextField, UNO_QUERY );
1253 0 : if( rXPropSet.is() ) {
1254 0 : OUString aFieldKind( rXTextField->getPresentation( true ) );
1255 : DBG(fprintf (stderr, "field kind: %s\n", USS(aFieldKind) ));
1256 0 : if( aFieldKind == "Page" ) {
1257 0 : return "slidenum";
1258 0 : }
1259 : // else if( aFieldKind == "URL" ) {
1260 : // do not return here
1261 : // and make URL field text run with hyperlink property later
1262 : // }
1263 : }
1264 0 : }
1265 : }
1266 :
1267 0 : return sType;
1268 : }
1269 :
1270 0 : void DrawingML::GetUUID( OStringBuffer& rBuffer )
1271 : {
1272 0 : Sequence< sal_uInt8 > aSeq( 16 );
1273 : static const char cDigits[17] = "0123456789ABCDEF";
1274 0 : rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, true );
1275 : int i;
1276 :
1277 0 : rBuffer.append( '{' );
1278 0 : for( i = 0; i < 4; i++ ) {
1279 0 : rBuffer.append( cDigits[ aSeq[i] >> 4 ] );
1280 0 : rBuffer.append( cDigits[ aSeq[i] & 0xf ] );
1281 : }
1282 0 : rBuffer.append( '-' );
1283 0 : for( ; i < 6; i++ ) {
1284 0 : rBuffer.append( cDigits[ aSeq[i] >> 4 ] );
1285 0 : rBuffer.append( cDigits[ aSeq[i] & 0xf ] );
1286 : }
1287 0 : rBuffer.append( '-' );
1288 0 : for( ; i < 8; i++ ) {
1289 0 : rBuffer.append( cDigits[ aSeq[i] >> 4 ] );
1290 0 : rBuffer.append( cDigits[ aSeq[i] & 0xf ] );
1291 : }
1292 0 : rBuffer.append( '-' );
1293 0 : for( ; i < 10; i++ ) {
1294 0 : rBuffer.append( cDigits[ aSeq[i] >> 4 ] );
1295 0 : rBuffer.append( cDigits[ aSeq[i] & 0xf ] );
1296 : }
1297 0 : rBuffer.append( '-' );
1298 0 : for( ; i < 16; i++ ) {
1299 0 : rBuffer.append( cDigits[ aSeq[i] >> 4 ] );
1300 0 : rBuffer.append( cDigits[ aSeq[i] & 0xf ] );
1301 : }
1302 0 : rBuffer.append( '}' );
1303 0 : }
1304 :
1305 0 : void DrawingML::WriteRun( Reference< XTextRange > rRun )
1306 : {
1307 : const char* sFieldType;
1308 0 : bool bIsField = false;
1309 0 : OUString sText = rRun->getString();
1310 :
1311 0 : if( sText.isEmpty()) {
1312 0 : Reference< XPropertySet > xPropSet( rRun, UNO_QUERY );
1313 :
1314 : try {
1315 0 : if( !xPropSet.is() || !( xPropSet->getPropertyValue( "PlaceholderText" ) >>= sText ) )
1316 0 : return;
1317 0 : if( sText.isEmpty() )
1318 0 : return;
1319 : }
1320 0 : catch (const Exception &) {
1321 0 : return;
1322 0 : }
1323 : }
1324 :
1325 0 : sFieldType = GetFieldType( rRun, bIsField );
1326 0 : if( ( sFieldType != NULL ) ) {
1327 0 : OStringBuffer sUUID(39);
1328 :
1329 0 : GetUUID( sUUID );
1330 : mpFS->startElementNS( XML_a, XML_fld,
1331 : XML_id, sUUID.getStr(),
1332 : XML_type, sFieldType,
1333 0 : FSEND );
1334 : } else
1335 0 : mpFS->startElementNS( XML_a, XML_r, FSEND );
1336 :
1337 0 : Reference< XPropertySet > xPropSet( rRun, uno::UNO_QUERY );
1338 0 : WriteRunProperties( xPropSet, bIsField );
1339 :
1340 0 : mpFS->startElementNS( XML_a, XML_t, FSEND );
1341 0 : mpFS->writeEscaped( sText );
1342 0 : mpFS->endElementNS( XML_a, XML_t );
1343 :
1344 0 : if( sFieldType )
1345 0 : mpFS->endElementNS( XML_a, XML_fld );
1346 : else
1347 0 : 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 0 : inline static const char* GetAutoNumType( sal_Int16 nNumberingType, bool bSDot, bool bPBehind, bool bPBoth )
1359 : {
1360 0 : const char* pAutoNumType = NULL;
1361 :
1362 0 : 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 0 : break;
1385 : }
1386 :
1387 0 : return pAutoNumType;
1388 : }
1389 :
1390 0 : void DrawingML::WriteParagraphNumbering( Reference< XPropertySet > rXPropSet, sal_Int16 nLevel )
1391 : {
1392 0 : if( nLevel >= 0 && GETA( NumberingRules ) )
1393 : {
1394 0 : Reference< XIndexAccess > rXIndexAccess;
1395 :
1396 0 : if ( ( mAny >>= rXIndexAccess ) && nLevel < rXIndexAccess->getCount() )
1397 : {
1398 : DBG(fprintf (stderr, "numbering rules\n"));
1399 :
1400 0 : Sequence< PropertyValue > aPropertySequence;
1401 0 : rXIndexAccess->getByIndex( nLevel ) >>= aPropertySequence;
1402 :
1403 0 : const PropertyValue* pPropValue = aPropertySequence.getArray();
1404 :
1405 0 : sal_Int32 nPropertyCount = aPropertySequence.getLength();
1406 :
1407 0 : if ( nPropertyCount ) {
1408 :
1409 0 : sal_Int16 nNumberingType = -1;
1410 0 : bool bSDot = false;
1411 0 : bool bPBehind = false;
1412 0 : bool bPBoth = false;
1413 0 : sal_Unicode aBulletChar = 0x2022; // a bullet
1414 0 : awt::FontDescriptor aFontDesc;
1415 0 : bool bHasFontDesc = false;
1416 0 : OUString aGraphicURL;
1417 0 : sal_Int16 nBulletRelSize = 0;
1418 :
1419 0 : for ( sal_Int32 i = 0; i < nPropertyCount; i++ ) {
1420 0 : const void* pValue = pPropValue[ i ].Value.getValue();
1421 0 : if ( pValue ) {
1422 0 : OUString aPropName( pPropValue[ i ].Name );
1423 : DBG(fprintf (stderr, "pro name: %s\n", OUStringToOString( aPropName, RTL_TEXTENCODING_UTF8 ).getStr()));
1424 0 : if ( aPropName == "NumberingType" )
1425 0 : nNumberingType = *( (sal_Int16*)pValue );
1426 0 : else if ( aPropName == "Prefix" ) {
1427 0 : if( *(OUString*)pValue == ")")
1428 0 : bPBoth = true;
1429 0 : } else if ( aPropName == "Suffix" ) {
1430 0 : if( *(OUString*)pValue == ".")
1431 0 : bSDot = true;
1432 0 : else if( *(OUString*)pValue == ")")
1433 0 : bPBehind = true;
1434 0 : } else if ( aPropName == "BulletChar" )
1435 : {
1436 0 : aBulletChar = OUString ( *( (OUString*)pValue ) )[ 0 ];
1437 : //printf ("bullet char: %d\n", aBulletChar.getStr());
1438 : }
1439 0 : else if ( aPropName == "BulletFont" )
1440 : {
1441 0 : aFontDesc = *( (awt::FontDescriptor*)pValue );
1442 0 : 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 0 : if ( aFontDesc.Name.equalsIgnoreAsciiCase("StarSymbol") )
1449 0 : aFontDesc.CharSet = RTL_TEXTENCODING_MS_1252;
1450 :
1451 0 : } else if ( aPropName == "BulletRelSize" ) {
1452 0 : nBulletRelSize = *( (sal_Int16*)pValue );
1453 0 : } else if ( aPropName == "GraphicURL" ) {
1454 0 : aGraphicURL = ( *(OUString*)pValue );
1455 : DBG(fprintf (stderr, "graphic url: %s\n", OUStringToOString( aGraphicURL, RTL_TEXTENCODING_UTF8 ).getStr()));
1456 0 : } else if ( aPropName == "GraphicSize" )
1457 : {
1458 0 : 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 0 : ::com::sun::star::awt::Size aSize;
1462 0 : 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 0 : }
1468 : }
1469 : }
1470 :
1471 0 : const char* pAutoNumType = GetAutoNumType( nNumberingType, bSDot, bPBehind, bPBoth );
1472 :
1473 0 : if( nLevel >= 0 ) {
1474 0 : 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 0 : if( nBulletRelSize && nBulletRelSize != 100 )
1482 : mpFS->singleElementNS( XML_a, XML_buSzPct,
1483 0 : XML_val, IS( std::max( (sal_Int32)25000, std::min( (sal_Int32)400000, 1000*( (sal_Int32)nBulletRelSize ) ) ) ), FSEND );
1484 0 : if( bHasFontDesc )
1485 : mpFS->singleElementNS( XML_a, XML_buFont,
1486 : XML_typeface, OUStringToOString( aFontDesc.Name, RTL_TEXTENCODING_UTF8 ).getStr(),
1487 0 : XML_charset, (aFontDesc.CharSet == awt::CharSet::SYMBOL) ? "2" : NULL,
1488 0 : FSEND );
1489 :
1490 0 : if( pAutoNumType )
1491 0 : mpFS->singleElementNS( XML_a, XML_buAutoNum, XML_type, pAutoNumType, FSEND );
1492 : else {
1493 0 : aBulletChar = SubstituteBullet( aBulletChar, aFontDesc );
1494 0 : mpFS->singleElementNS( XML_a, XML_buChar, XML_char, USS( OUString( aBulletChar ) ), FSEND );
1495 : }
1496 : }
1497 0 : }
1498 0 : }
1499 0 : }
1500 : }
1501 0 : }
1502 :
1503 0 : const char* DrawingML::GetAlignment( sal_Int32 nAlignment )
1504 : {
1505 0 : const char* sAlignment = NULL;
1506 :
1507 0 : switch( nAlignment ) {
1508 : case style::ParagraphAdjust_CENTER:
1509 0 : sAlignment = "ctr";
1510 0 : break;
1511 : case style::ParagraphAdjust_RIGHT:
1512 0 : sAlignment = "r";
1513 0 : break;
1514 : case style::ParagraphAdjust_BLOCK:
1515 0 : sAlignment = "just";
1516 0 : break;
1517 : default:
1518 : ;
1519 : }
1520 :
1521 0 : return sAlignment;
1522 : }
1523 :
1524 0 : void DrawingML::WriteLinespacing( LineSpacing& rSpacing )
1525 : {
1526 0 : if( rSpacing.Mode == LineSpacingMode::PROP )
1527 : mpFS->singleElementNS( XML_a, XML_spcPct,
1528 : XML_val, I32S( ((sal_Int32)rSpacing.Height)*1000 ),
1529 0 : FSEND );
1530 : else
1531 : mpFS->singleElementNS( XML_a, XML_spcPts,
1532 : XML_val, I32S( rSpacing.Height ),
1533 0 : FSEND );
1534 0 : }
1535 :
1536 0 : void DrawingML::WriteParagraphProperties( Reference< XTextContent > rParagraph )
1537 : {
1538 0 : Reference< XPropertySet > rXPropSet( rParagraph, UNO_QUERY );
1539 0 : Reference< XPropertyState > rXPropState( rParagraph, UNO_QUERY );
1540 : PropertyState eState;
1541 :
1542 0 : if( !rXPropSet.is() || !rXPropState.is() )
1543 0 : return;
1544 :
1545 0 : sal_Int16 nLevel = -1;
1546 0 : GET( nLevel, NumberingLevel );
1547 :
1548 0 : sal_Int16 nAlignment( style::ParagraphAdjust_LEFT );
1549 0 : GET( nAlignment, ParaAdjust );
1550 :
1551 0 : bool bHasLinespacing = false;
1552 0 : LineSpacing aLineSpacing;
1553 0 : if( GETAD( ParaLineSpacing ) )
1554 0 : bHasLinespacing = ( mAny >>= aLineSpacing );
1555 :
1556 0 : if( nLevel != -1
1557 0 : || nAlignment != style::ParagraphAdjust_LEFT
1558 0 : || bHasLinespacing ) {
1559 : mpFS->startElementNS( XML_a, XML_pPr,
1560 0 : XML_lvl, nLevel > 0 ? I32S( nLevel ) : NULL,
1561 : XML_marL, NULL,
1562 : XML_algn, GetAlignment( nAlignment ),
1563 0 : FSEND );
1564 :
1565 0 : if( bHasLinespacing ) {
1566 0 : mpFS->startElementNS( XML_a, XML_lnSpc, FSEND );
1567 0 : WriteLinespacing( aLineSpacing );
1568 0 : mpFS->endElementNS( XML_a, XML_lnSpc );
1569 : }
1570 :
1571 0 : WriteParagraphNumbering( rXPropSet, nLevel );
1572 :
1573 0 : mpFS->endElementNS( XML_a, XML_pPr );
1574 0 : }
1575 : }
1576 :
1577 0 : void DrawingML::WriteParagraph( Reference< XTextContent > rParagraph )
1578 : {
1579 0 : Reference< XEnumerationAccess > access( rParagraph, UNO_QUERY );
1580 0 : if( !access.is() )
1581 0 : return;
1582 :
1583 0 : Reference< XEnumeration > enumeration( access->createEnumeration() );
1584 0 : if( !enumeration.is() )
1585 0 : return;
1586 :
1587 0 : mpFS->startElementNS( XML_a, XML_p, FSEND );
1588 :
1589 0 : bool bPropertiesWritten = false;
1590 0 : while( enumeration->hasMoreElements() ) {
1591 0 : Reference< XTextRange > run;
1592 0 : Any any ( enumeration->nextElement() );
1593 :
1594 0 : if (any >>= run) {
1595 0 : if( !bPropertiesWritten ) {
1596 0 : WriteParagraphProperties( rParagraph );
1597 0 : bPropertiesWritten = true;
1598 : }
1599 0 : WriteRun( run );
1600 : }
1601 0 : }
1602 0 : mpFS->singleElementNS( XML_a, XML_endParaRPr, FSEND );
1603 :
1604 0 : mpFS->endElementNS( XML_a, XML_p );
1605 : }
1606 :
1607 0 : void DrawingML::WriteText( Reference< XInterface > rXIface, bool bBodyPr, bool bText, sal_Int32 nXmlNamespace )
1608 : {
1609 0 : Reference< XText > xXText( rXIface, UNO_QUERY );
1610 0 : Reference< XPropertySet > rXPropSet( rXIface, UNO_QUERY );
1611 :
1612 0 : if( !xXText.is() )
1613 0 : return;
1614 :
1615 : #define DEFLRINS 254
1616 : #define DEFTBINS 127
1617 : sal_Int32 nLeft, nRight, nTop, nBottom;
1618 0 : nLeft = nRight = DEFLRINS;
1619 0 : 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 0 : GET( nLeft, TextLeftDistance );
1624 0 : GET( nRight, TextRightDistance );
1625 0 : GET( nTop, TextUpperDistance );
1626 0 : GET( nBottom, TextLowerDistance );
1627 :
1628 0 : TextVerticalAdjust eVerticalAlignment( TextVerticalAdjust_TOP );
1629 0 : const char* sVerticalAlignment = NULL;
1630 0 : GET( eVerticalAlignment, TextVerticalAdjust );
1631 0 : if( eVerticalAlignment != TextVerticalAdjust_TOP )
1632 0 : sVerticalAlignment = GetTextVerticalAdjust(eVerticalAlignment);
1633 :
1634 0 : const char* sWritingMode = NULL;
1635 0 : bool bVertical = false;
1636 0 : if( GETA( TextWritingMode ) ) {
1637 : WritingMode eMode;
1638 :
1639 0 : if( ( mAny >>= eMode ) && eMode == WritingMode_TB_RL ) {
1640 0 : sWritingMode = "vert";
1641 0 : bVertical = true;
1642 : }
1643 : }
1644 :
1645 0 : if ( GETA( CustomShapeGeometry ) )
1646 : {
1647 0 : Sequence< PropertyValue > aProps;
1648 0 : if ( mAny >>= aProps )
1649 : {
1650 0 : for ( sal_Int32 i = 0, nElems = aProps.getLength(); i < nElems; ++i )
1651 : {
1652 0 : sal_Int32 nTextRotateAngle = 0;
1653 0 : if ( aProps[ i ].Name.equals( "TextPreRotateAngle" ) && ( aProps[ i ].Value >>= nTextRotateAngle ) )
1654 : {
1655 0 : if ( nTextRotateAngle == -90 )
1656 : {
1657 0 : sWritingMode = "vert";
1658 0 : bVertical = true;
1659 : }
1660 0 : break;
1661 : }
1662 : }
1663 0 : }
1664 : }
1665 :
1666 0 : TextHorizontalAdjust eHorizontalAlignment( TextHorizontalAdjust_CENTER );
1667 0 : bool bHorizontalCenter = false;
1668 0 : GET( eHorizontalAlignment, TextHorizontalAdjust );
1669 0 : if( eHorizontalAlignment == TextHorizontalAdjust_CENTER )
1670 0 : bHorizontalCenter = true;
1671 0 : else if( bVertical && eHorizontalAlignment == TextHorizontalAdjust_LEFT )
1672 0 : sVerticalAlignment = "b";
1673 :
1674 0 : bool bHasWrap = false;
1675 0 : bool bWrap = false;
1676 : // Only custom shapes obey the TextWordWrap option, normal text always wraps.
1677 0 : if( dynamic_cast<SvxCustomShape*>(rXIface.get()) && GETA( TextWordWrap ) ) {
1678 0 : mAny >>= bWrap;
1679 0 : bHasWrap = true;
1680 : }
1681 :
1682 0 : if (bBodyPr)
1683 : {
1684 0 : const char* pWrap = bHasWrap && !bWrap ? "none" : NULL;
1685 0 : 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 0 : uno::Reference<lang::XServiceInfo> xServiceInfo(rXIface, uno::UNO_QUERY);
1691 0 : if (xServiceInfo.is() && xServiceInfo->supportsService("com.sun.star.drawing.TextShape"))
1692 0 : pWrap = "square";
1693 : }
1694 : mpFS->singleElementNS( (nXmlNamespace ? nXmlNamespace : XML_a), XML_bodyPr,
1695 : XML_wrap, pWrap,
1696 0 : XML_lIns, (nLeft != DEFLRINS) ? IS( MM100toEMU( nLeft ) ) : NULL,
1697 0 : XML_rIns, (nRight != DEFLRINS) ? IS( MM100toEMU( nRight ) ) : NULL,
1698 0 : XML_tIns, (nTop != DEFTBINS) ? IS( MM100toEMU( nTop ) ) : NULL,
1699 0 : XML_bIns, (nBottom != DEFTBINS) ? IS( MM100toEMU( nBottom ) ) : NULL,
1700 : XML_anchor, sVerticalAlignment,
1701 : XML_anchorCtr, bHorizontalCenter ? "1" : NULL,
1702 : XML_vert, sWritingMode,
1703 0 : FSEND );
1704 : }
1705 :
1706 0 : Reference< XEnumerationAccess > access( xXText, UNO_QUERY );
1707 0 : if( !access.is() || !bText )
1708 0 : return;
1709 :
1710 0 : Reference< XEnumeration > enumeration( access->createEnumeration() );
1711 0 : if( !enumeration.is() )
1712 0 : return;
1713 :
1714 0 : SdrObject* pSdrObject = GetSdrObjectFromXShape(uno::Reference<drawing::XShape>(rXIface, uno::UNO_QUERY_THROW));
1715 0 : const SdrTextObj* pTxtObj = PTR_CAST(SdrTextObj, pSdrObject);
1716 0 : if (pTxtObj && mpTextExport)
1717 : {
1718 0 : const OutlinerParaObject* pParaObj = 0;
1719 0 : 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 0 : if (pTxtObj->IsTextEditActive())
1727 : {
1728 0 : pParaObj = pTxtObj->GetEditOutlinerParaObject();
1729 0 : bOwnParaObj = true;
1730 : }
1731 : else
1732 0 : pParaObj = pTxtObj->GetOutlinerParaObject();
1733 :
1734 0 : if (pParaObj)
1735 : {
1736 : // this is reached only in case some text is attached to the shape
1737 0 : mpTextExport->WriteOutliner(*pParaObj);
1738 0 : if (bOwnParaObj)
1739 0 : delete pParaObj;
1740 : }
1741 0 : return;
1742 : }
1743 :
1744 0 : while( enumeration->hasMoreElements() ) {
1745 0 : Reference< XTextContent > paragraph;
1746 0 : Any any ( enumeration->nextElement() );
1747 :
1748 0 : if( any >>= paragraph)
1749 0 : WriteParagraph( paragraph );
1750 0 : }
1751 :
1752 : }
1753 :
1754 0 : void DrawingML::WritePresetShape( const char* pShape )
1755 : {
1756 : mpFS->startElementNS( XML_a, XML_prstGeom,
1757 : XML_prst, pShape,
1758 0 : FSEND );
1759 0 : mpFS->singleElementNS( XML_a, XML_avLst, FSEND );
1760 0 : mpFS->endElementNS( XML_a, XML_prstGeom );
1761 0 : }
1762 :
1763 0 : void DrawingML::WritePresetShape( const char* pShape, MSO_SPT eShapeType, bool bPredefinedHandlesUsed, sal_Int32 nAdjustmentsWhichNeedsToBeConverted, const PropertyValue& rProp )
1764 : {
1765 0 : 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 0 : std::vector<OString> aAdjustments;
1768 0 : if (aAdjMap.find(OString(pShape)) != aAdjMap.end())
1769 0 : aAdjustments = aAdjMap[OString(pShape)];
1770 :
1771 : mpFS->startElementNS( XML_a, XML_prstGeom,
1772 : XML_prst, pShape,
1773 0 : FSEND );
1774 0 : mpFS->startElementNS( XML_a, XML_avLst, FSEND );
1775 :
1776 0 : Sequence< drawing::EnhancedCustomShapeAdjustmentValue > aAdjustmentSeq;
1777 0 : if ( ( rProp.Value >>= aAdjustmentSeq )
1778 0 : && eShapeType != mso_sptActionButtonForwardNext // we have adjustments values for these type of shape, but MSO doesn't like them
1779 0 : && eShapeType != mso_sptActionButtonBackPrevious // so they are now disabled
1780 0 : && 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 0 : if ( bPredefinedHandlesUsed )
1784 0 : EscherPropertyContainer::LookForPolarHandles( eShapeType, nAdjustmentsWhichNeedsToBeConverted );
1785 :
1786 0 : 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 0 : if(aAdjustments.size() == static_cast<sal_uInt32>(nLength))// In case there is a mismatch do not write the XML_gd tag.
1789 : {
1790 0 : for( sal_Int32 i=0; i < nLength; i++ )
1791 0 : 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 0 : OString aAdjName;
1795 0 : if (aAdjustmentSeq[i].Name.isEmpty() && static_cast<sal_uInt32>(i) < aAdjustments.size())
1796 0 : aAdjName = aAdjustments[i];
1797 :
1798 : mpFS->singleElementNS( XML_a, XML_gd,
1799 0 : XML_name, aAdjustmentSeq[ i ].Name.getLength() > 0 ? USS(aAdjustmentSeq[ i ].Name) : aAdjName.getStr(),
1800 0 : XML_fmla, OString("val " + OString::number( nValue )).getStr(),
1801 0 : FSEND );
1802 : }
1803 : }
1804 : }
1805 :
1806 0 : mpFS->endElementNS( XML_a, XML_avLst );
1807 0 : mpFS->endElementNS( XML_a, XML_prstGeom );
1808 0 : }
1809 :
1810 0 : void DrawingML::WritePolyPolygon( const PolyPolygon& rPolyPolygon )
1811 : {
1812 0 : if( rPolyPolygon.Count() < 1 )
1813 0 : return;
1814 :
1815 0 : mpFS->startElementNS( XML_a, XML_custGeom, FSEND );
1816 0 : mpFS->singleElementNS( XML_a, XML_avLst, FSEND );
1817 0 : mpFS->singleElementNS( XML_a, XML_gdLst, FSEND );
1818 0 : 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 0 : FSEND );
1825 :
1826 0 : mpFS->startElementNS( XML_a, XML_pathLst, FSEND );
1827 :
1828 0 : for( sal_uInt16 i = 0; i < rPolyPolygon.Count(); i ++ ) {
1829 :
1830 0 : const Polygon& rPoly = rPolyPolygon[ i ];
1831 0 : Rectangle aRect( rPoly.GetBoundRect() );
1832 :
1833 : mpFS->startElementNS( XML_a, XML_path,
1834 0 : XML_w, I64S( aRect.GetWidth() ),
1835 0 : XML_h, I64S( aRect.GetHeight() ),
1836 0 : FSEND );
1837 :
1838 0 : if( rPoly.GetSize() > 0 )
1839 : {
1840 0 : mpFS->startElementNS( XML_a, XML_moveTo, FSEND );
1841 :
1842 : mpFS->singleElementNS( XML_a, XML_pt,
1843 0 : XML_x, I64S( rPoly[ 0 ].X() - aRect.Left() ),
1844 0 : XML_y, I64S( rPoly[ 0 ].Y() - aRect.Top() ),
1845 0 : FSEND );
1846 :
1847 0 : mpFS->endElementNS( XML_a, XML_moveTo );
1848 : }
1849 :
1850 0 : for( sal_uInt16 j = 1; j < rPoly.GetSize(); j ++ )
1851 : {
1852 0 : enum PolyFlags flags = rPoly.GetFlags(j);
1853 0 : if( flags == POLY_CONTROL )
1854 : {
1855 : // a:cubicBezTo can only contain 3 a:pt elements, so we need to make sure of this
1856 0 : if( j+2 < rPoly.GetSize() && rPoly.GetFlags(j+1) == POLY_CONTROL && rPoly.GetFlags(j+2) != POLY_CONTROL )
1857 : {
1858 :
1859 0 : mpFS->startElementNS( XML_a, XML_cubicBezTo, FSEND );
1860 0 : for( sal_uInt8 k = 0; k <= 2; ++k )
1861 : {
1862 : mpFS->singleElementNS( XML_a, XML_pt,
1863 0 : XML_x, I64S( rPoly[j+k].X() - aRect.Left() ),
1864 0 : XML_y, I64S( rPoly[j+k].Y() - aRect.Top() ),
1865 0 : FSEND );
1866 :
1867 : }
1868 0 : mpFS->endElementNS( XML_a, XML_cubicBezTo );
1869 0 : j += 2;
1870 : }
1871 : }
1872 0 : else if( flags == POLY_NORMAL )
1873 : {
1874 0 : mpFS->startElementNS( XML_a, XML_lnTo, FSEND );
1875 : mpFS->singleElementNS( XML_a, XML_pt,
1876 0 : XML_x, I64S( rPoly[j].X() - aRect.Left() ),
1877 0 : XML_y, I64S( rPoly[j].Y() - aRect.Top() ),
1878 0 : FSEND );
1879 0 : mpFS->endElementNS( XML_a, XML_lnTo );
1880 : }
1881 : }
1882 :
1883 0 : mpFS->endElementNS( XML_a, XML_path );
1884 : }
1885 :
1886 0 : mpFS->endElementNS( XML_a, XML_pathLst );
1887 :
1888 0 : 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 0 : sal_Unicode DrawingML::SubstituteBullet( sal_Unicode cBulletId, ::com::sun::star::awt::FontDescriptor& rFontDesc )
1906 : {
1907 0 : if ( IsStarSymbol(rFontDesc.Name) )
1908 : {
1909 0 : rtl_TextEncoding eCharSet = rFontDesc.CharSet;
1910 0 : cBulletId = msfilter::util::bestFitOpenSymbolToMSFont(cBulletId, eCharSet, rFontDesc.Name);
1911 0 : rFontDesc.CharSet = eCharSet;
1912 : }
1913 :
1914 0 : return cBulletId;
1915 : }
1916 :
1917 0 : 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 0 : OUString sRelationshipId;
1926 0 : if (xParentRelation.is())
1927 0 : sRelationshipId = GetFB()->addRelation( xParentRelation, OUString::createFromAscii( sRelationshipType), sRelativeStream );
1928 : else
1929 0 : sRelationshipId = GetFB()->addRelation( OUString::createFromAscii( sRelationshipType ), sRelativeStream );
1930 :
1931 0 : if( pRelationshipId )
1932 0 : *pRelationshipId = sRelationshipId;
1933 :
1934 0 : sax_fastparser::FSHelperPtr p = GetFB()->openFragmentStreamWithSerializer( sFullStream, OUString::createFromAscii( sContentType ) );
1935 :
1936 0 : return p;
1937 : }
1938 :
1939 0 : void DrawingML::WriteFill( Reference< XPropertySet > xPropSet )
1940 : {
1941 0 : if ( !GetProperty( xPropSet, "FillStyle" ) )
1942 0 : return;
1943 0 : FillStyle aFillStyle( FillStyle_NONE );
1944 0 : xPropSet->getPropertyValue( "FillStyle" ) >>= aFillStyle;
1945 :
1946 0 : if ( aFillStyle == FillStyle_SOLID && GetProperty( xPropSet, "FillTransparence" ) )
1947 : {
1948 : // map full transparent background to no fill
1949 0 : sal_Int16 nVal = 0;
1950 0 : xPropSet->getPropertyValue( "FillTransparence" ) >>= nVal;
1951 0 : if ( nVal == 100 )
1952 0 : aFillStyle = FillStyle_NONE;
1953 : }
1954 :
1955 0 : switch( aFillStyle )
1956 : {
1957 : case FillStyle_SOLID :
1958 0 : WriteSolidFill( xPropSet );
1959 0 : break;
1960 : case FillStyle_GRADIENT :
1961 0 : WriteGradientFill( xPropSet );
1962 0 : break;
1963 : case FillStyle_BITMAP :
1964 0 : WriteBlipFill( xPropSet, "FillBitmapURL" );
1965 0 : break;
1966 : case FillStyle_HATCH :
1967 0 : WritePattFill( xPropSet );
1968 0 : break;
1969 : case FillStyle_NONE:
1970 0 : mpFS->singleElementNS( XML_a, XML_noFill, FSEND );
1971 0 : break;
1972 : default:
1973 : ;
1974 : }
1975 :
1976 0 : return;
1977 : }
1978 :
1979 0 : void DrawingML::WriteStyleProperties( sal_Int32 nTokenId, Sequence< PropertyValue > aProperties )
1980 : {
1981 0 : if( aProperties.getLength() > 0 )
1982 : {
1983 0 : OUString sSchemeClr;
1984 0 : sal_uInt32 nIdx = 0;
1985 0 : Sequence< PropertyValue > aTransformations;
1986 0 : for( sal_Int32 i=0; i < aProperties.getLength(); ++i)
1987 0 : if( aProperties[i].Name == "SchemeClr" )
1988 0 : aProperties[i].Value >>= sSchemeClr;
1989 0 : else if( aProperties[i].Name == "Idx" )
1990 0 : aProperties[i].Value >>= nIdx;
1991 0 : else if( aProperties[i].Name == "Transformations" )
1992 0 : aProperties[i].Value >>= aTransformations;
1993 0 : mpFS->startElementNS( XML_a, nTokenId, XML_idx, I32S( nIdx ), FSEND );
1994 0 : WriteColor( sSchemeClr, aTransformations );
1995 0 : mpFS->endElementNS( XML_a, nTokenId );
1996 : }
1997 : else
1998 : // write mock <a:*Ref> tag
1999 0 : mpFS->singleElementNS( XML_a, nTokenId, XML_idx, I32S( 0 ), FSEND );
2000 0 : }
2001 :
2002 0 : void DrawingML::WriteShapeStyle( Reference< XPropertySet > xPropSet )
2003 : {
2004 : // check existence of the grab bag
2005 0 : if ( !GetProperty( xPropSet, "InteropGrabBag" ) )
2006 0 : return;
2007 :
2008 : // extract the relevant properties from the grab bag
2009 0 : Sequence< PropertyValue > aGrabBag;
2010 0 : Sequence< PropertyValue > aFillRefProperties, aLnRefProperties, aEffectRefProperties;
2011 0 : mAny >>= aGrabBag;
2012 0 : for( sal_Int32 i=0; i < aGrabBag.getLength(); ++i)
2013 0 : if( aGrabBag[i].Name == "StyleFillRef" )
2014 0 : aGrabBag[i].Value >>= aFillRefProperties;
2015 0 : else if( aGrabBag[i].Name == "StyleLnRef" )
2016 0 : aGrabBag[i].Value >>= aLnRefProperties;
2017 0 : else if( aGrabBag[i].Name == "StyleEffectRef" )
2018 0 : aGrabBag[i].Value >>= aEffectRefProperties;
2019 :
2020 0 : WriteStyleProperties( XML_lnRef, aLnRefProperties );
2021 0 : WriteStyleProperties( XML_fillRef, aFillRefProperties );
2022 0 : WriteStyleProperties( XML_effectRef, aEffectRefProperties );
2023 :
2024 : // write mock <a:fontRef>
2025 0 : mpFS->singleElementNS( XML_a, XML_fontRef, XML_idx, "minor", FSEND );
2026 : }
2027 :
2028 : }
2029 0 : }
2030 :
2031 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|