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 <config_folders.h>
21 : #include "rtl/bootstrap.hxx"
22 : #include "oox/core/xmlfilterbase.hxx"
23 : #include "oox/export/drawingml.hxx"
24 : #include "oox/export/utils.hxx"
25 : #include <oox/drawingml/color.hxx>
26 : #include <oox/drawingml/fillproperties.hxx>
27 : #include <oox/token/tokens.hxx>
28 : #include <oox/drawingml/drawingmltypes.hxx>
29 :
30 : #include <cstdio>
31 : #include <com/sun/star/awt/CharSet.hpp>
32 : #include <com/sun/star/awt/FontDescriptor.hpp>
33 : #include <com/sun/star/awt/FontSlant.hpp>
34 : #include <com/sun/star/awt/FontStrikeout.hpp>
35 : #include <com/sun/star/awt/FontWeight.hpp>
36 : #include <com/sun/star/awt/FontUnderline.hpp>
37 : #include <com/sun/star/awt/Gradient.hpp>
38 : #include <com/sun/star/beans/XPropertySet.hpp>
39 : #include <com/sun/star/beans/XPropertyState.hpp>
40 : #include <com/sun/star/beans/Property.hpp>
41 : #include <com/sun/star/beans/XPropertySetInfo.hpp>
42 : #include <com/sun/star/container/XEnumerationAccess.hpp>
43 : #include <com/sun/star/container/XIndexAccess.hpp>
44 : #include <com/sun/star/drawing/BitmapMode.hpp>
45 : #include <com/sun/star/drawing/EnhancedCustomShapeAdjustmentValue.hpp>
46 : #include <com/sun/star/drawing/EnhancedCustomShapeParameterType.hpp>
47 : #include <com/sun/star/drawing/EnhancedCustomShapeParameterPair.hpp>
48 : #include <com/sun/star/drawing/EnhancedCustomShapeSegment.hpp>
49 : #include <com/sun/star/drawing/EnhancedCustomShapeSegmentCommand.hpp>
50 : #include <com/sun/star/drawing/LineDash.hpp>
51 : #include <com/sun/star/drawing/LineJoint.hpp>
52 : #include <com/sun/star/drawing/LineStyle.hpp>
53 : #include <com/sun/star/drawing/TextHorizontalAdjust.hpp>
54 : #include <com/sun/star/drawing/TextVerticalAdjust.hpp>
55 : #include <com/sun/star/drawing/XShape.hpp>
56 : #include <com/sun/star/drawing/FillStyle.hpp>
57 : #include <com/sun/star/geometry/IntegerRectangle2D.hpp>
58 : #include <com/sun/star/i18n/ScriptType.hpp>
59 : #include <com/sun/star/io/XOutputStream.hpp>
60 : #include <com/sun/star/style/LineSpacing.hpp>
61 : #include <com/sun/star/style/LineSpacingMode.hpp>
62 : #include <com/sun/star/style/ParagraphAdjust.hpp>
63 : #include <com/sun/star/text/WritingMode.hpp>
64 : #include <com/sun/star/text/WritingMode2.hpp>
65 : #include <com/sun/star/text/GraphicCrop.hpp>
66 : #include <com/sun/star/text/XText.hpp>
67 : #include <com/sun/star/text/XTextContent.hpp>
68 : #include <com/sun/star/text/XTextField.hpp>
69 : #include <com/sun/star/text/XTextRange.hpp>
70 : #include <com/sun/star/style/CaseMap.hpp>
71 : #include <tools/stream.hxx>
72 : #include <unotools/fontdefs.hxx>
73 : #include <vcl/cvtgrf.hxx>
74 : #include <vcl/graph.hxx>
75 : #include <vcl/settings.hxx>
76 : #include <svtools/grfmgr.hxx>
77 : #include <rtl/strbuf.hxx>
78 : #include <sfx2/app.hxx>
79 : #include <svl/languageoptions.hxx>
80 : #include <filter/msfilter/escherex.hxx>
81 : #include <filter/msfilter/util.hxx>
82 : #include <editeng/outlobj.hxx>
83 : #include <editeng/svxenum.hxx>
84 : #include <svx/unoapi.hxx>
85 : #include <svx/svdoashp.hxx>
86 : #include <svx/unoshape.hxx>
87 :
88 : using namespace ::css;
89 : using namespace ::css::beans;
90 : using namespace ::css::drawing;
91 : using namespace ::css::i18n;
92 : using namespace ::css::style;
93 : using namespace ::css::text;
94 : using namespace ::css::uno;
95 : using namespace ::css::container;
96 : using namespace ::css::text;
97 :
98 : using ::css::geometry::IntegerRectangle2D;
99 : using ::css::io::XOutputStream;
100 : using ::sax_fastparser::FSHelperPtr;
101 : using ::sax_fastparser::FastSerializerHelper;
102 :
103 : namespace oox {
104 : namespace drawingml {
105 :
106 : #define GETA(propName) \
107 : GetProperty( rXPropSet, OUString( #propName ) )
108 :
109 : #define GETAD(propName) \
110 : ( GetPropertyAndState( rXPropSet, rXPropState, OUString( #propName ), eState ) && eState == beans::PropertyState_DIRECT_VALUE )
111 :
112 : #define GET(variable, propName) \
113 : if ( GETA(propName) ) \
114 : mAny >>= variable;
115 :
116 : // not thread safe
117 : int DrawingML::mnImageCounter = 1;
118 : int DrawingML::mnWdpImageCounter = 1;
119 82 : std::map<OUString, OUString> DrawingML::maWdpCache;
120 :
121 508 : void DrawingML::ResetCounters()
122 : {
123 508 : mnImageCounter = 1;
124 508 : mnWdpImageCounter = 1;
125 508 : maWdpCache.clear();
126 508 : }
127 :
128 37257 : bool DrawingML::GetProperty( Reference< XPropertySet > rXPropertySet, const OUString& aName )
129 : {
130 : try
131 : {
132 37257 : mAny = rXPropertySet->getPropertyValue(aName);
133 33243 : if (mAny.hasValue())
134 31245 : return true;
135 : }
136 4014 : catch( const Exception& )
137 : {
138 : /* printf ("exception when trying to get value of property: %s\n", USS(aName)); */
139 : }
140 6012 : return false;
141 : }
142 :
143 3790 : bool DrawingML::GetPropertyAndState( Reference< XPropertySet > rXPropertySet, Reference< XPropertyState > rXPropertyState, const OUString& aName, PropertyState& eState )
144 : {
145 : try
146 : {
147 3790 : mAny = rXPropertySet->getPropertyValue(aName);
148 3790 : if (mAny.hasValue())
149 : {
150 3778 : eState = rXPropertyState->getPropertyState(aName);
151 3778 : return true;
152 : }
153 : }
154 0 : catch( const Exception& )
155 : {
156 : /* printf ("exception when trying to get value of property: %s\n", USS(aName)); */
157 : }
158 12 : return false;
159 : }
160 :
161 1815 : void DrawingML::WriteColor( sal_uInt32 nColor, sal_Int32 nAlpha )
162 : {
163 : // Transparency is a separate element.
164 1815 : OString sColor = OString::number( nColor & 0x00FFFFFF, 16 );
165 1815 : if( sColor.getLength() < 6 )
166 : {
167 489 : OStringBuffer sBuf( "0" );
168 489 : int remains = 5 - sColor.getLength();
169 :
170 2766 : while( remains > 0 )
171 : {
172 1788 : sBuf.append( "0" );
173 1788 : remains--;
174 : }
175 :
176 489 : sBuf.append( sColor );
177 :
178 489 : sColor = sBuf.getStr();
179 : }
180 1815 : if( nAlpha < MAX_PERCENT )
181 : {
182 37 : mpFS->startElementNS( XML_a, XML_srgbClr, XML_val, sColor.getStr(), FSEND );
183 37 : mpFS->singleElementNS( XML_a, XML_alpha, XML_val, OString::number(nAlpha), FSEND );
184 37 : mpFS->endElementNS( XML_a, XML_srgbClr );
185 :
186 : }
187 : else
188 : {
189 1778 : mpFS->singleElementNS( XML_a, XML_srgbClr, XML_val, sColor.getStr(), FSEND );
190 1815 : }
191 1815 : }
192 :
193 531 : void DrawingML::WriteColor( const OUString& sColorSchemeName, const Sequence< PropertyValue >& aTransformations )
194 : {
195 : // prevent writing a tag with empty val attribute
196 531 : if( sColorSchemeName.isEmpty() )
197 623 : return;
198 :
199 439 : if( aTransformations.hasElements() )
200 : {
201 : mpFS->startElementNS( XML_a, XML_schemeClr,
202 : XML_val, USS( sColorSchemeName ),
203 130 : FSEND );
204 130 : WriteColorTransformations( aTransformations );
205 130 : mpFS->endElementNS( XML_a, XML_schemeClr );
206 : }
207 : else
208 : {
209 : mpFS->singleElementNS( XML_a, XML_schemeClr,
210 : XML_val, USS( sColorSchemeName ),
211 309 : FSEND );
212 : }
213 : }
214 :
215 130 : void DrawingML::WriteColorTransformations( const Sequence< PropertyValue >& aTransformations )
216 : {
217 338 : for( sal_Int32 i = 0; i < aTransformations.getLength(); i++ )
218 : {
219 208 : sal_Int32 nToken = Color::getColorTransformationToken( aTransformations[i].Name );
220 208 : if( nToken != XML_TOKEN_INVALID && aTransformations[i].Value.hasValue() )
221 : {
222 206 : sal_Int32 nValue = aTransformations[i].Value.get<sal_Int32>();
223 206 : mpFS->singleElementNS( XML_a, nToken, XML_val, I32S( nValue ), FSEND );
224 : }
225 : }
226 130 : }
227 :
228 1562 : void DrawingML::WriteSolidFill( sal_uInt32 nColor, sal_Int32 nAlpha )
229 : {
230 1562 : mpFS->startElementNS( XML_a, XML_solidFill, FSEND );
231 1562 : WriteColor( nColor, nAlpha );
232 1562 : mpFS->endElementNS( XML_a, XML_solidFill );
233 1562 : }
234 :
235 84 : void DrawingML::WriteSolidFill( const OUString& sSchemeName, const Sequence< PropertyValue >& aTransformations )
236 : {
237 84 : mpFS->startElementNS( XML_a, XML_solidFill, FSEND );
238 84 : WriteColor( sSchemeName, aTransformations );
239 84 : mpFS->endElementNS( XML_a, XML_solidFill );
240 84 : }
241 :
242 611 : void DrawingML::WriteSolidFill( Reference< XPropertySet > rXPropSet )
243 : {
244 : // get fill color
245 611 : if ( !GetProperty( rXPropSet, "FillColor" ) )
246 612 : return;
247 610 : sal_uInt32 nFillColor = mAny.get<sal_uInt32>();
248 :
249 : // get InteropGrabBag and search the relevant attributes
250 610 : OUString sColorFillScheme;
251 610 : sal_uInt32 nOriginalColor = 0;
252 1220 : Sequence< PropertyValue > aStyleProperties, aTransformations;
253 610 : if ( GetProperty( rXPropSet, "InteropGrabBag" ) )
254 : {
255 319 : Sequence< PropertyValue > aGrabBag;
256 319 : mAny >>= aGrabBag;
257 1430 : for( sal_Int32 i=0; i < aGrabBag.getLength(); ++i )
258 : {
259 1111 : if( aGrabBag[i].Name == "SpPrSolidFillSchemeClr" )
260 51 : aGrabBag[i].Value >>= sColorFillScheme;
261 1060 : else if( aGrabBag[i].Name == "OriginalSolidFillClr" )
262 192 : aGrabBag[i].Value >>= nOriginalColor;
263 868 : else if( aGrabBag[i].Name == "StyleFillRef" )
264 69 : aGrabBag[i].Value >>= aStyleProperties;
265 799 : else if( aGrabBag[i].Name == "SpPrSolidFillSchemeClrTransformations" )
266 51 : aGrabBag[i].Value >>= aTransformations;
267 319 : }
268 : }
269 :
270 610 : sal_Int32 nAlpha = MAX_PERCENT;
271 610 : if( GetProperty( rXPropSet, "FillTransparence" ) )
272 : {
273 610 : sal_Int32 nTransparency = 0;
274 610 : mAny >>= nTransparency;
275 : // Calculate alpha value (see oox/source/drawingml/color.cxx : getTransparency())
276 610 : nAlpha = (MAX_PERCENT - ( PER_PERCENT * nTransparency ) );
277 : }
278 :
279 : // write XML
280 610 : if ( nFillColor != nOriginalColor )
281 : {
282 : // the user has set a different color for the shape
283 398 : WriteSolidFill( nFillColor & 0xffffff, nAlpha );
284 : }
285 212 : else if ( !sColorFillScheme.isEmpty() )
286 : {
287 : // the shape had a scheme color and the user didn't change it
288 48 : WriteSolidFill( sColorFillScheme, aTransformations );
289 : }
290 164 : else if ( aStyleProperties.hasElements() )
291 : {
292 56 : sal_uInt32 nThemeColor = 0;
293 168 : for( sal_Int32 i=0; i < aStyleProperties.getLength(); ++i )
294 : {
295 168 : if( aStyleProperties[i].Name == "Color" )
296 : {
297 56 : aStyleProperties[i].Value >>= nThemeColor;
298 56 : break;
299 : }
300 : }
301 56 : if ( nFillColor != nThemeColor )
302 : // the shape contains a theme but it wasn't being used
303 3 : WriteSolidFill( nFillColor & 0xffffff, nAlpha );
304 : // in case the shape used the style color and the user didn't change it,
305 : // we must not write a <a: solidFill> tag.
306 : }
307 : else
308 : {
309 : // the shape had a custom color and the user didn't change it
310 108 : WriteSolidFill( nFillColor & 0xffffff, nAlpha );
311 610 : }
312 : }
313 :
314 15 : void DrawingML::WriteGradientStop( sal_uInt16 nStop, sal_uInt32 nColor )
315 : {
316 : mpFS->startElementNS( XML_a, XML_gs,
317 : XML_pos, I32S( nStop * 1000 ),
318 15 : FSEND );
319 15 : WriteColor( nColor );
320 15 : mpFS->endElementNS( XML_a, XML_gs );
321 15 : }
322 :
323 15 : sal_uInt32 DrawingML::ColorWithIntensity( sal_uInt32 nColor, sal_uInt32 nIntensity )
324 : {
325 15 : return ( ( ( nColor & 0xff ) * nIntensity ) / 100 )
326 15 : | ( ( ( ( ( nColor & 0xff00 ) >> 8 ) * nIntensity ) / 100 ) << 8 )
327 15 : | ( ( ( ( ( nColor & 0xff0000 ) >> 8 ) * nIntensity ) / 100 ) << 8 );
328 : }
329 :
330 60 : bool DrawingML::EqualGradients( awt::Gradient aGradient1, awt::Gradient aGradient2 )
331 : {
332 116 : return aGradient1.Style == aGradient2.Style &&
333 110 : aGradient1.StartColor == aGradient2.StartColor &&
334 108 : aGradient1.EndColor == aGradient2.EndColor &&
335 108 : aGradient1.Angle == aGradient2.Angle &&
336 108 : aGradient1.Border == aGradient2.Border &&
337 108 : aGradient1.XOffset == aGradient2.XOffset &&
338 108 : aGradient1.YOffset == aGradient2.YOffset &&
339 108 : aGradient1.StartIntensity == aGradient2.StartIntensity &&
340 168 : aGradient1.EndIntensity == aGradient2.EndIntensity &&
341 114 : aGradient1.StepCount == aGradient2.StepCount;
342 : }
343 :
344 60 : void DrawingML::WriteGradientFill( Reference< XPropertySet > rXPropSet )
345 : {
346 60 : awt::Gradient aGradient;
347 60 : if( GETA( FillGradient ) )
348 : {
349 60 : aGradient = *static_cast< const awt::Gradient* >( mAny.getValue() );
350 :
351 : // get InteropGrabBag and search the relevant attributes
352 60 : awt::Gradient aOriginalGradient;
353 60 : Sequence< PropertyValue > aGradientStops;
354 60 : if ( GetProperty( rXPropSet, "InteropGrabBag" ) )
355 : {
356 56 : Sequence< PropertyValue > aGrabBag;
357 56 : mAny >>= aGrabBag;
358 383 : for( sal_Int32 i=0; i < aGrabBag.getLength(); ++i )
359 327 : if( aGrabBag[i].Name == "GradFillDefinition" )
360 52 : aGrabBag[i].Value >>= aGradientStops;
361 275 : else if( aGrabBag[i].Name == "OriginalGradFill" )
362 110 : aGrabBag[i].Value >>= aOriginalGradient;
363 : }
364 :
365 : // check if an ooxml gradient had been imported and if the user has modified it
366 60 : if( EqualGradients( aOriginalGradient, aGradient ) )
367 : {
368 : // If we have no gradient stops that means original gradient were defined by a theme.
369 54 : if( aGradientStops.hasElements() )
370 : {
371 52 : mpFS->startElementNS( XML_a, XML_gradFill, FSEND );
372 52 : WriteGrabBagGradientFill(aGradientStops, aGradient);
373 52 : mpFS->endElementNS( XML_a, XML_gradFill );
374 : }
375 : }
376 : else
377 : {
378 6 : mpFS->startElementNS( XML_a, XML_gradFill, FSEND );
379 6 : WriteGradientFill(aGradient);
380 6 : mpFS->endElementNS( XML_a, XML_gradFill );
381 60 : }
382 : }
383 60 : }
384 :
385 52 : void DrawingML::WriteGrabBagGradientFill( const Sequence< PropertyValue >& aGradientStops, awt::Gradient rGradient )
386 : {
387 : // write back the original gradient
388 52 : mpFS->startElementNS( XML_a, XML_gsLst, FSEND );
389 :
390 : // get original stops and write them
391 161 : for( sal_Int32 i=0; i < aGradientStops.getLength(); ++i )
392 : {
393 109 : Sequence< PropertyValue > aGradientStop;
394 109 : aGradientStops[i].Value >>= aGradientStop;
395 :
396 : // get values
397 218 : OUString sSchemeClr;
398 109 : double nPos = 0;
399 109 : sal_Int16 nTransparency = 0;
400 109 : sal_Int32 nRgbClr = 0;
401 218 : Sequence< PropertyValue > aTransformations;
402 436 : for( sal_Int32 j=0; j < aGradientStop.getLength(); ++j )
403 : {
404 327 : if( aGradientStop[j].Name == "SchemeClr" )
405 50 : aGradientStop[j].Value >>= sSchemeClr;
406 277 : else if( aGradientStop[j].Name == "RgbClr" )
407 59 : aGradientStop[j].Value >>= nRgbClr;
408 218 : else if( aGradientStop[j].Name == "Pos" )
409 109 : aGradientStop[j].Value >>= nPos;
410 109 : else if( aGradientStop[j].Name == "Transparency" )
411 9 : aGradientStop[j].Value >>= nTransparency;
412 100 : else if( aGradientStop[j].Name == "Transformations" )
413 50 : aGradientStop[j].Value >>= aTransformations;
414 : }
415 : // write stop
416 : mpFS->startElementNS( XML_a, XML_gs,
417 : XML_pos, OString::number( nPos * 100000.0 ).getStr(),
418 109 : FSEND );
419 109 : if( sSchemeClr.isEmpty() )
420 : {
421 : // Calculate alpha value (see oox/source/drawingml/color.cxx : getTransparency())
422 59 : sal_Int32 nAlpha = (MAX_PERCENT - ( PER_PERCENT * nTransparency ) );
423 59 : WriteColor( nRgbClr, nAlpha );
424 : }
425 : else
426 : {
427 50 : WriteColor( sSchemeClr, aTransformations );
428 : }
429 109 : mpFS->endElementNS( XML_a, XML_gs );
430 109 : }
431 52 : mpFS->endElementNS( XML_a, XML_gsLst );
432 :
433 : mpFS->singleElementNS( XML_a, XML_lin,
434 52 : XML_ang, I32S( ( ( ( 3600 - rGradient.Angle + 900 ) * 6000 ) % 21600000 ) ),
435 52 : FSEND );
436 52 : }
437 :
438 6 : void DrawingML::WriteGradientFill( awt::Gradient rGradient )
439 : {
440 6 : switch( rGradient.Style )
441 : {
442 : default:
443 : case GradientStyle_LINEAR:
444 2 : mpFS->startElementNS( XML_a, XML_gsLst, FSEND );
445 2 : WriteGradientStop( 0, ColorWithIntensity( rGradient.StartColor, rGradient.StartIntensity ) );
446 2 : WriteGradientStop( 100, ColorWithIntensity( rGradient.EndColor, rGradient.EndIntensity ) );
447 2 : mpFS->endElementNS( XML_a, XML_gsLst );
448 : mpFS->singleElementNS( XML_a, XML_lin,
449 2 : XML_ang, I32S( ( ( ( 3600 - rGradient.Angle + 900 ) * 6000 ) % 21600000 ) ),
450 2 : FSEND );
451 2 : break;
452 :
453 : case GradientStyle_AXIAL:
454 3 : mpFS->startElementNS( XML_a, XML_gsLst, FSEND );
455 3 : WriteGradientStop( 0, ColorWithIntensity( rGradient.EndColor, rGradient.EndIntensity ) );
456 3 : WriteGradientStop( 50, ColorWithIntensity( rGradient.StartColor, rGradient.StartIntensity ) );
457 3 : WriteGradientStop( 100, ColorWithIntensity( rGradient.EndColor, rGradient.EndIntensity ) );
458 3 : mpFS->endElementNS( XML_a, XML_gsLst );
459 : mpFS->singleElementNS( XML_a, XML_lin,
460 3 : XML_ang, I32S( ( ( ( 3600 - rGradient.Angle + 900 ) * 6000 ) % 21600000 ) ),
461 3 : FSEND );
462 3 : break;
463 :
464 : /* I don't see how to apply transformation to gradients, so
465 : * elliptical will end as radial and square as
466 : * rectangular. also position offsets are not applied */
467 : case GradientStyle_RADIAL:
468 : case GradientStyle_ELLIPTICAL:
469 : case GradientStyle_RECT:
470 : case GradientStyle_SQUARE:
471 1 : mpFS->startElementNS( XML_a, XML_gsLst, FSEND );
472 1 : WriteGradientStop( 0, ColorWithIntensity( rGradient.EndColor, rGradient.EndIntensity ) );
473 1 : WriteGradientStop( 100, ColorWithIntensity( rGradient.StartColor, rGradient.StartIntensity ) );
474 1 : mpFS->endElementNS( XML_a, XML_gsLst );
475 : mpFS->singleElementNS( XML_a, XML_path,
476 2 : XML_path, ( rGradient.Style == awt::GradientStyle_RADIAL || rGradient.Style == awt::GradientStyle_ELLIPTICAL ) ? "circle" : "rect",
477 1 : FSEND );
478 1 : break;
479 : }
480 6 : }
481 :
482 1362 : void DrawingML::WriteLineArrow( Reference< XPropertySet > rXPropSet, bool bLineStart )
483 : {
484 : ESCHER_LineEnd eLineEnd;
485 : sal_Int32 nArrowLength;
486 : sal_Int32 nArrowWidth;
487 :
488 1362 : if ( EscherPropertyContainer::GetLineArrow( bLineStart, rXPropSet, eLineEnd, nArrowLength, nArrowWidth ) )
489 : {
490 : const char* len;
491 : const char* type;
492 : const char* width;
493 :
494 27 : switch( nArrowLength )
495 : {
496 : case ESCHER_LineShortArrow:
497 1 : len = "sm";
498 1 : break;
499 : default:
500 : case ESCHER_LineMediumLenArrow:
501 26 : len = "med";
502 26 : break;
503 : case ESCHER_LineLongArrow:
504 0 : len = "lg";
505 0 : break;
506 : }
507 :
508 27 : switch( eLineEnd )
509 : {
510 : default:
511 : case ESCHER_LineNoEnd:
512 0 : type = "none";
513 0 : break;
514 : case ESCHER_LineArrowEnd:
515 21 : type = "triangle";
516 21 : break;
517 : case ESCHER_LineArrowStealthEnd:
518 1 : type = "stealth";
519 1 : break;
520 : case ESCHER_LineArrowDiamondEnd:
521 2 : type = "diamond";
522 2 : break;
523 : case ESCHER_LineArrowOvalEnd:
524 0 : type = "oval";
525 0 : break;
526 : case ESCHER_LineArrowOpenEnd:
527 3 : type = "arrow";
528 3 : break;
529 : }
530 :
531 27 : switch( nArrowWidth )
532 : {
533 : case ESCHER_LineNarrowArrow:
534 1 : width = "sm";
535 1 : break;
536 : default:
537 : case ESCHER_LineMediumWidthArrow:
538 26 : width = "med";
539 26 : break;
540 : case ESCHER_LineWideArrow:
541 0 : width = "lg";
542 0 : break;
543 : }
544 :
545 : mpFS->singleElementNS( XML_a, bLineStart ? XML_headEnd : XML_tailEnd,
546 : XML_len, len,
547 : XML_type, type,
548 : XML_w, width,
549 27 : FSEND );
550 : }
551 1362 : }
552 :
553 1286 : void DrawingML::WriteOutline( Reference<XPropertySet> rXPropSet )
554 : {
555 1286 : drawing::LineStyle aLineStyle( drawing::LineStyle_NONE );
556 :
557 1286 : GET( aLineStyle, LineStyle );
558 :
559 1286 : sal_uInt32 nLineWidth = 0;
560 1286 : sal_uInt32 nColor = 0;
561 1286 : bool bColorSet = false;
562 1286 : const char* cap = NULL;
563 1286 : drawing::LineDash aLineDash;
564 1286 : bool bDashSet = false;
565 1286 : bool bNoFill = false;
566 :
567 : // get InteropGrabBag and search the relevant attributes
568 1286 : OUString sColorFillScheme;
569 :
570 1286 : sal_uInt32 nOriginalColor = 0;
571 1286 : sal_uInt32 nStyleColor = 0;
572 1286 : sal_uInt32 nStyleLineWidth = 0;
573 :
574 2572 : Sequence<PropertyValue> aStyleProperties;
575 2572 : Sequence<PropertyValue> aTransformations;
576 :
577 1286 : drawing::LineStyle aStyleLineStyle(drawing::LineStyle_NONE);
578 1286 : drawing::LineJoint aStyleLineJoint(drawing::LineJoint_NONE);
579 :
580 1286 : if (GetProperty(rXPropSet, "InteropGrabBag"))
581 : {
582 633 : Sequence<PropertyValue> aGrabBag;
583 633 : mAny >>= aGrabBag;
584 :
585 2621 : for (sal_Int32 i=0; i < aGrabBag.getLength(); ++i)
586 : {
587 1988 : if( aGrabBag[i].Name == "SpPrLnSolidFillSchemeClr" )
588 39 : aGrabBag[i].Value >>= sColorFillScheme;
589 1949 : else if( aGrabBag[i].Name == "OriginalLnSolidFillClr" )
590 383 : aGrabBag[i].Value >>= nOriginalColor;
591 1566 : else if( aGrabBag[i].Name == "StyleLnRef" )
592 144 : aGrabBag[i].Value >>= aStyleProperties;
593 1422 : else if( aGrabBag[i].Name == "SpPrLnSolidFillSchemeClrTransformations" )
594 39 : aGrabBag[i].Value >>= aTransformations;
595 : }
596 633 : if (aStyleProperties.hasElements())
597 : {
598 1152 : for (sal_Int32 i=0; i < aStyleProperties.getLength(); ++i)
599 : {
600 1008 : if( aStyleProperties[i].Name == "Color" )
601 144 : aStyleProperties[i].Value >>= nStyleColor;
602 864 : else if( aStyleProperties[i].Name == "LineStyle" )
603 144 : aStyleProperties[i].Value >>= aStyleLineStyle;
604 720 : else if( aStyleProperties[i].Name == "LineJoint" )
605 144 : aStyleProperties[i].Value >>= aStyleLineJoint;
606 576 : else if( aStyleProperties[i].Name == "LineWidth" )
607 144 : aStyleProperties[i].Value >>= nStyleLineWidth;
608 : }
609 633 : }
610 : }
611 :
612 1286 : GET( nLineWidth, LineWidth );
613 :
614 1286 : switch (aLineStyle)
615 : {
616 : case drawing::LineStyle_NONE:
617 605 : bNoFill = true;
618 605 : break;
619 : case drawing::LineStyle_DASH:
620 19 : if (GetProperty(rXPropSet, "LineDash"))
621 : {
622 19 : aLineDash = mAny.get<drawing::LineDash>();
623 19 : bDashSet = true;
624 19 : if (aLineDash.Style == DashStyle_ROUND || aLineDash.Style == DashStyle_ROUNDRELATIVE)
625 : {
626 9 : cap = "rnd";
627 : }
628 :
629 : SAL_INFO("oox.shape", "dash dots: " << aLineDash.Dots << " dashes: " << aLineDash.Dashes
630 : << " dotlen: " << aLineDash.DotLen << " dashlen: " << aLineDash.DashLen << " distance: " << aLineDash.Distance);
631 : }
632 : /* fallthru intended */
633 : case drawing::LineStyle_SOLID:
634 : default:
635 681 : if ( GETA( LineColor ) )
636 : {
637 681 : nColor = mAny.get<sal_uInt32>() & 0xffffff;
638 681 : bColorSet = true;
639 : }
640 681 : break;
641 : }
642 :
643 : mpFS->startElementNS( XML_a, XML_ln,
644 : XML_cap, cap,
645 1868 : XML_w, nLineWidth > 1 && nStyleLineWidth != nLineWidth ?
646 2288 : I64S( oox::drawingml::convertHmmToEmu( nLineWidth ) ) :NULL,
647 3858 : FSEND );
648 :
649 1286 : if( bColorSet )
650 : {
651 681 : if( nColor != nOriginalColor )
652 : {
653 : // the user has set a different color for the line
654 331 : WriteSolidFill( nColor );
655 : }
656 350 : else if( !sColorFillScheme.isEmpty() )
657 : {
658 : // the line had a scheme color and the user didn't change it
659 36 : WriteSolidFill( sColorFillScheme, aTransformations );
660 : }
661 314 : else if( aStyleProperties.hasElements() )
662 : {
663 80 : if( nColor != nStyleColor )
664 : // the line style defines some color but it wasn't being used
665 11 : WriteSolidFill( nColor );
666 : // in case the shape used the style color and the user didn't change it,
667 : // we must not write a <a: solidFill> tag.
668 : }
669 : else
670 : {
671 234 : WriteSolidFill( nColor );
672 : }
673 : }
674 :
675 1286 : if( bDashSet && aStyleLineStyle != drawing::LineStyle_DASH )
676 : {
677 : // line style is a dash and it was not set by the shape style
678 :
679 19 : if (aLineDash.Dashes == 1 && aLineDash.DashLen == 564 && aLineDash.Distance == 423)
680 : {
681 : // That's exactly the predefined "dash" value.
682 : mpFS->singleElementNS(XML_a, XML_prstDash,
683 : XML_val, "dash",
684 2 : FSEND);
685 : }
686 : else
687 : {
688 17 : mpFS->startElementNS( XML_a, XML_custDash, FSEND );
689 :
690 : // Check that line-width is positive and distance between dashes\dots is positive
691 17 : if ( nLineWidth > 0 && aLineDash.Distance > 0 )
692 : {
693 : // Write 'dashes' first, and then 'dots'
694 : int i;
695 17 : if ( aLineDash.Dashes > 0 )
696 : {
697 32 : for( i = 0; i < aLineDash.Dashes; i ++ )
698 : {
699 : mpFS->singleElementNS( XML_a , XML_ds,
700 32 : XML_d , write1000thOfAPercent( aLineDash.DashLen > 0 ? aLineDash.DashLen / nLineWidth * 100 : 100 ),
701 32 : XML_sp, write1000thOfAPercent( aLineDash.Distance > 0 ? aLineDash.Distance / nLineWidth * 100 : 100 ),
702 64 : FSEND );
703 : }
704 : }
705 17 : if ( aLineDash.Dots > 0 )
706 : {
707 11 : for( i = 0; i < aLineDash.Dots; i ++ )
708 : {
709 : mpFS->singleElementNS( XML_a, XML_ds,
710 14 : XML_d , write1000thOfAPercent( aLineDash.DotLen > 0 ? aLineDash.DotLen / nLineWidth * 100 : 100 ),
711 14 : XML_sp, write1000thOfAPercent( aLineDash.Distance > 0 ? aLineDash.Distance / nLineWidth * 100 : 100 ),
712 28 : FSEND );
713 : }
714 : }
715 : }
716 :
717 : SAL_WARN_IF(nLineWidth <= 0,
718 : "oox", "while writing outline - custom dash - line width was < 0 : " << nLineWidth);
719 : SAL_WARN_IF(aLineDash.Dashes < 0,
720 : "oox", "while writing outline - custom dash - number of dashes was < 0 : " << aLineDash.Dashes);
721 : SAL_WARN_IF(aLineDash.Dashes > 0 && aLineDash.DashLen <= 0,
722 : "oox", "while writing outline - custom dash - dash length was < 0 : " << aLineDash.DashLen);
723 : SAL_WARN_IF(aLineDash.Dots < 0,
724 : "oox", "while writing outline - custom dash - number of dots was < 0 : " << aLineDash.Dots);
725 : SAL_WARN_IF(aLineDash.Dots > 0 && aLineDash.DotLen <= 0,
726 : "oox", "while writing outline - custom dash - dot length was < 0 : " << aLineDash.DotLen);
727 : SAL_WARN_IF(aLineDash.Distance <= 0,
728 : "oox", "while writing outline - custom dash - distance was < 0 : " << aLineDash.Distance);
729 :
730 17 : mpFS->endElementNS( XML_a, XML_custDash );
731 : }
732 : }
733 :
734 1286 : if( !bNoFill && nLineWidth > 1 && GETA( LineJoint ) )
735 : {
736 524 : LineJoint eLineJoint = mAny.get<LineJoint>();
737 :
738 524 : if( aStyleLineJoint == LineJoint_NONE || aStyleLineJoint != eLineJoint )
739 : {
740 : // style-defined line joint does not exist, or is different from the shape's joint
741 520 : switch( eLineJoint )
742 : {
743 : case LineJoint_NONE:
744 : case LineJoint_MIDDLE:
745 : case LineJoint_BEVEL:
746 1 : mpFS->singleElementNS( XML_a, XML_bevel, FSEND );
747 1 : break;
748 : default:
749 : case LineJoint_MITER:
750 41 : mpFS->singleElementNS( XML_a, XML_miter, FSEND );
751 41 : break;
752 : case LineJoint_ROUND:
753 478 : mpFS->singleElementNS( XML_a, XML_round, FSEND );
754 478 : break;
755 : }
756 : }
757 : }
758 :
759 1286 : if( !bNoFill )
760 : {
761 681 : WriteLineArrow( rXPropSet, true );
762 681 : WriteLineArrow( rXPropSet, false );
763 : }
764 : else
765 : {
766 605 : mpFS->singleElementNS( XML_a, XML_noFill, FSEND );
767 : }
768 :
769 2572 : mpFS->endElementNS( XML_a, XML_ln );
770 1286 : }
771 :
772 119 : OUString DrawingML::WriteImage( const OUString& rURL, bool bRelPathToMedia )
773 : {
774 119 : OString aURLBS(OUStringToOString(rURL, RTL_TEXTENCODING_UTF8));
775 :
776 119 : const char aURLBegin[] = "vnd.sun.star.GraphicObject:";
777 119 : sal_Int32 index = aURLBS.indexOf(aURLBegin);
778 :
779 119 : if ( index != -1 )
780 : {
781 : SAL_INFO("oox.shape", "begin: " << sizeof( aURLBegin ) << " " << USS( rURL ) + RTL_CONSTASCII_LENGTH( aURLBegin ));
782 117 : Graphic aGraphic = GraphicObject( aURLBS.copy(RTL_CONSTASCII_LENGTH(aURLBegin)) ).GetTransformedGraphic ();
783 :
784 117 : return WriteImage( aGraphic , bRelPathToMedia );
785 : }
786 : else
787 : {
788 : // add link to relations
789 : }
790 :
791 2 : return OUString();
792 : }
793 :
794 257 : const char* DrawingML::GetComponentDir()
795 : {
796 257 : switch ( meDocumentType )
797 : {
798 185 : case DOCUMENT_DOCX: return "word";
799 62 : case DOCUMENT_PPTX: return "ppt";
800 10 : case DOCUMENT_XLSX: return "xl";
801 : }
802 :
803 0 : return "unknown";
804 : }
805 :
806 257 : const char* DrawingML::GetRelationCompPrefix()
807 : {
808 257 : switch ( meDocumentType )
809 : {
810 185 : case DOCUMENT_DOCX: return "";
811 : case DOCUMENT_PPTX:
812 72 : case DOCUMENT_XLSX: return "../";
813 : }
814 :
815 0 : return "unknown";
816 : }
817 :
818 277 : OUString DrawingML::WriteImage( const Graphic& rGraphic , bool bRelPathToMedia )
819 : {
820 277 : GfxLink aLink = rGraphic.GetLink ();
821 554 : OUString sMediaType;
822 277 : const char* pExtension = "";
823 277 : OUString sRelId;
824 :
825 554 : SvMemoryStream aStream;
826 277 : const void* aData = aLink.GetData();
827 277 : sal_Size nDataSize = aLink.GetDataSize();
828 :
829 277 : switch ( aLink.GetType() )
830 : {
831 : case GFX_LINK_TYPE_NATIVE_GIF:
832 21 : sMediaType = "image/gif";
833 21 : pExtension = ".gif";
834 21 : break;
835 :
836 : // #i15508# added BMP type for better exports
837 : // export not yet active, so adding for reference (not checked)
838 : case GFX_LINK_TYPE_NATIVE_BMP:
839 0 : sMediaType = "image/bmp";
840 0 : pExtension = ".bmp";
841 0 : break;
842 :
843 : case GFX_LINK_TYPE_NATIVE_JPG:
844 49 : sMediaType = "image/jpeg";
845 49 : pExtension = ".jpeg";
846 49 : break;
847 : case GFX_LINK_TYPE_NATIVE_PNG:
848 76 : sMediaType = "image/png";
849 76 : pExtension = ".png";
850 76 : break;
851 : case GFX_LINK_TYPE_NATIVE_TIF:
852 1 : sMediaType = "image/tif";
853 1 : pExtension = ".tif";
854 1 : break;
855 : case GFX_LINK_TYPE_NATIVE_WMF:
856 30 : sMediaType = "image/x-wmf";
857 30 : pExtension = ".wmf";
858 30 : break;
859 : case GFX_LINK_TYPE_NATIVE_MET:
860 0 : sMediaType = "image/x-met";
861 0 : pExtension = ".met";
862 0 : break;
863 : case GFX_LINK_TYPE_NATIVE_PCT:
864 0 : sMediaType = "image/x-pict";
865 0 : pExtension = ".pct";
866 0 : break;
867 : case GFX_LINK_TYPE_NATIVE_MOV:
868 0 : sMediaType = "application/movie";
869 0 : pExtension = ".MOV";
870 0 : break;
871 : default:
872 : {
873 100 : GraphicType aType = rGraphic.GetType();
874 100 : if ( aType == GRAPHIC_BITMAP || aType == GRAPHIC_GDIMETAFILE)
875 : {
876 156 : if ( aType == GRAPHIC_BITMAP )
877 : {
878 59 : (void)GraphicConverter::Export( aStream, rGraphic, ConvertDataFormat::PNG );
879 59 : sMediaType = "image/png";
880 59 : pExtension = ".png";
881 : }
882 : else
883 : {
884 19 : (void)GraphicConverter::Export( aStream, rGraphic, ConvertDataFormat::EMF );
885 19 : sMediaType = "image/x-emf";
886 19 : pExtension = ".emf";
887 : }
888 : }
889 : else
890 : {
891 : OSL_TRACE( "unhandled graphic type" );
892 : /*Earlier, even in case of unhandled graphic types we were
893 : proceeding to write the image, which would eventually
894 : write an empty image with a zero size, and return a valid
895 : relationID, which is incorrect.
896 : */
897 22 : return sRelId;
898 : }
899 :
900 78 : aData = aStream.GetData();
901 78 : nDataSize = aStream.GetEndOfData();
902 78 : break;
903 : }
904 : }
905 :
906 : Reference< XOutputStream > xOutStream = mpFB->openFragmentStream( OUStringBuffer()
907 510 : .appendAscii( GetComponentDir() )
908 255 : .appendAscii( "/media/image" )
909 510 : .append( (sal_Int32) mnImageCounter )
910 255 : .appendAscii( pExtension )
911 : .makeStringAndClear(),
912 255 : sMediaType );
913 255 : xOutStream->writeBytes( Sequence< sal_Int8 >( static_cast<const sal_Int8*>(aData), nDataSize ) );
914 255 : xOutStream->closeOutput();
915 :
916 510 : OString sRelPathToMedia = "media/image";
917 255 : if ( bRelPathToMedia )
918 1 : sRelPathToMedia = "../" + sRelPathToMedia;
919 510 : sRelId = mpFB->addRelation( mpFS->getOutputStream(),
920 : "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",
921 : OUStringBuffer()
922 510 : .appendAscii( GetRelationCompPrefix() )
923 510 : .appendAscii( sRelPathToMedia.getStr() )
924 510 : .append( (sal_Int32) mnImageCounter ++ )
925 255 : .appendAscii( pExtension )
926 255 : .makeStringAndClear() );
927 :
928 787 : return sRelId;
929 : }
930 :
931 116 : OUString DrawingML::WriteBlip( Reference< XPropertySet > rXPropSet, const OUString& rURL, bool bRelPathToMedia, const Graphic *pGraphic )
932 : {
933 116 : OUString sRelId = pGraphic ? WriteImage( *pGraphic, bRelPathToMedia ) : WriteImage( rURL, bRelPathToMedia );
934 116 : sal_Int16 nBright = 0;
935 116 : sal_Int32 nContrast = 0;
936 :
937 116 : GET( nBright, AdjustLuminance );
938 116 : GET( nContrast, AdjustContrast );
939 :
940 : mpFS->startElementNS( XML_a, XML_blip,
941 : FSNS( XML_r, XML_embed), sRelId.toUtf8().getStr(),
942 116 : FSEND );
943 116 : if( nBright || nContrast )
944 : {
945 : mpFS->singleElementNS( XML_a, XML_lum,
946 0 : XML_bright, nBright ? I32S( nBright*1000 ) : NULL,
947 0 : XML_contrast, nContrast ? I32S( nContrast*1000 ) : NULL,
948 116 : FSEND );
949 : }
950 116 : WriteArtisticEffect( rXPropSet );
951 :
952 116 : mpFS->endElementNS( XML_a, XML_blip );
953 :
954 116 : return sRelId;
955 : }
956 :
957 6 : void DrawingML::WriteBlipMode( Reference< XPropertySet > rXPropSet, const OUString& rURL )
958 : {
959 6 : BitmapMode eBitmapMode( BitmapMode_NO_REPEAT );
960 6 : if (GetProperty( rXPropSet, "FillBitmapMode" ) )
961 6 : mAny >>= eBitmapMode;
962 :
963 : SAL_INFO("oox.shape", "fill bitmap mode: " << int(eBitmapMode));
964 :
965 6 : switch (eBitmapMode)
966 : {
967 : case BitmapMode_REPEAT:
968 2 : mpFS->singleElementNS( XML_a, XML_tile, FSEND );
969 2 : break;
970 : case BitmapMode_STRETCH:
971 4 : WriteStretch( rXPropSet, rURL );
972 4 : break;
973 : default:
974 0 : break;
975 : }
976 6 : }
977 :
978 104 : void DrawingML::WriteBlipOrNormalFill( Reference< XPropertySet > xPropSet, const OUString& rURLPropName )
979 : {
980 : // check for blip and otherwise fall back to normal fill
981 : // we always store normal fill properties but OOXML
982 : // uses a choice between our fill props and BlipFill
983 104 : if (GetProperty ( xPropSet, rURLPropName ))
984 0 : WriteBlipFill( xPropSet, rURLPropName );
985 : else
986 104 : WriteFill(xPropSet);
987 104 : }
988 :
989 959 : void DrawingML::WriteBlipFill( Reference< XPropertySet > rXPropSet, const OUString& sURLPropName )
990 : {
991 959 : WriteBlipFill( rXPropSet, sURLPropName, XML_a );
992 959 : }
993 :
994 959 : void DrawingML::WriteBlipFill( Reference< XPropertySet > rXPropSet, const OUString& sURLPropName, sal_Int32 nXmlNamespace )
995 : {
996 959 : if ( GetProperty( rXPropSet, sURLPropName ) )
997 : {
998 5 : OUString aURL;
999 5 : mAny >>= aURL;
1000 5 : bool bWriteMode = false;
1001 5 : if( sURLPropName == "FillBitmapURL" || sURLPropName == "BackGraphicURL")
1002 5 : bWriteMode = true;
1003 5 : WriteBlipFill( rXPropSet, aURL, nXmlNamespace, bWriteMode );
1004 : }
1005 959 : }
1006 :
1007 6 : void DrawingML::WriteBlipFill( Reference< XPropertySet > rXPropSet, const OUString& sBitmapURL, sal_Int32 nXmlNamespace, bool bWriteMode, bool bRelPathToMedia )
1008 : {
1009 6 : if ( !sBitmapURL.isEmpty() )
1010 : {
1011 : SAL_INFO("oox.shape", "URL: " << sBitmapURL);
1012 :
1013 6 : mpFS->startElementNS( nXmlNamespace , XML_blipFill, FSEND );
1014 :
1015 6 : WriteBlip( rXPropSet, sBitmapURL, bRelPathToMedia );
1016 :
1017 6 : if( bWriteMode )
1018 : {
1019 6 : WriteBlipMode( rXPropSet, sBitmapURL );
1020 : }
1021 0 : else if( GetProperty( rXPropSet, "FillBitmapStretch" ) )
1022 : {
1023 0 : bool bStretch = false;
1024 0 : mAny >>= bStretch;
1025 :
1026 0 : if( bStretch )
1027 0 : WriteStretch( rXPropSet, sBitmapURL );
1028 : }
1029 6 : mpFS->endElementNS( nXmlNamespace, XML_blipFill );
1030 : }
1031 6 : }
1032 :
1033 14 : void DrawingML::WritePattFill( Reference< XPropertySet > rXPropSet )
1034 : {
1035 14 : if ( GetProperty( rXPropSet, "FillHatch" ) )
1036 : {
1037 14 : drawing::Hatch aHatch;
1038 14 : mAny >>= aHatch;
1039 :
1040 14 : mpFS->startElementNS( XML_a , XML_pattFill, XML_prst, GetHatchPattern(aHatch), FSEND );
1041 :
1042 14 : mpFS->startElementNS( XML_a , XML_fgClr, FSEND );
1043 14 : WriteColor(aHatch.Color);
1044 14 : mpFS->endElementNS( XML_a , XML_fgClr );
1045 :
1046 : // In Writer hatching has no background so use white as a default value.
1047 14 : mpFS->startElementNS( XML_a , XML_bgClr, FSEND );
1048 14 : WriteColor(COL_WHITE);
1049 14 : mpFS->endElementNS( XML_a , XML_bgClr );
1050 :
1051 14 : mpFS->endElementNS( XML_a , XML_pattFill );
1052 : }
1053 14 : }
1054 :
1055 110 : void DrawingML::WriteSrcRect( Reference< XPropertySet > rXPropSet, const OUString& rURL )
1056 : {
1057 110 : GraphicObject aGraphicObject = GraphicObject::CreateGraphicObjectFromURL(rURL);
1058 110 : Size aOriginalSize = aGraphicObject.GetPrefSize();
1059 110 : const MapMode& rMapMode = aGraphicObject.GetPrefMapMode();
1060 :
1061 : // GraphicCrop is in mm100, so in case the original size is in pixels, convert it over.
1062 110 : if (rMapMode.GetMapUnit() == MAP_PIXEL)
1063 75 : aOriginalSize = Application::GetDefaultDevice()->PixelToLogic(aOriginalSize, MapMode(MAP_100TH_MM));
1064 :
1065 110 : if ( GetProperty( rXPropSet, "GraphicCrop" ) )
1066 : {
1067 110 : ::com::sun::star::text::GraphicCrop aGraphicCropStruct;
1068 110 : mAny >>= aGraphicCropStruct;
1069 :
1070 110 : if ( (0 != aGraphicCropStruct.Left) || (0 != aGraphicCropStruct.Top) || (0 != aGraphicCropStruct.Right) || (0 != aGraphicCropStruct.Bottom) )
1071 : {
1072 : mpFS->singleElementNS( XML_a, XML_srcRect,
1073 1 : XML_l, I32S(rtl::math::round(static_cast<double>(aGraphicCropStruct.Left) * 100000 / aOriginalSize.Width())),
1074 1 : XML_t, I32S(rtl::math::round(static_cast<double>(aGraphicCropStruct.Top) * 100000 / aOriginalSize.Height())),
1075 1 : XML_r, I32S(rtl::math::round(static_cast<double>(aGraphicCropStruct.Right) * 100000 / aOriginalSize.Width())),
1076 1 : XML_b, I32S(rtl::math::round(static_cast<double>(aGraphicCropStruct.Bottom) * 100000 / aOriginalSize.Height())),
1077 4 : FSEND );
1078 : }
1079 110 : }
1080 110 : }
1081 :
1082 4 : void DrawingML::WriteStretch( ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > rXPropSet, const OUString& rURL )
1083 : {
1084 4 : mpFS->startElementNS( XML_a, XML_stretch, FSEND );
1085 :
1086 4 : bool bCrop = false;
1087 4 : if ( GetProperty( rXPropSet, "GraphicCrop" ) )
1088 : {
1089 3 : ::com::sun::star::text::GraphicCrop aGraphicCropStruct;
1090 3 : mAny >>= aGraphicCropStruct;
1091 :
1092 3 : if ( (0 != aGraphicCropStruct.Left) || (0 != aGraphicCropStruct.Top) || (0 != aGraphicCropStruct.Right) || (0 != aGraphicCropStruct.Bottom) )
1093 : {
1094 1 : Size aOriginalSize( GraphicObject::CreateGraphicObjectFromURL( rURL ).GetPrefSize() );
1095 : mpFS->singleElementNS( XML_a, XML_fillRect,
1096 2 : XML_l, I32S(((aGraphicCropStruct.Left) * 100000)/aOriginalSize.Width()),
1097 2 : XML_t, I32S(((aGraphicCropStruct.Top) * 100000)/aOriginalSize.Height()),
1098 2 : XML_r, I32S(((aGraphicCropStruct.Right) * 100000)/aOriginalSize.Width()),
1099 2 : XML_b, I32S(((aGraphicCropStruct.Bottom) * 100000)/aOriginalSize.Height()),
1100 8 : FSEND );
1101 1 : bCrop = true;
1102 : }
1103 : }
1104 :
1105 4 : if( !bCrop )
1106 : {
1107 3 : mpFS->singleElementNS( XML_a, XML_fillRect, FSEND );
1108 : }
1109 :
1110 4 : mpFS->endElementNS( XML_a, XML_stretch );
1111 4 : }
1112 :
1113 1759 : void DrawingML::WriteTransformation( const Rectangle& rRect,
1114 : sal_Int32 nXmlNamespace, bool bFlipH, bool bFlipV, sal_Int32 nRotation )
1115 : {
1116 : mpFS->startElementNS( nXmlNamespace, XML_xfrm,
1117 : XML_flipH, bFlipH ? "1" : NULL,
1118 : XML_flipV, bFlipV ? "1" : NULL,
1119 3560 : XML_rot, (nRotation % 21600000) ? I32S( nRotation ) : NULL,
1120 3518 : FSEND );
1121 :
1122 1759 : sal_Int32 nLeft = rRect.Left();
1123 1759 : sal_Int32 nTop = rRect.Top();
1124 1759 : if (GetDocumentType() == DOCUMENT_DOCX && !m_xParent.is())
1125 : {
1126 336 : nLeft = 0;
1127 336 : nTop = 0;
1128 : }
1129 :
1130 1759 : mpFS->singleElementNS( XML_a, XML_off, XML_x, IS( oox::drawingml::convertHmmToEmu( nLeft ) ), XML_y, IS( oox::drawingml::convertHmmToEmu( nTop ) ), FSEND );
1131 1759 : mpFS->singleElementNS( XML_a, XML_ext, XML_cx, IS( oox::drawingml::convertHmmToEmu( rRect.GetWidth() ) ), XML_cy, IS( oox::drawingml::convertHmmToEmu( rRect.GetHeight() ) ), FSEND );
1132 :
1133 1759 : mpFS->endElementNS( nXmlNamespace, XML_xfrm );
1134 1759 : }
1135 :
1136 1715 : void DrawingML::WriteShapeTransformation( Reference< XShape > rXShape, sal_Int32 nXmlNamespace, bool bFlipH, bool bFlipV, bool bSuppressRotation )
1137 : {
1138 : SAL_INFO("oox.shape", "write shape transformation");
1139 :
1140 1715 : sal_Int32 nRotation=0;
1141 1715 : awt::Point aPos = rXShape->getPosition();
1142 1715 : awt::Size aSize = rXShape->getSize();
1143 :
1144 1715 : if (m_xParent.is())
1145 : {
1146 277 : awt::Point aParentPos = m_xParent->getPosition();
1147 277 : aPos.X -= aParentPos.X;
1148 277 : aPos.Y -= aParentPos.Y;
1149 : }
1150 :
1151 1715 : if ( aSize.Width < 0 )
1152 26 : aSize.Width = 1000;
1153 1715 : if ( aSize.Height < 0 )
1154 11 : aSize.Height = 1000;
1155 1715 : if (!bSuppressRotation)
1156 : {
1157 1699 : SdrObject* pShape = GetSdrObjectFromXShape( rXShape );
1158 1699 : nRotation = pShape ? pShape->GetRotateAngle() : 0;
1159 1699 : if (nRotation != 0 && nRotation != 18000)
1160 : {
1161 15 : int faccos=bFlipV ? -1 : 1;
1162 15 : int facsin=bFlipH ? -1 : 1;
1163 15 : aPos.X-=(1-faccos*cos(nRotation*F_PI18000))*aSize.Width/2-facsin*sin(nRotation*F_PI18000)*aSize.Height/2;
1164 15 : aPos.Y-=(1-faccos*cos(nRotation*F_PI18000))*aSize.Height/2+facsin*sin(nRotation*F_PI18000)*aSize.Width/2;
1165 : }
1166 :
1167 : // The RotateAngle property's value is independent from any flipping, and that's exactly what we need here.
1168 1699 : uno::Reference<beans::XPropertySet> xPropertySet(rXShape, uno::UNO_QUERY);
1169 3398 : uno::Reference<beans::XPropertySetInfo> xPropertySetInfo = xPropertySet->getPropertySetInfo();
1170 1699 : if (xPropertySetInfo->hasPropertyByName("RotateAngle"))
1171 3394 : xPropertySet->getPropertyValue("RotateAngle") >>= nRotation;
1172 : }
1173 1715 : WriteTransformation( Rectangle( Point( aPos.X, aPos.Y ), Size( aSize.Width, aSize.Height ) ), nXmlNamespace, bFlipH, bFlipV, OOX_DRAWINGML_EXPORT_ROTATE_CLOCKWISIFY(nRotation) );
1174 1715 : }
1175 :
1176 447 : void DrawingML::WriteRunProperties( Reference< XPropertySet > rRun, bool bIsField, sal_Int32 nElement /*= XML_rPr*/ )
1177 : {
1178 447 : Reference< XPropertySet > rXPropSet( rRun, UNO_QUERY );
1179 894 : Reference< XPropertyState > rXPropState( rRun, UNO_QUERY );
1180 894 : OUString usLanguage;
1181 : PropertyState eState;
1182 447 : SvtScriptType nScriptType = SvtLanguageOptions::GetScriptTypeOfLanguage( Application::GetSettings().GetLanguageTag().getLanguageType() );
1183 447 : bool bComplex = ( nScriptType == SvtScriptType::COMPLEX );
1184 447 : const char* bold = NULL;
1185 447 : const char* italic = NULL;
1186 447 : const char* underline = NULL;
1187 447 : const char* strikeout = NULL;
1188 447 : const char* cap = NULL;
1189 447 : sal_Int32 nSize = 1800;
1190 447 : sal_Int32 nCharEscapement = 0;
1191 447 : sal_Int32 nCharKerning = 0;
1192 :
1193 447 : if( GETA( CharHeight ) )
1194 447 : nSize = (sal_Int32) (100*(*static_cast<float const *>(mAny.getValue())));
1195 :
1196 447 : if( GETA( CharKerning ) )
1197 447 : nCharKerning = (sal_Int32)(*static_cast<short const *>(mAny.getValue()));
1198 : /** While setting values in propertymap,
1199 : * CharKerning converted using GetTextSpacingPoint
1200 : * i.e set @ http://opengrok.libreoffice.org/xref/core/oox/source/drawingml/textcharacterproperties.cxx#129
1201 : * therefore to get original value CharKerning need to be convert.
1202 : * http://opengrok.libreoffice.org/xref/core/oox/source/drawingml/drawingmltypes.cxx#95
1203 : **/
1204 447 : nCharKerning = ((nCharKerning * 720)-360) / 254;
1205 :
1206 447 : if ( ( bComplex && GETA( CharWeightComplex ) ) || GETA( CharWeight ) )
1207 : {
1208 447 : if ( *static_cast<float const *>(mAny.getValue()) >= awt::FontWeight::SEMIBOLD )
1209 78 : bold = "1";
1210 : }
1211 :
1212 447 : if ( ( bComplex && GETA( CharPostureComplex ) ) || GETA( CharPosture ) )
1213 447 : switch ( *static_cast<awt::FontSlant const *>(mAny.getValue()) )
1214 : {
1215 : case awt::FontSlant_OBLIQUE :
1216 : case awt::FontSlant_ITALIC :
1217 10 : italic = "1";
1218 10 : break;
1219 : default:
1220 437 : break;
1221 : }
1222 :
1223 447 : if ( GETAD( CharUnderline ) )
1224 : {
1225 122 : switch ( *static_cast<sal_Int16 const *>(mAny.getValue()) )
1226 : {
1227 : case awt::FontUnderline::SINGLE :
1228 2 : underline = "sng";
1229 2 : break;
1230 : case awt::FontUnderline::DOUBLE :
1231 1 : underline = "dbl";
1232 1 : break;
1233 : case awt::FontUnderline::DOTTED :
1234 0 : underline = "dotted";
1235 0 : break;
1236 : case awt::FontUnderline::DASH :
1237 0 : underline = "dash";
1238 0 : break;
1239 : case awt::FontUnderline::LONGDASH :
1240 0 : underline = "dashLong";
1241 0 : break;
1242 : case awt::FontUnderline::DASHDOT :
1243 0 : underline = "dotDash";
1244 0 : break;
1245 : case awt::FontUnderline::DASHDOTDOT :
1246 0 : underline = "dotDotDash";
1247 0 : break;
1248 : case awt::FontUnderline::WAVE :
1249 0 : underline = "wavy";
1250 0 : break;
1251 : case awt::FontUnderline::DOUBLEWAVE :
1252 0 : underline = "wavyDbl";
1253 0 : break;
1254 : case awt::FontUnderline::BOLD :
1255 0 : underline = "heavy";
1256 0 : break;
1257 : case awt::FontUnderline::BOLDDOTTED :
1258 0 : underline = "dottedHeavy";
1259 0 : break;
1260 : case awt::FontUnderline::BOLDDASH :
1261 0 : underline = "dashHeavy";
1262 0 : break;
1263 : case awt::FontUnderline::BOLDLONGDASH :
1264 0 : underline = "dashLongHeavy";
1265 0 : break;
1266 : case awt::FontUnderline::BOLDDASHDOT :
1267 0 : underline = "dotDashHeavy";
1268 0 : break;
1269 : case awt::FontUnderline::BOLDDASHDOTDOT :
1270 0 : underline = "dotDotDashHeavy";
1271 0 : break;
1272 : case awt::FontUnderline::BOLDWAVE :
1273 0 : underline = "wavyHeavy";
1274 0 : break;
1275 : }
1276 : }
1277 :
1278 447 : if ( GETAD( CharStrikeout ) )
1279 : {
1280 122 : switch ( *static_cast<sal_Int16 const *>(mAny.getValue()) )
1281 : {
1282 : case awt::FontStrikeout::NONE :
1283 121 : strikeout = "noStrike";
1284 121 : break;
1285 : case awt::FontStrikeout::SINGLE :
1286 : // LibO supports further values of character
1287 : // strikeout, OOXML standard (20.1.10.78,
1288 : // ST_TextStrikeType) however specifies only
1289 : // 3 - single, double and none. Approximate
1290 : // the remaining ones by single strike (better
1291 : // some strike than none at all).
1292 : // TODO: figure out how to do this better
1293 : case awt::FontStrikeout::BOLD :
1294 : case awt::FontStrikeout::SLASH :
1295 : case awt::FontStrikeout::X :
1296 1 : strikeout = "sngStrike";
1297 1 : break;
1298 : case awt::FontStrikeout::DOUBLE :
1299 0 : strikeout = "dblStrike";
1300 0 : break;
1301 : }
1302 : }
1303 :
1304 447 : if( GETA( CharLocale ) )
1305 : {
1306 447 : com::sun::star::lang::Locale aLocale;
1307 447 : mAny >>= aLocale;
1308 894 : LanguageTag aLanguageTag( aLocale);
1309 447 : if (!aLanguageTag.isSystemLocale())
1310 700 : usLanguage = aLanguageTag.getBcp47();
1311 : }
1312 :
1313 447 : if( GETAD( CharEscapement ) )
1314 303 : mAny >>= nCharEscapement;
1315 :
1316 447 : if( nCharEscapement && GETAD( CharEscapementHeight ) )
1317 : {
1318 1 : sal_uInt32 nCharEscapementHeight = 0;
1319 1 : mAny >>= nCharEscapementHeight;
1320 1 : nSize = (nSize * nCharEscapementHeight) / 100;
1321 : // MSO uses default ~58% size
1322 1 : nSize = (nSize / 0.58);
1323 : }
1324 :
1325 447 : if( GETA( CharCaseMap ) )
1326 : {
1327 253 : switch ( *static_cast<sal_Int16 const *>(mAny.getValue()) )
1328 : {
1329 : case CaseMap::UPPERCASE :
1330 0 : cap = "all";
1331 0 : break;
1332 : case CaseMap::SMALLCAPS :
1333 0 : cap = "small";
1334 0 : break;
1335 : }
1336 : }
1337 :
1338 : mpFS->startElementNS( XML_a, nElement,
1339 : XML_b, bold,
1340 : XML_i, italic,
1341 1147 : XML_lang, usLanguage.isEmpty() ? NULL : USS( usLanguage ),
1342 : XML_sz, IS( nSize ),
1343 : // For Condensed character spacing spc value is negative.
1344 894 : XML_spc, nCharKerning ? IS(nCharKerning) : NULL,
1345 : XML_strike, strikeout,
1346 : XML_u, underline,
1347 896 : XML_baseline, nCharEscapement == 0 ? NULL : IS( nCharEscapement*1000 ),
1348 : XML_cap, cap,
1349 2488 : FSEND );
1350 :
1351 : // mso doesn't like text color to be placed after typeface
1352 447 : if( GETAD( CharColor ) )
1353 : {
1354 305 : sal_uInt32 color = *static_cast<sal_uInt32 const *>(mAny.getValue());
1355 : SAL_INFO("oox.shape", "run color: " << color << " auto: " << COL_AUTO);
1356 :
1357 305 : if( color == COL_AUTO ) // nCharColor depends to the background color
1358 : {
1359 0 : bool bIsDark = false;
1360 0 : GET( bIsDark, IsBackgroundDark );
1361 0 : color = bIsDark ? 0xffffff : 0x000000;
1362 : }
1363 305 : color &= 0xffffff;
1364 :
1365 : // TODO: special handle embossed/engraved
1366 :
1367 305 : WriteSolidFill( color );
1368 : }
1369 :
1370 447 : if( GETAD( CharUnderlineColor ) )
1371 : {
1372 122 : sal_uInt32 color = *static_cast<sal_uInt32 const *>(mAny.getValue());
1373 :
1374 122 : mpFS->startElementNS( XML_a, XML_uFill,FSEND);
1375 122 : WriteSolidFill( color );
1376 122 : mpFS->endElementNS( XML_a, XML_uFill );
1377 : }
1378 :
1379 447 : if( GETA( CharFontName ) )
1380 : {
1381 447 : const char* pitch = NULL;
1382 447 : const char* charset = NULL;
1383 447 : OUString usTypeface;
1384 :
1385 447 : mAny >>= usTypeface;
1386 894 : OUString aSubstName( GetSubsFontName( usTypeface, SubsFontFlags::ONLYONE | SubsFontFlags::MS ) );
1387 :
1388 : mpFS->singleElementNS( XML_a, XML_latin,
1389 447 : XML_typeface, USS(aSubstName.getLength() ? aSubstName : usTypeface),
1390 : XML_pitchFamily, pitch,
1391 : XML_charset, charset,
1392 894 : FSEND );
1393 : }
1394 :
1395 447 : if( ( bComplex && GETAD( CharFontNameComplex ) ) || ( !bComplex && GETAD( CharFontNameAsian ) ) )
1396 : {
1397 30 : const char* pitch = NULL;
1398 30 : const char* charset = NULL;
1399 30 : OUString usTypeface;
1400 :
1401 30 : mAny >>= usTypeface;
1402 60 : OUString aSubstName( GetSubsFontName( usTypeface, SubsFontFlags::ONLYONE | SubsFontFlags::MS ) );
1403 :
1404 : mpFS->singleElementNS( XML_a, bComplex ? XML_cs : XML_ea,
1405 30 : XML_typeface, USS(aSubstName.getLength() ? aSubstName : usTypeface),
1406 : XML_pitchFamily, pitch,
1407 : XML_charset, charset,
1408 60 : FSEND );
1409 : }
1410 :
1411 447 : if( bIsField )
1412 : {
1413 55 : Reference< XTextField > rXTextField;
1414 55 : GET( rXTextField, TextField );
1415 55 : if( rXTextField.is() )
1416 55 : rRun.set( rXTextField, UNO_QUERY );
1417 : }
1418 :
1419 : // field properties starts here
1420 447 : if( GETA( URL ) )
1421 : {
1422 0 : OUString sURL;
1423 :
1424 0 : mAny >>= sURL;
1425 0 : if( !sURL.isEmpty() ) {
1426 : OUString sRelId = mpFB->addRelation( mpFS->getOutputStream(),
1427 : "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink",
1428 0 : sURL, true );
1429 :
1430 : mpFS->singleElementNS( XML_a, XML_hlinkClick,
1431 : FSNS( XML_r,XML_id ), USS( sRelId ),
1432 0 : FSEND );
1433 0 : }
1434 : }
1435 :
1436 894 : mpFS->endElementNS( XML_a, nElement );
1437 447 : }
1438 :
1439 253 : const char* DrawingML::GetFieldType( ::com::sun::star::uno::Reference< ::com::sun::star::text::XTextRange > rRun, bool& bIsField )
1440 : {
1441 253 : const char* sType = NULL;
1442 253 : Reference< XPropertySet > rXPropSet( rRun, UNO_QUERY );
1443 506 : OUString aFieldType;
1444 :
1445 253 : if( GETA( TextPortionType ) )
1446 : {
1447 253 : aFieldType = OUString( *static_cast<OUString const *>(mAny.getValue()) );
1448 : SAL_INFO("oox.shape", "field type: " << aFieldType);
1449 : }
1450 :
1451 253 : if( aFieldType == "TextField" )
1452 : {
1453 55 : Reference< XTextField > rXTextField;
1454 55 : GET( rXTextField, TextField );
1455 55 : if( rXTextField.is() )
1456 : {
1457 55 : bIsField = true;
1458 55 : rXPropSet.set( rXTextField, UNO_QUERY );
1459 55 : if( rXPropSet.is() )
1460 : {
1461 55 : OUString aFieldKind( rXTextField->getPresentation( true ) );
1462 : SAL_INFO("oox.shape", "field kind: " << aFieldKind);
1463 55 : if( aFieldKind == "Page" )
1464 : {
1465 22 : return "slidenum";
1466 33 : }
1467 : // else if( aFieldKind == "URL" ) {
1468 : // do not return here
1469 : // and make URL field text run with hyperlink property later
1470 : // }
1471 : }
1472 33 : }
1473 : }
1474 :
1475 484 : return sType;
1476 : }
1477 :
1478 22 : void DrawingML::GetUUID( OStringBuffer& rBuffer )
1479 : {
1480 22 : Sequence< sal_uInt8 > aSeq( 16 );
1481 : static const char cDigits[17] = "0123456789ABCDEF";
1482 22 : rtl_createUuid( aSeq.getArray(), 0, true );
1483 : int i;
1484 :
1485 22 : rBuffer.append( '{' );
1486 110 : for( i = 0; i < 4; i++ )
1487 : {
1488 88 : rBuffer.append( cDigits[ aSeq[i] >> 4 ] );
1489 88 : rBuffer.append( cDigits[ aSeq[i] & 0xf ] );
1490 : }
1491 22 : rBuffer.append( '-' );
1492 66 : for( ; i < 6; i++ )
1493 : {
1494 44 : rBuffer.append( cDigits[ aSeq[i] >> 4 ] );
1495 44 : rBuffer.append( cDigits[ aSeq[i] & 0xf ] );
1496 : }
1497 22 : rBuffer.append( '-' );
1498 66 : for( ; i < 8; i++ )
1499 : {
1500 44 : rBuffer.append( cDigits[ aSeq[i] >> 4 ] );
1501 44 : rBuffer.append( cDigits[ aSeq[i] & 0xf ] );
1502 : }
1503 22 : rBuffer.append( '-' );
1504 66 : for( ; i < 10; i++ )
1505 : {
1506 44 : rBuffer.append( cDigits[ aSeq[i] >> 4 ] );
1507 44 : rBuffer.append( cDigits[ aSeq[i] & 0xf ] );
1508 : }
1509 22 : rBuffer.append( '-' );
1510 154 : for( ; i < 16; i++ )
1511 : {
1512 132 : rBuffer.append( cDigits[ aSeq[i] >> 4 ] );
1513 132 : rBuffer.append( cDigits[ aSeq[i] & 0xf ] );
1514 : }
1515 22 : rBuffer.append( '}' );
1516 22 : }
1517 :
1518 1111 : void DrawingML::WriteRun( Reference< XTextRange > rRun )
1519 : {
1520 1111 : Reference< XPropertySet > rXPropSet( rRun, UNO_QUERY );
1521 1111 : sal_Int16 nLevel = -1;
1522 1111 : GET( nLevel, NumberingLevel );
1523 :
1524 : const char* sFieldType;
1525 1111 : bool bIsField = false;
1526 1364 : OUString sText = rRun->getString();
1527 :
1528 : //if there is no text following the bullet, add a space after the bullet
1529 1111 : if (nLevel !=-1 && sText.isEmpty() )
1530 1 : sText=" ";
1531 :
1532 1111 : if( sText.isEmpty())
1533 : {
1534 858 : Reference< XPropertySet > xPropSet( rRun, UNO_QUERY );
1535 :
1536 : try
1537 : {
1538 1716 : if( !xPropSet.is() || !( xPropSet->getPropertyValue( "PlaceholderText" ) >>= sText ) )
1539 0 : return;
1540 0 : if( sText.isEmpty() )
1541 0 : return;
1542 : }
1543 1716 : catch (const Exception &)
1544 : {
1545 858 : return;
1546 0 : }
1547 : }
1548 :
1549 253 : sFieldType = GetFieldType( rRun, bIsField );
1550 253 : if( ( sFieldType != NULL ) )
1551 : {
1552 22 : OStringBuffer sUUID(39);
1553 :
1554 22 : GetUUID( sUUID );
1555 : mpFS->startElementNS( XML_a, XML_fld,
1556 : XML_id, sUUID.getStr(),
1557 : XML_type, sFieldType,
1558 22 : FSEND );
1559 : }
1560 : else
1561 : {
1562 231 : mpFS->startElementNS( XML_a, XML_r, FSEND );
1563 : }
1564 :
1565 506 : Reference< XPropertySet > xPropSet( rRun, uno::UNO_QUERY );
1566 253 : WriteRunProperties( xPropSet, bIsField );
1567 :
1568 253 : mpFS->startElementNS( XML_a, XML_t, FSEND );
1569 253 : mpFS->writeEscaped( sText );
1570 253 : mpFS->endElementNS( XML_a, XML_t );
1571 :
1572 253 : if( sFieldType )
1573 22 : mpFS->endElementNS( XML_a, XML_fld );
1574 : else
1575 484 : mpFS->endElementNS( XML_a, XML_r );
1576 : }
1577 :
1578 120 : OUString GetAutoNumType(sal_Int16 nNumberingType, bool bSDot, bool bPBehind, bool bPBoth)
1579 : {
1580 120 : OUString sPrefixSuffix;
1581 :
1582 120 : if (bPBoth)
1583 0 : sPrefixSuffix = "ParenBoth";
1584 120 : else if (bPBehind)
1585 2 : sPrefixSuffix = "ParenR";
1586 118 : else if (bSDot)
1587 8 : sPrefixSuffix = "Period";
1588 :
1589 120 : switch( (SvxExtNumType)nNumberingType )
1590 : {
1591 : case SVX_NUM_CHARS_UPPER_LETTER_N :
1592 : case SVX_NUM_CHARS_UPPER_LETTER :
1593 2 : return "alphaUc" + sPrefixSuffix;
1594 :
1595 : case SVX_NUM_CHARS_LOWER_LETTER_N :
1596 : case SVX_NUM_CHARS_LOWER_LETTER :
1597 2 : return "alphaLc" + sPrefixSuffix;
1598 :
1599 : case SVX_NUM_ROMAN_UPPER :
1600 2 : return "romanUc" + sPrefixSuffix;
1601 :
1602 : case SVX_NUM_ROMAN_LOWER :
1603 2 : return "romanLc" + sPrefixSuffix;
1604 :
1605 : case SVX_NUM_ARABIC :
1606 : {
1607 2 : if (sPrefixSuffix.isEmpty())
1608 0 : return OUString("arabicPlain");
1609 : else
1610 2 : return "arabic" + sPrefixSuffix;
1611 : }
1612 : default:
1613 110 : break;
1614 : }
1615 :
1616 110 : return OUString();
1617 : }
1618 :
1619 400 : void DrawingML::WriteParagraphNumbering( Reference< XPropertySet > rXPropSet, sal_Int16 nLevel )
1620 : {
1621 400 : if( nLevel < 0 || !GETA( NumberingRules ) )
1622 545 : return;
1623 :
1624 132 : Reference< XIndexAccess > rXIndexAccess;
1625 :
1626 132 : if (!(mAny >>= rXIndexAccess) || nLevel >= rXIndexAccess->getCount())
1627 0 : return;
1628 :
1629 : SAL_INFO("oox.shape", "numbering rules");
1630 :
1631 255 : Sequence<PropertyValue> aPropertySequence;
1632 132 : rXIndexAccess->getByIndex(nLevel) >>= aPropertySequence;
1633 :
1634 132 : if (!aPropertySequence.hasElements())
1635 0 : return;
1636 :
1637 132 : sal_Int32 nPropertyCount = aPropertySequence.getLength();
1638 :
1639 132 : const PropertyValue* pPropValue = aPropertySequence.getArray();
1640 :
1641 132 : sal_Int16 nNumberingType = SVX_NUM_NUMBER_NONE;
1642 132 : bool bSDot = false;
1643 132 : bool bPBehind = false;
1644 132 : bool bPBoth = false;
1645 132 : sal_Unicode aBulletChar = 0x2022; // a bullet
1646 255 : awt::FontDescriptor aFontDesc;
1647 132 : bool bHasFontDesc = false;
1648 255 : OUString aGraphicURL;
1649 132 : sal_Int16 nBulletRelSize = 0;
1650 132 : sal_Int16 nStartWith = 1;
1651 132 : sal_Int32 nBulletColor = 0;
1652 :
1653 1829 : for ( sal_Int32 i = 0; i < nPropertyCount; i++ )
1654 : {
1655 1697 : const void* pValue = pPropValue[ i ].Value.getValue();
1656 1697 : if ( pValue )
1657 : {
1658 1697 : OUString aPropName( pPropValue[ i ].Name );
1659 : SAL_INFO("oox.shape", "pro name: " << aPropName);
1660 1697 : if ( aPropName == "NumberingType" )
1661 : {
1662 132 : nNumberingType = *( static_cast<sal_Int16 const *>(pValue) );
1663 : }
1664 1565 : else if ( aPropName == "Prefix" )
1665 : {
1666 132 : if( *static_cast<OUString const *>(pValue) == ")")
1667 0 : bPBoth = true;
1668 : }
1669 1433 : else if ( aPropName == "Suffix" )
1670 : {
1671 132 : if( *static_cast<OUString const *>(pValue) == ".")
1672 8 : bSDot = true;
1673 124 : else if( *static_cast<OUString const *>(pValue) == ")")
1674 2 : bPBehind = true;
1675 : }
1676 1301 : else if(aPropName == "BulletColor")
1677 : {
1678 132 : nBulletColor = *static_cast<sal_Int32 const *>(pValue);
1679 : }
1680 1169 : else if ( aPropName == "BulletChar" )
1681 : {
1682 110 : aBulletChar = OUString ( *( static_cast<OUString const *>(pValue) ) )[ 0 ];
1683 : }
1684 1059 : else if ( aPropName == "BulletFont" )
1685 : {
1686 132 : aFontDesc = *static_cast<awt::FontDescriptor const *>(pValue);
1687 132 : bHasFontDesc = true;
1688 :
1689 : // Our numbullet dialog has set the wrong textencoding for our "StarSymbol" font,
1690 : // instead of a Unicode encoding the encoding RTL_TEXTENCODING_SYMBOL was used.
1691 : // Because there might exist a lot of damaged documemts I added this two lines
1692 : // which fixes the bullet problem for the export.
1693 132 : if ( aFontDesc.Name.equalsIgnoreAsciiCase("StarSymbol") )
1694 98 : aFontDesc.CharSet = RTL_TEXTENCODING_MS_1252;
1695 :
1696 : }
1697 927 : else if ( aPropName == "BulletRelSize" )
1698 : {
1699 132 : nBulletRelSize = *static_cast<sal_Int16 const *>(pValue);
1700 : }
1701 795 : else if ( aPropName == "StartWith" )
1702 : {
1703 132 : nStartWith = *static_cast<sal_Int16 const *>(pValue);
1704 : }
1705 663 : else if ( aPropName == "GraphicURL" )
1706 : {
1707 3 : aGraphicURL = *static_cast<OUString const *>(pValue);
1708 : SAL_INFO("oox.shape", "graphic url: " << aGraphicURL);
1709 : }
1710 660 : else if ( aPropName == "GraphicSize" )
1711 : {
1712 132 : if ( pPropValue[ i ].Value.getValueType() == cppu::UnoType<awt::Size>::get())
1713 : {
1714 : // don't cast awt::Size to Size as on 64-bits they are not the same.
1715 132 : css::awt::Size aSize;
1716 132 : pPropValue[ i ].Value >>= aSize;
1717 : //aBuGraSize.nA = aSize.Width;
1718 : //aBuGraSize.nB = aSize.Height;
1719 : SAL_INFO("oox.shape", "graphic size: " << aSize.Width << "x" << aSize.Height);
1720 : }
1721 1697 : }
1722 : }
1723 : }
1724 :
1725 132 : if (nNumberingType == SVX_NUM_NUMBER_NONE)
1726 9 : return;
1727 :
1728 123 : if( !aGraphicURL.isEmpty() )
1729 : {
1730 3 : OUString sRelId = WriteImage( aGraphicURL );
1731 :
1732 3 : mpFS->startElementNS( XML_a, XML_buBlip, FSEND );
1733 3 : mpFS->singleElementNS( XML_a, XML_blip, FSNS( XML_r, XML_embed ), USS( sRelId ), FSEND );
1734 3 : mpFS->endElementNS( XML_a, XML_buBlip );
1735 : }
1736 : else
1737 : {
1738 120 : if(nBulletColor)
1739 : {
1740 89 : mpFS->startElementNS( XML_a, XML_buClr, FSEND );
1741 89 : WriteColor( nBulletColor );
1742 89 : mpFS->endElementNS( XML_a, XML_buClr );
1743 : }
1744 :
1745 120 : if( nBulletRelSize && nBulletRelSize != 100 )
1746 : mpFS->singleElementNS( XML_a, XML_buSzPct,
1747 93 : XML_val, IS( std::max( (sal_Int32)25000, std::min( (sal_Int32)400000, 1000*( (sal_Int32)nBulletRelSize ) ) ) ), FSEND );
1748 120 : if( bHasFontDesc )
1749 : mpFS->singleElementNS( XML_a, XML_buFont,
1750 : XML_typeface, aFontDesc.Name.toUtf8().getStr(),
1751 120 : XML_charset, (aFontDesc.CharSet == awt::CharSet::SYMBOL) ? "2" : NULL,
1752 120 : FSEND );
1753 :
1754 120 : OUString pAutoNumType = GetAutoNumType( nNumberingType, bSDot, bPBehind, bPBoth );
1755 :
1756 120 : if (!pAutoNumType.isEmpty())
1757 : {
1758 : mpFS->singleElementNS(XML_a, XML_buAutoNum,
1759 : XML_type, OUStringToOString(pAutoNumType, RTL_TEXTENCODING_UTF8).getStr(),
1760 30 : XML_startAt, nStartWith > 1 ? IS(nStartWith) : NULL,
1761 20 : FSEND);
1762 : }
1763 : else
1764 : {
1765 110 : aBulletChar = SubstituteBullet( aBulletChar, aFontDesc );
1766 110 : mpFS->singleElementNS(XML_a, XML_buChar, XML_char, USS( OUString( aBulletChar ) ), FSEND);
1767 120 : }
1768 123 : }
1769 : }
1770 :
1771 2214 : sal_Int32 DrawingML::getBulletMarginIndentation (Reference< XPropertySet > rXPropSet,sal_Int16 nLevel, const OUString& propName)
1772 : {
1773 2214 : if( nLevel < 0 || !GETA( NumberingRules ) )
1774 1950 : return 0;
1775 :
1776 264 : Reference< XIndexAccess > rXIndexAccess;
1777 :
1778 264 : if (!(mAny >>= rXIndexAccess) || nLevel >= rXIndexAccess->getCount())
1779 0 : return 0;
1780 :
1781 : SAL_INFO("oox.shape", "numbering rules");
1782 :
1783 528 : Sequence<PropertyValue> aPropertySequence;
1784 264 : rXIndexAccess->getByIndex(nLevel) >>= aPropertySequence;
1785 :
1786 264 : if (!aPropertySequence.hasElements())
1787 0 : return 0;
1788 :
1789 264 : sal_Int32 nPropertyCount = aPropertySequence.getLength();
1790 :
1791 264 : const PropertyValue* pPropValue = aPropertySequence.getArray();
1792 :
1793 2470 : for ( sal_Int32 i = 0; i < nPropertyCount; i++ )
1794 : {
1795 2470 : const void* pValue = pPropValue[ i ].Value.getValue();
1796 2470 : if ( pValue )
1797 : {
1798 2470 : OUString aPropName( pPropValue[ i ].Name );
1799 : SAL_INFO("oox.shape", "pro name: " << aPropName);
1800 2470 : if ( aPropName == propName )
1801 264 : return *( static_cast<sal_Int32 const *>(pValue) );
1802 : }
1803 : }
1804 :
1805 264 : return 0;
1806 : }
1807 :
1808 400 : const char* DrawingML::GetAlignment( sal_Int32 nAlignment )
1809 : {
1810 400 : const char* sAlignment = NULL;
1811 :
1812 400 : switch( nAlignment )
1813 : {
1814 : case style::ParagraphAdjust_CENTER:
1815 226 : sAlignment = "ctr";
1816 226 : break;
1817 : case style::ParagraphAdjust_RIGHT:
1818 29 : sAlignment = "r";
1819 29 : break;
1820 : case style::ParagraphAdjust_BLOCK:
1821 0 : sAlignment = "just";
1822 0 : break;
1823 : default:
1824 : ;
1825 : }
1826 :
1827 400 : return sAlignment;
1828 : }
1829 :
1830 100 : void DrawingML::WriteLinespacing( LineSpacing& rSpacing )
1831 : {
1832 100 : if( rSpacing.Mode == LineSpacingMode::PROP )
1833 : {
1834 : mpFS->singleElementNS( XML_a, XML_spcPct,
1835 : XML_val, I32S( ((sal_Int32)rSpacing.Height)*1000 ),
1836 100 : FSEND );
1837 : }
1838 : else
1839 : {
1840 : mpFS->singleElementNS( XML_a, XML_spcPts,
1841 : XML_val, I32S( rSpacing.Height ),
1842 0 : FSEND );
1843 : }
1844 100 : }
1845 :
1846 1107 : void DrawingML::WriteParagraphProperties( Reference< XTextContent > rParagraph )
1847 : {
1848 1107 : Reference< XPropertySet > rXPropSet( rParagraph, UNO_QUERY );
1849 2214 : Reference< XPropertyState > rXPropState( rParagraph, UNO_QUERY );
1850 : PropertyState eState;
1851 :
1852 1107 : if( !rXPropSet.is() || !rXPropState.is() )
1853 1107 : return;
1854 :
1855 1107 : sal_Int16 nLevel = -1;
1856 1107 : GET( nLevel, NumberingLevel );
1857 :
1858 1107 : sal_Int16 nAlignment( style::ParagraphAdjust_LEFT );
1859 1107 : GET( nAlignment, ParaAdjust );
1860 :
1861 1107 : bool bHasLinespacing = false;
1862 1107 : LineSpacing aLineSpacing;
1863 1107 : if( GETAD( ParaLineSpacing ) )
1864 100 : bHasLinespacing = ( mAny >>= aLineSpacing );
1865 :
1866 1107 : bool bRtl = false;
1867 1107 : if( GETA( WritingMode ) )
1868 : {
1869 : sal_Int16 nWritingMode;
1870 1107 : if( ( mAny >>= nWritingMode ) && nWritingMode == text::WritingMode2::RL_TB )
1871 : {
1872 1 : bRtl = true;
1873 : }
1874 : }
1875 :
1876 1107 : sal_Int32 nParaLeftMargin = 0;
1877 1107 : sal_Int32 nParaFirstLineIndent = 0;
1878 :
1879 1107 : GET( nParaLeftMargin, ParaLeftMargin );
1880 1107 : GET( nParaFirstLineIndent,ParaFirstLineIndent);
1881 :
1882 1107 : sal_Int32 nLeftMargin = getBulletMarginIndentation ( rXPropSet, nLevel,"LeftMargin");
1883 1107 : sal_Int32 nLineIndentation = getBulletMarginIndentation ( rXPropSet, nLevel,"FirstLineOffset");
1884 :
1885 1107 : if( nLevel != -1
1886 975 : || nAlignment != style::ParagraphAdjust_LEFT
1887 727 : || bHasLinespacing )
1888 : {
1889 400 : if (nParaLeftMargin) // For Paraghraph
1890 : mpFS->startElementNS( XML_a, XML_pPr,
1891 28 : XML_lvl, nLevel > 0 ? I32S( nLevel ) : NULL,
1892 33 : XML_marL, nParaLeftMargin > 0 ? I32S( oox::drawingml::convertHmmToEmu( nParaLeftMargin ) ) : NULL,
1893 31 : XML_indent, nParaFirstLineIndent ? I32S( oox::drawingml::convertHmmToEmu( nParaFirstLineIndent ) ) : NULL,
1894 : XML_algn, GetAlignment( nAlignment ),
1895 : XML_rtl, bRtl ? BS(bRtl) : NULL,
1896 61 : FSEND );
1897 : else
1898 : mpFS->startElementNS( XML_a, XML_pPr,
1899 861 : XML_lvl, nLevel > 0 ? I32S( nLevel ) : NULL,
1900 506 : XML_marL, nLeftMargin > 0 ? I32S( oox::drawingml::convertHmmToEmu( nLeftMargin ) ) : NULL,
1901 623 : XML_indent, nLineIndentation ? I32S( oox::drawingml::convertHmmToEmu( nLineIndentation ) ) : NULL,
1902 : XML_algn, GetAlignment( nAlignment ),
1903 : XML_rtl, bRtl ? BS(bRtl) : NULL,
1904 1367 : FSEND );
1905 :
1906 :
1907 :
1908 400 : if( bHasLinespacing )
1909 : {
1910 100 : mpFS->startElementNS( XML_a, XML_lnSpc, FSEND );
1911 100 : WriteLinespacing( aLineSpacing );
1912 100 : mpFS->endElementNS( XML_a, XML_lnSpc );
1913 : }
1914 :
1915 400 : WriteParagraphNumbering( rXPropSet, nLevel );
1916 :
1917 400 : mpFS->endElementNS( XML_a, XML_pPr );
1918 1107 : }
1919 : }
1920 :
1921 1107 : void DrawingML::WriteParagraph( Reference< XTextContent > rParagraph )
1922 : {
1923 1107 : Reference< XEnumerationAccess > access( rParagraph, UNO_QUERY );
1924 1107 : if( !access.is() )
1925 0 : return;
1926 :
1927 2214 : Reference< XEnumeration > enumeration( access->createEnumeration() );
1928 1107 : if( !enumeration.is() )
1929 0 : return;
1930 :
1931 1107 : mpFS->startElementNS( XML_a, XML_p, FSEND );
1932 :
1933 1107 : bool bPropertiesWritten = false;
1934 3325 : while( enumeration->hasMoreElements() )
1935 : {
1936 1111 : Reference< XTextRange > run;
1937 2222 : Any any ( enumeration->nextElement() );
1938 :
1939 1111 : if (any >>= run)
1940 : {
1941 1111 : if( !bPropertiesWritten )
1942 : {
1943 1107 : WriteParagraphProperties( rParagraph );
1944 1107 : bPropertiesWritten = true;
1945 : }
1946 1111 : WriteRun( run );
1947 : }
1948 1111 : }
1949 1107 : mpFS->singleElementNS( XML_a, XML_endParaRPr, FSEND );
1950 :
1951 2214 : mpFS->endElementNS( XML_a, XML_p );
1952 : }
1953 :
1954 1377 : void DrawingML::WriteText( Reference< XInterface > rXIface, const OUString& presetWarp, bool bBodyPr, bool bText, sal_Int32 nXmlNamespace )
1955 : {
1956 1377 : Reference< XText > xXText( rXIface, UNO_QUERY );
1957 2378 : Reference< XPropertySet > rXPropSet( rXIface, UNO_QUERY );
1958 :
1959 1377 : if( !xXText.is() )
1960 0 : return;
1961 :
1962 : #define DEFLRINS 254
1963 : #define DEFTBINS 127
1964 : sal_Int32 nLeft, nRight, nTop, nBottom;
1965 1377 : nLeft = nRight = DEFLRINS;
1966 1377 : nTop = nBottom = DEFTBINS;
1967 :
1968 : // top inset looks a bit different compared to ppt export
1969 : // check if something related doesn't work as expected
1970 1377 : GET( nLeft, TextLeftDistance );
1971 1377 : GET( nRight, TextRightDistance );
1972 1377 : GET( nTop, TextUpperDistance );
1973 1377 : GET( nBottom, TextLowerDistance );
1974 :
1975 1377 : TextVerticalAdjust eVerticalAlignment( TextVerticalAdjust_TOP );
1976 1377 : const char* sVerticalAlignment = NULL;
1977 1377 : GET( eVerticalAlignment, TextVerticalAdjust );
1978 1377 : if( eVerticalAlignment != TextVerticalAdjust_TOP )
1979 520 : sVerticalAlignment = GetTextVerticalAdjust(eVerticalAlignment);
1980 :
1981 1377 : const char* sWritingMode = NULL;
1982 1377 : bool bVertical = false;
1983 1377 : if( GETA( TextWritingMode ) )
1984 : {
1985 : WritingMode eMode;
1986 :
1987 1377 : if( ( mAny >>= eMode ) && eMode == WritingMode_TB_RL )
1988 : {
1989 0 : sWritingMode = "vert";
1990 0 : bVertical = true;
1991 : }
1992 : }
1993 :
1994 1377 : if ( GETA( CustomShapeGeometry ) )
1995 : {
1996 224 : Sequence< PropertyValue > aProps;
1997 224 : if ( mAny >>= aProps )
1998 : {
1999 1851 : for ( sal_Int32 i = 0, nElems = aProps.getLength(); i < nElems; ++i )
2000 : {
2001 1831 : sal_Int32 nTextRotateAngle = 0;
2002 1831 : if ( aProps[ i ].Name == "TextPreRotateAngle" && ( aProps[ i ].Value >>= nTextRotateAngle ) )
2003 : {
2004 204 : if ( nTextRotateAngle == -90 )
2005 : {
2006 0 : sWritingMode = "vert";
2007 0 : bVertical = true;
2008 : }
2009 204 : else if ( nTextRotateAngle == -270 )
2010 : {
2011 2 : sWritingMode = "vert270";
2012 2 : bVertical = true;
2013 : }
2014 204 : break;
2015 : }
2016 : }
2017 224 : }
2018 : }
2019 :
2020 1377 : TextHorizontalAdjust eHorizontalAlignment( TextHorizontalAdjust_CENTER );
2021 1377 : bool bHorizontalCenter = false;
2022 1377 : GET( eHorizontalAlignment, TextHorizontalAdjust );
2023 1377 : if( eHorizontalAlignment == TextHorizontalAdjust_CENTER )
2024 2 : bHorizontalCenter = true;
2025 1375 : else if( bVertical && eHorizontalAlignment == TextHorizontalAdjust_LEFT )
2026 0 : sVerticalAlignment = "b";
2027 :
2028 1377 : bool bHasWrap = false;
2029 1377 : bool bWrap = false;
2030 : // Only custom shapes obey the TextWordWrap option, normal text always wraps.
2031 1377 : if( dynamic_cast<SvxCustomShape*>(rXIface.get()) && GETA( TextWordWrap ) )
2032 : {
2033 26 : mAny >>= bWrap;
2034 26 : bHasWrap = true;
2035 : }
2036 :
2037 1377 : if (bBodyPr)
2038 : {
2039 1247 : const char* pWrap = bHasWrap && !bWrap ? "none" : NULL;
2040 1247 : if (GetDocumentType() == DOCUMENT_DOCX)
2041 : {
2042 : // In case of DOCX, if we want to have the same effect as
2043 : // TextShape's automatic word wrapping, then we need to set
2044 : // wrapping to square.
2045 246 : uno::Reference<lang::XServiceInfo> xServiceInfo(rXIface, uno::UNO_QUERY);
2046 246 : if (xServiceInfo.is() && xServiceInfo->supportsService("com.sun.star.drawing.TextShape"))
2047 88 : pWrap = "square";
2048 : }
2049 : mpFS->startElementNS( (nXmlNamespace ? nXmlNamespace : XML_a), XML_bodyPr,
2050 : XML_wrap, pWrap,
2051 3550 : XML_lIns, (nLeft != DEFLRINS) ? IS( oox::drawingml::convertHmmToEmu( nLeft ) ) : NULL,
2052 3549 : XML_rIns, (nRight != DEFLRINS) ? IS( oox::drawingml::convertHmmToEmu( nRight ) ) : NULL,
2053 3546 : XML_tIns, (nTop != DEFTBINS) ? IS( oox::drawingml::convertHmmToEmu( nTop ) ) : NULL,
2054 4598 : XML_bIns, (nBottom != DEFTBINS) ? IS( oox::drawingml::convertHmmToEmu( nBottom ) ) : NULL,
2055 : XML_anchor, sVerticalAlignment,
2056 : XML_anchorCtr, bHorizontalCenter ? "1" : NULL,
2057 : XML_vert, sWritingMode,
2058 10645 : FSEND );
2059 1247 : if( presetWarp != NULL && !presetWarp.isEmpty())
2060 : {
2061 : mpFS->singleElementNS(XML_a, XML_prstTxWarp, XML_prst, presetWarp.toUtf8().getStr(),
2062 33 : FSEND );
2063 : }
2064 1247 : if (GetDocumentType() == DOCUMENT_DOCX)
2065 : {
2066 246 : sal_Bool bTextAutoGrowHeight = sal_False;
2067 246 : GET(bTextAutoGrowHeight, TextAutoGrowHeight);
2068 246 : mpFS->singleElementNS(XML_a, (bTextAutoGrowHeight ? XML_spAutoFit : XML_noAutofit), FSEND);
2069 : }
2070 1247 : mpFS->endElementNS((nXmlNamespace ? nXmlNamespace : XML_a), XML_bodyPr);
2071 : }
2072 :
2073 2378 : Reference< XEnumerationAccess > access( xXText, UNO_QUERY );
2074 1377 : if( !access.is() || !bText )
2075 246 : return;
2076 :
2077 2132 : Reference< XEnumeration > enumeration( access->createEnumeration() );
2078 1131 : if( !enumeration.is() )
2079 0 : return;
2080 :
2081 2132 : uno::Reference<drawing::XShape> xShape(rXIface, uno::UNO_QUERY);
2082 1131 : SdrObject* pSdrObject = xShape.is() ? GetSdrObjectFromXShape(xShape) : 0;
2083 1131 : const SdrTextObj* pTxtObj = PTR_CAST(SdrTextObj, pSdrObject);
2084 1131 : if (pTxtObj && mpTextExport)
2085 : {
2086 130 : const OutlinerParaObject* pParaObj = 0;
2087 130 : bool bOwnParaObj = false;
2088 :
2089 : /*
2090 : #i13885#
2091 : When the object is actively being edited, that text is not set into
2092 : the objects normal text object, but lives in a separate object.
2093 : */
2094 130 : if (pTxtObj->IsTextEditActive())
2095 : {
2096 0 : pParaObj = pTxtObj->GetEditOutlinerParaObject();
2097 0 : bOwnParaObj = true;
2098 : }
2099 : else
2100 130 : pParaObj = pTxtObj->GetOutlinerParaObject();
2101 :
2102 130 : if (pParaObj)
2103 : {
2104 : // this is reached only in case some text is attached to the shape
2105 130 : mpTextExport->WriteOutliner(*pParaObj);
2106 130 : if (bOwnParaObj)
2107 0 : delete pParaObj;
2108 : }
2109 130 : return;
2110 : }
2111 :
2112 3109 : while( enumeration->hasMoreElements() )
2113 : {
2114 1107 : Reference< XTextContent > paragraph;
2115 2214 : Any any ( enumeration->nextElement() );
2116 :
2117 1107 : if( any >>= paragraph)
2118 1107 : WriteParagraph( paragraph );
2119 2108 : }
2120 :
2121 : }
2122 :
2123 1234 : void DrawingML::WritePresetShape( const char* pShape )
2124 : {
2125 : mpFS->startElementNS( XML_a, XML_prstGeom,
2126 : XML_prst, pShape,
2127 1234 : FSEND );
2128 1234 : mpFS->singleElementNS( XML_a, XML_avLst, FSEND );
2129 1234 : mpFS->endElementNS( XML_a, XML_prstGeom );
2130 1234 : }
2131 :
2132 13 : std::map< OString, std::vector<OString> > lcl_getAdjNames()
2133 : {
2134 13 : std::map< OString, std::vector<OString> > aRet;
2135 :
2136 26 : OUString aPath("$BRAND_BASE_DIR/" LIBO_SHARE_FOLDER "/filter/oox-drawingml-adj-names");
2137 13 : rtl::Bootstrap::expandMacros(aPath);
2138 26 : SvFileStream aStream(aPath, StreamMode::READ);
2139 13 : if (aStream.GetError() != ERRCODE_NONE)
2140 : SAL_WARN("oox", "failed to open oox-drawingml-adj-names");
2141 26 : OString aLine;
2142 13 : bool bNotDone = aStream.ReadLine(aLine);
2143 4550 : while (bNotDone)
2144 : {
2145 4524 : sal_Int32 nIndex = 0;
2146 : // Each line is in a "key\tvalue" format: read the key, the rest is the value.
2147 4524 : OString aKey = aLine.getToken(0, '\t', nIndex);
2148 9048 : OString aValue = aLine.copy(nIndex);
2149 4524 : aRet[aKey].push_back(aValue);
2150 4524 : bNotDone = aStream.ReadLine(aLine);
2151 4524 : }
2152 26 : return aRet;
2153 : }
2154 :
2155 298 : void DrawingML::WritePresetShape( const char* pShape, MSO_SPT eShapeType, bool bPredefinedHandlesUsed, sal_Int32 nAdjustmentsWhichNeedsToBeConverted, const PropertyValue& rProp )
2156 : {
2157 298 : static std::map< OString, std::vector<OString> > aAdjMap = lcl_getAdjNames();
2158 : // If there are predefined adj names for this shape type, look them up now.
2159 298 : std::vector<OString> aAdjustments;
2160 298 : if (aAdjMap.find(OString(pShape)) != aAdjMap.end())
2161 113 : aAdjustments = aAdjMap[OString(pShape)];
2162 :
2163 : mpFS->startElementNS( XML_a, XML_prstGeom,
2164 : XML_prst, pShape,
2165 298 : FSEND );
2166 298 : mpFS->startElementNS( XML_a, XML_avLst, FSEND );
2167 :
2168 596 : Sequence< drawing::EnhancedCustomShapeAdjustmentValue > aAdjustmentSeq;
2169 894 : if ( ( rProp.Value >>= aAdjustmentSeq )
2170 298 : && eShapeType != mso_sptActionButtonForwardNext // we have adjustments values for these type of shape, but MSO doesn't like them
2171 298 : && eShapeType != mso_sptActionButtonBackPrevious // so they are now disabled
2172 1490 : && OString(pShape) != "rect" //some shape types are commented out in pCustomShapeTypeTranslationTable[] & are being defaulted to rect & rect does not have adjustment values/name.
2173 : )
2174 : {
2175 : SAL_INFO("oox.shape", "adj seq len: " << aAdjustmentSeq.getLength());
2176 134 : if ( bPredefinedHandlesUsed )
2177 8 : EscherPropertyContainer::LookForPolarHandles( eShapeType, nAdjustmentsWhichNeedsToBeConverted );
2178 :
2179 134 : sal_Int32 nValue, nLength = aAdjustmentSeq.getLength();
2180 : //aAdjustments will give info about the number of adj values for a particular geometry. For example for hexagon aAdjustments.size() will be 2 and for circular arrow it will be 5 as per lcl_getAdjNames.
2181 134 : if(aAdjustments.size() == static_cast<sal_uInt32>(nLength))// In case there is a mismatch do not write the XML_gd tag.
2182 : {
2183 266 : for( sal_Int32 i=0; i < nLength; i++ )
2184 : {
2185 132 : if( EscherPropertyContainer::GetAdjustmentValue( aAdjustmentSeq[ i ], i, nAdjustmentsWhichNeedsToBeConverted, nValue ) )
2186 : {
2187 : // If the document model doesn't have an adjustment name (e.g. shape was created from VML), then take it from the predefined list.
2188 132 : OString aAdjName;
2189 132 : if (aAdjustmentSeq[i].Name.isEmpty() && static_cast<sal_uInt32>(i) < aAdjustments.size())
2190 11 : aAdjName = aAdjustments[i];
2191 :
2192 : mpFS->singleElementNS( XML_a, XML_gd,
2193 385 : XML_name, aAdjustmentSeq[ i ].Name.getLength() > 0 ? USS(aAdjustmentSeq[ i ].Name) : aAdjName.getStr(),
2194 264 : XML_fmla, OString("val " + OString::number( nValue )).getStr(),
2195 649 : FSEND );
2196 : }
2197 : }
2198 : }
2199 : }
2200 :
2201 298 : mpFS->endElementNS( XML_a, XML_avLst );
2202 596 : mpFS->endElementNS( XML_a, XML_prstGeom );
2203 298 : }
2204 :
2205 115 : void DrawingML::WriteCustomGeometry( Reference< XShape > rXShape )
2206 : {
2207 115 : uno::Reference< beans::XPropertySet > aXPropSet;
2208 223 : uno::Any aAny( rXShape->queryInterface(cppu::UnoType<beans::XPropertySet>::get()));
2209 :
2210 115 : if ( ! (aAny >>= aXPropSet) )
2211 0 : return;
2212 :
2213 : try
2214 : {
2215 115 : aAny = aXPropSet->getPropertyValue( "CustomShapeGeometry" );
2216 115 : if ( !aAny.hasValue() )
2217 0 : return;
2218 : }
2219 0 : catch( const ::uno::Exception& )
2220 : {
2221 0 : return;
2222 : }
2223 :
2224 :
2225 :
2226 : uno::Sequence< beans::PropertyValue > const * pGeometrySeq =
2227 115 : static_cast<uno::Sequence< beans::PropertyValue > const *>(aAny.getValue());
2228 :
2229 115 : if ( pGeometrySeq )
2230 : {
2231 876 : for( int i = 0; i < pGeometrySeq->getLength(); ++i )
2232 : {
2233 768 : const beans::PropertyValue& rProp = (*pGeometrySeq)[ i ];
2234 768 : if ( rProp.Name == "Path" )
2235 : {
2236 113 : uno::Sequence<beans::PropertyValue> aPathProp;
2237 113 : rProp.Value >>= aPathProp;
2238 :
2239 219 : uno::Sequence<drawing::EnhancedCustomShapeParameterPair> aPairs;
2240 219 : uno::Sequence<drawing::EnhancedCustomShapeSegment> aSegments;
2241 219 : uno::Sequence<awt::Size> aPathSize;
2242 390 : for (int j = 0; j < aPathProp.getLength(); ++j )
2243 : {
2244 277 : const beans::PropertyValue& rPathProp = aPathProp[j];
2245 277 : if (rPathProp.Name == "Coordinates")
2246 113 : rPathProp.Value >>= aPairs;
2247 164 : else if (rPathProp.Name == "Segments")
2248 106 : rPathProp.Value >>= aSegments;
2249 58 : else if (rPathProp.Name == "SubViewSize")
2250 26 : rPathProp.Value >>= aPathSize;
2251 : }
2252 :
2253 113 : if ( !aPairs.hasElements() || !aSegments.hasElements() )
2254 7 : return;
2255 :
2256 106 : int nExpectedPairCount = 0;
2257 685 : for( int j = 0; j < aSegments.getLength(); ++j )
2258 : {
2259 579 : nExpectedPairCount += aSegments[j].Count;
2260 : }
2261 :
2262 106 : if ( nExpectedPairCount > aPairs.getLength() )
2263 : {
2264 : SAL_WARN("oox", "Segments need " << nExpectedPairCount << " coordinates, but Coordinates have only " << aPairs.getLength() << " pairs.");
2265 0 : return;
2266 : }
2267 :
2268 106 : mpFS->startElementNS( XML_a, XML_custGeom, FSEND );
2269 106 : mpFS->singleElementNS( XML_a, XML_avLst, FSEND );
2270 106 : mpFS->singleElementNS( XML_a, XML_gdLst, FSEND );
2271 106 : mpFS->singleElementNS( XML_a, XML_ahLst, FSEND );
2272 : mpFS->singleElementNS( XML_a, XML_rect, XML_l, "l", XML_t, "t",
2273 106 : XML_r, "r", XML_b, "b", FSEND );
2274 106 : mpFS->startElementNS( XML_a, XML_pathLst, FSEND );
2275 :
2276 106 : if ( aPathSize.hasElements() )
2277 : {
2278 : mpFS->startElementNS( XML_a, XML_path,
2279 26 : XML_w, I64S( aPathSize[0].Width ),
2280 26 : XML_h, I64S( aPathSize[0].Height ),
2281 52 : FSEND );
2282 : }
2283 : else
2284 : {
2285 80 : sal_Int32 nXMin(0);
2286 80 : aPairs[0].First.Value >>= nXMin;
2287 80 : sal_Int32 nXMax = nXMin;
2288 80 : sal_Int32 nYMin(0);
2289 80 : aPairs[0].Second.Value >>= nYMin;
2290 80 : sal_Int32 nYMax = nYMin;
2291 :
2292 2192 : for ( int j = 0; j < aPairs.getLength(); ++j )
2293 : {
2294 2112 : sal_Int32 nCandidate(0);
2295 2112 : if ((aPairs[j].First.Value >>= nCandidate) && nCandidate < nXMin)
2296 2 : nXMin = nCandidate;
2297 2112 : if ((aPairs[j].Second.Value >>= nCandidate) && nCandidate < nYMin)
2298 0 : nYMin = nCandidate;
2299 2112 : if ((aPairs[j].First.Value >>= nCandidate) && nCandidate > nXMax)
2300 72 : nXMax = nCandidate;
2301 2112 : if ((aPairs[j].Second.Value >>= nCandidate) && nCandidate > nYMax)
2302 64 : nYMax = nCandidate;
2303 : }
2304 : mpFS->startElementNS( XML_a, XML_path,
2305 : XML_w, I64S( nXMax - nXMin ),
2306 : XML_h, I64S( nYMax - nYMin ),
2307 80 : FSEND );
2308 : }
2309 :
2310 :
2311 106 : int nPairIndex = 0;
2312 685 : for( int j = 0; j < aSegments.getLength(); ++j )
2313 : {
2314 579 : if ( aSegments[ j ].Command == drawing::EnhancedCustomShapeSegmentCommand::CLOSESUBPATH )
2315 : {
2316 15 : mpFS->singleElementNS( XML_a, XML_close, FSEND );
2317 : }
2318 1974 : for ( int k = 0; k < aSegments[j].Count; ++k )
2319 : {
2320 1395 : switch( aSegments[ j ].Command )
2321 : {
2322 : case drawing::EnhancedCustomShapeSegmentCommand::MOVETO :
2323 : {
2324 158 : mpFS->startElementNS( XML_a, XML_moveTo, FSEND );
2325 :
2326 158 : sal_Int32 nX(0), nY(0);
2327 158 : aPairs[nPairIndex].First.Value >>= nX;
2328 158 : aPairs[nPairIndex].Second.Value >>= nY;
2329 :
2330 : mpFS->singleElementNS( XML_a, XML_pt,
2331 : XML_x, I64S(nX),
2332 : XML_y, I64S(nY),
2333 158 : FSEND );
2334 :
2335 158 : mpFS->endElementNS( XML_a, XML_moveTo );
2336 158 : nPairIndex++;
2337 158 : break;
2338 : }
2339 : case drawing::EnhancedCustomShapeSegmentCommand::LINETO :
2340 : {
2341 672 : mpFS->startElementNS( XML_a, XML_lnTo, FSEND );
2342 :
2343 672 : sal_Int32 nX(0), nY(0);
2344 672 : aPairs[nPairIndex].First.Value >>= nX;
2345 672 : aPairs[nPairIndex].Second.Value >>= nY;
2346 :
2347 : mpFS->singleElementNS( XML_a, XML_pt,
2348 : XML_x, I64S(nX),
2349 : XML_y, I64S(nY),
2350 672 : FSEND );
2351 672 : mpFS->endElementNS( XML_a, XML_lnTo );
2352 672 : nPairIndex++;
2353 672 : break;
2354 : }
2355 : case drawing::EnhancedCustomShapeSegmentCommand::CURVETO :
2356 : {
2357 562 : mpFS->startElementNS( XML_a, XML_cubicBezTo, FSEND );
2358 2248 : for( sal_uInt8 l = 0; l <= 2; ++l )
2359 : {
2360 1686 : sal_Int32 nX(0), nY(0);
2361 1686 : aPairs[nPairIndex+l].First.Value >>= nX;
2362 1686 : aPairs[nPairIndex+l].Second.Value >>= nY;
2363 :
2364 : mpFS->singleElementNS( XML_a, XML_pt,
2365 : XML_x, I64S( nX ),
2366 : XML_y, I64S( nY ),
2367 1686 : FSEND );
2368 :
2369 : }
2370 562 : mpFS->endElementNS( XML_a, XML_cubicBezTo );
2371 562 : nPairIndex += 3;
2372 562 : break;
2373 : }
2374 : case drawing::EnhancedCustomShapeSegmentCommand::ANGLEELLIPSETO :
2375 : case drawing::EnhancedCustomShapeSegmentCommand::ANGLEELLIPSE :
2376 : {
2377 1 : nPairIndex += 3;
2378 1 : break;
2379 : }
2380 : case drawing::EnhancedCustomShapeSegmentCommand::ARCTO :
2381 : case drawing::EnhancedCustomShapeSegmentCommand::ARC :
2382 : case drawing::EnhancedCustomShapeSegmentCommand::CLOCKWISEARCTO :
2383 : case drawing::EnhancedCustomShapeSegmentCommand::CLOCKWISEARC :
2384 : {
2385 2 : nPairIndex += 4;
2386 2 : break;
2387 : }
2388 : case drawing::EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTX :
2389 : case drawing::EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTY :
2390 : {
2391 0 : nPairIndex++;
2392 0 : break;
2393 : }
2394 : case drawing::EnhancedCustomShapeSegmentCommand::QUADRATICCURVETO :
2395 : {
2396 0 : mpFS->startElementNS( XML_a, XML_quadBezTo, FSEND );
2397 0 : for( sal_uInt8 l = 0; l < 2; ++l )
2398 : {
2399 0 : sal_Int32 nX(0), nY(0);
2400 0 : aPairs[nPairIndex+l].First.Value >>= nX;
2401 0 : aPairs[nPairIndex+l].Second.Value >>= nY;
2402 :
2403 : mpFS->singleElementNS( XML_a, XML_pt,
2404 : XML_x, I64S( nX ),
2405 : XML_y, I64S( nY ),
2406 0 : FSEND );
2407 :
2408 : }
2409 0 : mpFS->endElementNS( XML_a, XML_quadBezTo );
2410 0 : nPairIndex += 2;
2411 0 : break;
2412 : }
2413 : case drawing::EnhancedCustomShapeSegmentCommand::ARCANGLETO :
2414 : {
2415 0 : nPairIndex += 2;
2416 0 : break;
2417 : }
2418 : default:
2419 : // do nothing
2420 0 : break;
2421 : }
2422 : }
2423 : }
2424 106 : mpFS->endElementNS( XML_a, XML_path );
2425 106 : mpFS->endElementNS( XML_a, XML_pathLst );
2426 212 : mpFS->endElementNS( XML_a, XML_custGeom );
2427 : }
2428 : }
2429 108 : }
2430 :
2431 : }
2432 :
2433 44 : void DrawingML::WritePolyPolygon( const tools::PolyPolygon& rPolyPolygon )
2434 : {
2435 44 : if( rPolyPolygon.Count() < 1 )
2436 44 : return;
2437 :
2438 44 : mpFS->startElementNS( XML_a, XML_custGeom, FSEND );
2439 44 : mpFS->singleElementNS( XML_a, XML_avLst, FSEND );
2440 44 : mpFS->singleElementNS( XML_a, XML_gdLst, FSEND );
2441 44 : mpFS->singleElementNS( XML_a, XML_ahLst, FSEND );
2442 : mpFS->singleElementNS( XML_a, XML_rect,
2443 : XML_l, "0",
2444 : XML_t, "0",
2445 : XML_r, "r",
2446 : XML_b, "b",
2447 44 : FSEND );
2448 :
2449 44 : mpFS->startElementNS( XML_a, XML_pathLst, FSEND );
2450 :
2451 126 : for( sal_uInt16 i = 0; i < rPolyPolygon.Count(); i ++ )
2452 : {
2453 :
2454 82 : const Polygon& rPoly = rPolyPolygon[ i ];
2455 82 : Rectangle aRect( rPoly.GetBoundRect() );
2456 :
2457 : mpFS->startElementNS( XML_a, XML_path,
2458 : XML_w, I64S( aRect.GetWidth() ),
2459 : XML_h, I64S( aRect.GetHeight() ),
2460 82 : FSEND );
2461 :
2462 82 : if( rPoly.GetSize() > 0 )
2463 : {
2464 82 : mpFS->startElementNS( XML_a, XML_moveTo, FSEND );
2465 :
2466 : mpFS->singleElementNS( XML_a, XML_pt,
2467 82 : XML_x, I64S( rPoly[ 0 ].X() - aRect.Left() ),
2468 82 : XML_y, I64S( rPoly[ 0 ].Y() - aRect.Top() ),
2469 164 : FSEND );
2470 :
2471 82 : mpFS->endElementNS( XML_a, XML_moveTo );
2472 : }
2473 :
2474 755 : for( sal_uInt16 j = 1; j < rPoly.GetSize(); j ++ )
2475 : {
2476 673 : enum PolyFlags flags = rPoly.GetFlags(j);
2477 673 : if( flags == POLY_CONTROL )
2478 : {
2479 : // a:cubicBezTo can only contain 3 a:pt elements, so we need to make sure of this
2480 210 : if( j+2 < rPoly.GetSize() && rPoly.GetFlags(j+1) == POLY_CONTROL && rPoly.GetFlags(j+2) != POLY_CONTROL )
2481 : {
2482 :
2483 210 : mpFS->startElementNS( XML_a, XML_cubicBezTo, FSEND );
2484 840 : for( sal_uInt8 k = 0; k <= 2; ++k )
2485 : {
2486 : mpFS->singleElementNS( XML_a, XML_pt,
2487 630 : XML_x, I64S( rPoly[j+k].X() - aRect.Left() ),
2488 630 : XML_y, I64S( rPoly[j+k].Y() - aRect.Top() ),
2489 1260 : FSEND );
2490 :
2491 : }
2492 210 : mpFS->endElementNS( XML_a, XML_cubicBezTo );
2493 210 : j += 2;
2494 : }
2495 : }
2496 463 : else if( flags == POLY_NORMAL )
2497 : {
2498 463 : mpFS->startElementNS( XML_a, XML_lnTo, FSEND );
2499 : mpFS->singleElementNS( XML_a, XML_pt,
2500 463 : XML_x, I64S( rPoly[j].X() - aRect.Left() ),
2501 463 : XML_y, I64S( rPoly[j].Y() - aRect.Top() ),
2502 926 : FSEND );
2503 463 : mpFS->endElementNS( XML_a, XML_lnTo );
2504 : }
2505 : }
2506 :
2507 82 : mpFS->endElementNS( XML_a, XML_path );
2508 : }
2509 :
2510 44 : mpFS->endElementNS( XML_a, XML_pathLst );
2511 :
2512 44 : mpFS->endElementNS( XML_a, XML_custGeom );
2513 : }
2514 :
2515 0 : void DrawingML::WriteConnectorConnections( EscherConnectorListEntry& rConnectorEntry, sal_Int32 nStartID, sal_Int32 nEndID )
2516 : {
2517 0 : if( nStartID != -1 )
2518 : {
2519 : mpFS->singleElementNS( XML_a, XML_stCxn,
2520 : XML_id, I32S( nStartID ),
2521 0 : XML_idx, I64S( rConnectorEntry.GetConnectorRule( true ) ),
2522 0 : FSEND );
2523 : }
2524 0 : if( nEndID != -1 )
2525 : {
2526 : mpFS->singleElementNS( XML_a, XML_endCxn,
2527 : XML_id, I32S( nEndID ),
2528 0 : XML_idx, I64S( rConnectorEntry.GetConnectorRule( false ) ),
2529 0 : FSEND );
2530 : }
2531 0 : }
2532 :
2533 110 : sal_Unicode DrawingML::SubstituteBullet( sal_Unicode cBulletId, ::com::sun::star::awt::FontDescriptor& rFontDesc )
2534 : {
2535 110 : if ( IsStarSymbol(rFontDesc.Name) )
2536 : {
2537 86 : rtl_TextEncoding eCharSet = rFontDesc.CharSet;
2538 86 : cBulletId = msfilter::util::bestFitOpenSymbolToMSFont(cBulletId, eCharSet, rFontDesc.Name);
2539 86 : rFontDesc.CharSet = eCharSet;
2540 : }
2541 :
2542 110 : return cBulletId;
2543 : }
2544 :
2545 24 : sax_fastparser::FSHelperPtr DrawingML::CreateOutputStream (
2546 : const OUString& sFullStream,
2547 : const OUString& sRelativeStream,
2548 : const Reference< XOutputStream >& xParentRelation,
2549 : const char* sContentType,
2550 : const char* sRelationshipType,
2551 : OUString* pRelationshipId )
2552 : {
2553 24 : OUString sRelationshipId;
2554 24 : if (xParentRelation.is())
2555 24 : sRelationshipId = GetFB()->addRelation( xParentRelation, OUString::createFromAscii( sRelationshipType), sRelativeStream );
2556 : else
2557 0 : sRelationshipId = GetFB()->addRelation( OUString::createFromAscii( sRelationshipType ), sRelativeStream );
2558 :
2559 24 : if( pRelationshipId )
2560 24 : *pRelationshipId = sRelationshipId;
2561 :
2562 24 : sax_fastparser::FSHelperPtr p = GetFB()->openFragmentStreamWithSerializer( sFullStream, OUString::createFromAscii( sContentType ) );
2563 :
2564 24 : return p;
2565 : }
2566 :
2567 1186 : void DrawingML::WriteFill( Reference< XPropertySet > xPropSet )
2568 : {
2569 1186 : if ( !GetProperty( xPropSet, "FillStyle" ) )
2570 194 : return;
2571 992 : FillStyle aFillStyle( FillStyle_NONE );
2572 992 : xPropSet->getPropertyValue( "FillStyle" ) >>= aFillStyle;
2573 :
2574 992 : if ( aFillStyle == FillStyle_SOLID && GetProperty( xPropSet, "FillTransparence" ) )
2575 : {
2576 : // map full transparent background to no fill
2577 613 : sal_Int16 nVal = 0;
2578 613 : xPropSet->getPropertyValue( "FillTransparence" ) >>= nVal;
2579 613 : if ( nVal == 100 )
2580 3 : aFillStyle = FillStyle_NONE;
2581 : }
2582 :
2583 992 : switch( aFillStyle )
2584 : {
2585 : case FillStyle_SOLID :
2586 611 : WriteSolidFill( xPropSet );
2587 611 : break;
2588 : case FillStyle_GRADIENT :
2589 57 : WriteGradientFill( xPropSet );
2590 57 : break;
2591 : case FillStyle_BITMAP :
2592 5 : WriteBlipFill( xPropSet, "FillBitmapURL" );
2593 5 : break;
2594 : case FillStyle_HATCH :
2595 14 : WritePattFill( xPropSet );
2596 14 : break;
2597 : case FillStyle_NONE:
2598 305 : mpFS->singleElementNS( XML_a, XML_noFill, FSEND );
2599 305 : break;
2600 : default:
2601 : ;
2602 : }
2603 :
2604 992 : return;
2605 : }
2606 :
2607 1287 : void DrawingML::WriteStyleProperties( sal_Int32 nTokenId, const Sequence< PropertyValue >& aProperties )
2608 : {
2609 1287 : if( aProperties.getLength() > 0 )
2610 : {
2611 386 : OUString sSchemeClr;
2612 386 : sal_uInt32 nIdx = 0;
2613 772 : Sequence< PropertyValue > aTransformations;
2614 2218 : for( sal_Int32 i=0; i < aProperties.getLength(); ++i)
2615 : {
2616 1832 : if( aProperties[i].Name == "SchemeClr" )
2617 386 : aProperties[i].Value >>= sSchemeClr;
2618 1446 : else if( aProperties[i].Name == "Idx" )
2619 386 : aProperties[i].Value >>= nIdx;
2620 1060 : else if( aProperties[i].Name == "Transformations" )
2621 386 : aProperties[i].Value >>= aTransformations;
2622 : }
2623 386 : mpFS->startElementNS( XML_a, nTokenId, XML_idx, I32S( nIdx ), FSEND );
2624 386 : WriteColor( sSchemeClr, aTransformations );
2625 772 : mpFS->endElementNS( XML_a, nTokenId );
2626 : }
2627 : else
2628 : {
2629 : // write mock <a:*Ref> tag
2630 901 : mpFS->singleElementNS( XML_a, nTokenId, XML_idx, I32S( 0 ), FSEND );
2631 : }
2632 1287 : }
2633 :
2634 429 : void DrawingML::WriteShapeStyle( Reference< XPropertySet > xPropSet )
2635 : {
2636 : // check existence of the grab bag
2637 429 : if ( !GetProperty( xPropSet, "InteropGrabBag" ) )
2638 429 : return;
2639 :
2640 : // extract the relevant properties from the grab bag
2641 429 : Sequence< PropertyValue > aGrabBag;
2642 858 : Sequence< PropertyValue > aFillRefProperties, aLnRefProperties, aEffectRefProperties;
2643 429 : mAny >>= aGrabBag;
2644 2348 : for( sal_Int32 i=0; i < aGrabBag.getLength(); ++i)
2645 : {
2646 1919 : if( aGrabBag[i].Name == "StyleFillRef" )
2647 98 : aGrabBag[i].Value >>= aFillRefProperties;
2648 1821 : else if( aGrabBag[i].Name == "StyleLnRef" )
2649 144 : aGrabBag[i].Value >>= aLnRefProperties;
2650 1677 : else if( aGrabBag[i].Name == "StyleEffectRef" )
2651 144 : aGrabBag[i].Value >>= aEffectRefProperties;
2652 : }
2653 :
2654 429 : WriteStyleProperties( XML_lnRef, aLnRefProperties );
2655 429 : WriteStyleProperties( XML_fillRef, aFillRefProperties );
2656 429 : WriteStyleProperties( XML_effectRef, aEffectRefProperties );
2657 :
2658 : // write mock <a:fontRef>
2659 858 : mpFS->singleElementNS( XML_a, XML_fontRef, XML_idx, "minor", FSEND );
2660 : }
2661 :
2662 78 : void DrawingML::WriteShapeEffect( const OUString& sName, const Sequence< PropertyValue >& aEffectProps )
2663 : {
2664 78 : if( aEffectProps.getLength() == 0 )
2665 78 : return;
2666 :
2667 : // assign the proper tag and enable bContainsColor if necessary
2668 78 : sal_Int32 nEffectToken = 0;
2669 78 : bool bContainsColor = false;
2670 78 : if( sName == "outerShdw" )
2671 : {
2672 59 : nEffectToken = FSNS( XML_a, XML_outerShdw );
2673 59 : bContainsColor = true;
2674 : }
2675 19 : else if( sName == "innerShdw" )
2676 : {
2677 2 : nEffectToken = FSNS( XML_a, XML_innerShdw );
2678 2 : bContainsColor = true;
2679 : }
2680 17 : else if( sName == "glow" )
2681 : {
2682 8 : nEffectToken = FSNS( XML_a, XML_glow );
2683 8 : bContainsColor = true;
2684 : }
2685 9 : else if( sName == "softEdge" )
2686 2 : nEffectToken = FSNS( XML_a, XML_softEdge );
2687 7 : else if( sName == "reflection" )
2688 7 : nEffectToken = FSNS( XML_a, XML_reflection );
2689 0 : else if( sName == "blur" )
2690 0 : nEffectToken = FSNS( XML_a, XML_blur );
2691 :
2692 78 : OUString sSchemeClr;
2693 78 : sal_uInt32 nRgbClr = 0;
2694 78 : sal_Int32 nAlpha = MAX_PERCENT;
2695 156 : Sequence< PropertyValue > aTransformations;
2696 78 : sax_fastparser::FastAttributeList *aOuterShdwAttrList = FastSerializerHelper::createAttrList();
2697 156 : sax_fastparser::XFastAttributeListRef xOuterShdwAttrList( aOuterShdwAttrList );
2698 312 : for( sal_Int32 i=0; i < aEffectProps.getLength(); ++i )
2699 : {
2700 234 : if( aEffectProps[i].Name == "Attribs" )
2701 : {
2702 : // read tag attributes
2703 78 : uno::Sequence< beans::PropertyValue > aOuterShdwProps;
2704 78 : aEffectProps[i].Value >>= aOuterShdwProps;
2705 355 : for( sal_Int32 j=0; j < aOuterShdwProps.getLength(); ++j )
2706 : {
2707 277 : if( aOuterShdwProps[j].Name == "algn" )
2708 : {
2709 57 : OUString sVal;
2710 57 : aOuterShdwProps[j].Value >>= sVal;
2711 57 : aOuterShdwAttrList->add( XML_algn, OUStringToOString( sVal, RTL_TEXTENCODING_UTF8 ).getStr() );
2712 : }
2713 220 : else if( aOuterShdwProps[j].Name == "blurRad" )
2714 : {
2715 27 : sal_Int32 nVal = 0;
2716 27 : aOuterShdwProps[j].Value >>= nVal;
2717 27 : aOuterShdwAttrList->add( XML_blurRad, OString::number( nVal ).getStr() );
2718 : }
2719 193 : else if( aOuterShdwProps[j].Name == "dir" )
2720 : {
2721 30 : sal_Int32 nVal = 0;
2722 30 : aOuterShdwProps[j].Value >>= nVal;
2723 30 : aOuterShdwAttrList->add( XML_dir, OString::number( nVal ).getStr() );
2724 : }
2725 163 : else if( aOuterShdwProps[j].Name == "dist" )
2726 : {
2727 63 : sal_Int32 nVal = 0;
2728 63 : aOuterShdwProps[j].Value >>= nVal;
2729 63 : aOuterShdwAttrList->add( XML_dist, OString::number( nVal ).getStr() );
2730 : }
2731 100 : else if( aOuterShdwProps[j].Name == "kx" )
2732 : {
2733 0 : sal_Int32 nVal = 0;
2734 0 : aOuterShdwProps[j].Value >>= nVal;
2735 0 : aOuterShdwAttrList->add( XML_kx, OString::number( nVal ).getStr() );
2736 : }
2737 100 : else if( aOuterShdwProps[j].Name == "ky" )
2738 : {
2739 0 : sal_Int32 nVal = 0;
2740 0 : aOuterShdwProps[j].Value >>= nVal;
2741 0 : aOuterShdwAttrList->add( XML_ky, OString::number( nVal ).getStr() );
2742 : }
2743 100 : else if( aOuterShdwProps[j].Name == "rotWithShape" )
2744 : {
2745 63 : sal_Int32 nVal = 0;
2746 63 : aOuterShdwProps[j].Value >>= nVal;
2747 63 : aOuterShdwAttrList->add( XML_rotWithShape, OString::number( nVal ).getStr() );
2748 : }
2749 37 : else if( aOuterShdwProps[j].Name == "sx" )
2750 : {
2751 0 : sal_Int32 nVal = 0;
2752 0 : aOuterShdwProps[j].Value >>= nVal;
2753 0 : aOuterShdwAttrList->add( XML_sx, OString::number( nVal ).getStr() );
2754 : }
2755 37 : else if( aOuterShdwProps[j].Name == "sy" )
2756 : {
2757 7 : sal_Int32 nVal = 0;
2758 7 : aOuterShdwProps[j].Value >>= nVal;
2759 7 : aOuterShdwAttrList->add( XML_sy, OString::number( nVal ).getStr() );
2760 : }
2761 30 : else if( aOuterShdwProps[j].Name == "rad" )
2762 : {
2763 10 : sal_Int32 nVal = 0;
2764 10 : aOuterShdwProps[j].Value >>= nVal;
2765 10 : aOuterShdwAttrList->add( XML_rad, OString::number( nVal ).getStr() );
2766 : }
2767 20 : else if( aOuterShdwProps[j].Name == "endA" )
2768 : {
2769 6 : sal_Int32 nVal = 0;
2770 6 : aOuterShdwProps[j].Value >>= nVal;
2771 6 : aOuterShdwAttrList->add( XML_endA, OString::number( nVal ).getStr() );
2772 : }
2773 14 : else if( aOuterShdwProps[j].Name == "endPos" )
2774 : {
2775 7 : sal_Int32 nVal = 0;
2776 7 : aOuterShdwProps[j].Value >>= nVal;
2777 7 : aOuterShdwAttrList->add( XML_endPos, OString::number( nVal ).getStr() );
2778 : }
2779 7 : else if( aOuterShdwProps[j].Name == "fadeDir" )
2780 : {
2781 0 : sal_Int32 nVal = 0;
2782 0 : aOuterShdwProps[j].Value >>= nVal;
2783 0 : aOuterShdwAttrList->add( XML_fadeDir, OString::number( nVal ).getStr() );
2784 : }
2785 7 : else if( aOuterShdwProps[j].Name == "stA" )
2786 : {
2787 7 : sal_Int32 nVal = 0;
2788 7 : aOuterShdwProps[j].Value >>= nVal;
2789 7 : aOuterShdwAttrList->add( XML_stA, OString::number( nVal ).getStr() );
2790 : }
2791 0 : else if( aOuterShdwProps[j].Name == "stPos" )
2792 : {
2793 0 : sal_Int32 nVal = 0;
2794 0 : aOuterShdwProps[j].Value >>= nVal;
2795 0 : aOuterShdwAttrList->add( XML_stPos, OString::number( nVal ).getStr() );
2796 : }
2797 0 : else if( aOuterShdwProps[j].Name == "grow" )
2798 : {
2799 0 : sal_Int32 nVal = 0;
2800 0 : aOuterShdwProps[j].Value >>= nVal;
2801 0 : aOuterShdwAttrList->add( XML_grow, OString::number( nVal ).getStr() );
2802 : }
2803 78 : }
2804 : }
2805 156 : else if(aEffectProps[i].Name == "RgbClr")
2806 : {
2807 69 : aEffectProps[i].Value >>= nRgbClr;
2808 : }
2809 87 : else if(aEffectProps[i].Name == "RgbClrTransparency")
2810 : {
2811 : sal_Int32 nTransparency;
2812 69 : if (aEffectProps[i].Value >>= nTransparency)
2813 : // Calculate alpha value (see oox/source/drawingml/color.cxx : getTransparency())
2814 69 : nAlpha = MAX_PERCENT - ( PER_PERCENT * nTransparency );
2815 : }
2816 18 : else if(aEffectProps[i].Name == "SchemeClr")
2817 : {
2818 9 : aEffectProps[i].Value >>= sSchemeClr;
2819 : }
2820 9 : else if(aEffectProps[i].Name == "SchemeClrTransformations")
2821 : {
2822 9 : aEffectProps[i].Value >>= aTransformations;
2823 : }
2824 : }
2825 :
2826 78 : if( nEffectToken > 0 )
2827 : {
2828 78 : mpFS->startElement( nEffectToken, xOuterShdwAttrList );
2829 :
2830 78 : if( bContainsColor )
2831 : {
2832 69 : if( sSchemeClr.isEmpty() )
2833 60 : WriteColor( nRgbClr, nAlpha );
2834 : else
2835 9 : WriteColor( sSchemeClr, aTransformations );
2836 : }
2837 :
2838 78 : mpFS->endElement( nEffectToken );
2839 78 : }
2840 : }
2841 :
2842 523 : void DrawingML::WriteShapeEffects( Reference< XPropertySet > rXPropSet )
2843 : {
2844 523 : if( !GetProperty( rXPropSet, "InteropGrabBag" ) )
2845 456 : return;
2846 :
2847 590 : Sequence< PropertyValue > aGrabBag, aEffects;
2848 523 : mAny >>= aGrabBag;
2849 2114 : for( sal_Int32 i=0; i < aGrabBag.getLength(); ++i )
2850 : {
2851 1658 : if( aGrabBag[i].Name == "EffectProperties" )
2852 : {
2853 67 : aGrabBag[i].Value >>= aEffects;
2854 67 : break;
2855 : }
2856 : }
2857 523 : if( aEffects.getLength() == 0 )
2858 : {
2859 456 : bool bHasShadow = false;
2860 456 : rXPropSet->getPropertyValue( "Shadow" ) >>= bHasShadow;
2861 456 : if( bHasShadow )
2862 : {
2863 2 : Sequence< PropertyValue > aShadowGrabBag( 3 );
2864 4 : Sequence< PropertyValue > aShadowAttribsGrabBag( 2 );
2865 :
2866 2 : double dX = +0.0, dY = +0.0;
2867 2 : rXPropSet->getPropertyValue( "ShadowXDistance" ) >>= dX;
2868 2 : rXPropSet->getPropertyValue( "ShadowYDistance" ) >>= dY;
2869 :
2870 2 : aShadowAttribsGrabBag[0].Name = "dist";
2871 2 : aShadowAttribsGrabBag[0].Value = Any(static_cast< sal_Int32 >(sqrt(dX*dX + dY*dY) * 360));
2872 2 : aShadowAttribsGrabBag[1].Name = "dir";
2873 2 : aShadowAttribsGrabBag[1].Value = Any(static_cast< sal_Int32 >(atan2(dY,dX) * 180 * 60000 / M_PI));
2874 :
2875 2 : aShadowGrabBag[0].Name = "Attribs";
2876 2 : aShadowGrabBag[0].Value = Any(aShadowAttribsGrabBag);
2877 2 : aShadowGrabBag[1].Name = "RgbClr";
2878 2 : aShadowGrabBag[1].Value = rXPropSet->getPropertyValue( "ShadowColor" );
2879 2 : aShadowGrabBag[2].Name = "RgbClrTransparency";
2880 2 : aShadowGrabBag[2].Value = rXPropSet->getPropertyValue( "ShadowTransparence" );
2881 :
2882 2 : mpFS->startElementNS(XML_a, XML_effectLst, FSEND);
2883 2 : WriteShapeEffect( "outerShdw", aShadowGrabBag );
2884 4 : mpFS->endElementNS(XML_a, XML_effectLst);
2885 : }
2886 456 : return;
2887 : }
2888 :
2889 67 : mpFS->startElementNS(XML_a, XML_effectLst, FSEND);
2890 :
2891 143 : for( sal_Int32 i=0; i < aEffects.getLength(); ++i )
2892 : {
2893 76 : Sequence< PropertyValue > aEffectProps;
2894 76 : aEffects[i].Value >>= aEffectProps;
2895 76 : WriteShapeEffect( aEffects[i].Name, aEffectProps );
2896 76 : }
2897 :
2898 134 : mpFS->endElementNS(XML_a, XML_effectLst);
2899 : }
2900 :
2901 523 : void DrawingML::WriteShape3DEffects( Reference< XPropertySet > xPropSet )
2902 : {
2903 : // check existence of the grab bag
2904 523 : if( !GetProperty( xPropSet, "InteropGrabBag" ) )
2905 515 : return;
2906 :
2907 : // extract the relevant properties from the grab bag
2908 531 : Sequence< PropertyValue > aGrabBag, aEffectProps, aLightRigProps, aShape3DProps;
2909 523 : mAny >>= aGrabBag;
2910 2387 : for( sal_Int32 i=0; i < aGrabBag.getLength(); ++i )
2911 : {
2912 1873 : if( aGrabBag[i].Name == "3DEffectProperties" )
2913 : {
2914 9 : Sequence< PropertyValue > a3DEffectProps;
2915 9 : aGrabBag[i].Value >>= a3DEffectProps;
2916 36 : for( sal_Int32 j=0; j < a3DEffectProps.getLength(); ++j )
2917 : {
2918 27 : if( a3DEffectProps[j].Name == "Camera" )
2919 9 : a3DEffectProps[j].Value >>= aEffectProps;
2920 18 : else if( a3DEffectProps[j].Name == "LightRig" )
2921 9 : a3DEffectProps[j].Value >>= aLightRigProps;
2922 9 : else if( a3DEffectProps[j].Name == "Shape3D" )
2923 9 : a3DEffectProps[j].Value >>= aShape3DProps;
2924 : }
2925 9 : break;
2926 : }
2927 : }
2928 523 : if( aEffectProps.getLength() == 0 && aLightRigProps.getLength() == 0 && aShape3DProps.getLength() == 0 )
2929 514 : return;
2930 :
2931 9 : bool bCameraRotationPresent = false;
2932 9 : sax_fastparser::FastAttributeList *aCameraAttrList = FastSerializerHelper::createAttrList();
2933 17 : sax_fastparser::XFastAttributeListRef xCameraAttrList( aCameraAttrList );
2934 9 : sax_fastparser::FastAttributeList *aCameraRotationAttrList = FastSerializerHelper::createAttrList();
2935 17 : sax_fastparser::XFastAttributeListRef xRotAttrList( aCameraRotationAttrList );
2936 25 : for( sal_Int32 i=0; i < aEffectProps.getLength(); ++i )
2937 : {
2938 16 : if( aEffectProps[i].Name == "prst" )
2939 : {
2940 9 : OUString sVal;
2941 9 : aEffectProps[i].Value >>= sVal;
2942 9 : aCameraAttrList->add( XML_prst, OUStringToOString( sVal, RTL_TEXTENCODING_UTF8 ).getStr() );
2943 : }
2944 7 : else if( aEffectProps[i].Name == "fov" )
2945 : {
2946 0 : float fVal = 0;
2947 0 : aEffectProps[i].Value >>= fVal;
2948 0 : aCameraAttrList->add( XML_fov, OString::number( fVal * 60000 ).getStr() );
2949 : }
2950 7 : else if( aEffectProps[i].Name == "zoom" )
2951 : {
2952 1 : float fVal = 1;
2953 1 : aEffectProps[i].Value >>= fVal;
2954 1 : aCameraAttrList->add( XML_zoom, OString::number( fVal * 100000 ).getStr() );
2955 : }
2956 16 : else if( aEffectProps[i].Name == "rotLat" ||
2957 8 : aEffectProps[i].Name == "rotLon" ||
2958 2 : aEffectProps[i].Name == "rotRev" )
2959 : {
2960 6 : sal_Int32 nVal = 0, nToken = XML_none;
2961 6 : aEffectProps[i].Value >>= nVal;
2962 6 : if( aEffectProps[i].Name == "rotLat" )
2963 2 : nToken = XML_lat;
2964 4 : else if( aEffectProps[i].Name == "rotLon" )
2965 2 : nToken = XML_lon;
2966 2 : else if( aEffectProps[i].Name == "rotRev" )
2967 2 : nToken = XML_rev;
2968 6 : aCameraRotationAttrList->add( nToken, OString::number( nVal ).getStr() );
2969 6 : bCameraRotationPresent = true;
2970 : }
2971 : }
2972 :
2973 9 : bool bLightRigRotationPresent = false;
2974 9 : sax_fastparser::FastAttributeList *aLightRigAttrList = FastSerializerHelper::createAttrList();
2975 17 : sax_fastparser::XFastAttributeListRef xLightAttrList( aLightRigAttrList );
2976 9 : sax_fastparser::FastAttributeList *aLightRigRotationAttrList = FastSerializerHelper::createAttrList();
2977 17 : sax_fastparser::XFastAttributeListRef xLightRotAttrList( aLightRigRotationAttrList );
2978 42 : for( sal_Int32 i=0; i < aLightRigProps.getLength(); ++i )
2979 : {
2980 33 : if( aLightRigProps[i].Name == "rig" || aLightRigProps[i].Name == "dir" )
2981 : {
2982 18 : OUString sVal;
2983 18 : sal_Int32 nToken = XML_none;
2984 18 : aLightRigProps[i].Value >>= sVal;
2985 18 : if( aLightRigProps[i].Name == "rig" )
2986 9 : nToken = XML_rig;
2987 9 : else if( aLightRigProps[i].Name == "dir" )
2988 9 : nToken = XML_dir;
2989 18 : aLightRigAttrList->add( nToken, OUStringToOString( sVal, RTL_TEXTENCODING_UTF8 ).getStr() );
2990 : }
2991 40 : else if( aLightRigProps[i].Name == "rotLat" ||
2992 20 : aLightRigProps[i].Name == "rotLon" ||
2993 5 : aLightRigProps[i].Name == "rotRev" )
2994 : {
2995 15 : sal_Int32 nVal = 0, nToken = XML_none;
2996 15 : aLightRigProps[i].Value >>= nVal;
2997 15 : if( aLightRigProps[i].Name == "rotLat" )
2998 5 : nToken = XML_lat;
2999 10 : else if( aLightRigProps[i].Name == "rotLon" )
3000 5 : nToken = XML_lon;
3001 5 : else if( aLightRigProps[i].Name == "rotRev" )
3002 5 : nToken = XML_rev;
3003 15 : aLightRigRotationAttrList->add( nToken, OString::number( nVal ).getStr() );
3004 15 : bLightRigRotationPresent = true;
3005 : }
3006 : }
3007 :
3008 9 : mpFS->startElementNS( XML_a, XML_scene3d, FSEND );
3009 :
3010 9 : if( aEffectProps.getLength() > 0 )
3011 : {
3012 9 : mpFS->startElementNS( XML_a, XML_camera, xCameraAttrList );
3013 9 : if( bCameraRotationPresent )
3014 : {
3015 2 : mpFS->singleElementNS( XML_a, XML_rot, xRotAttrList );
3016 : }
3017 9 : mpFS->endElementNS( XML_a, XML_camera );
3018 : }
3019 : else
3020 : {
3021 : // a:camera with Word default values - Word won't open the document if this is not present
3022 0 : mpFS->singleElementNS( XML_a, XML_camera, XML_prst, "orthographicFront", FSEND );
3023 : }
3024 :
3025 9 : if( aEffectProps.getLength() > 0 )
3026 : {
3027 9 : mpFS->startElementNS( XML_a, XML_lightRig, xLightAttrList );
3028 9 : if( bLightRigRotationPresent )
3029 : {
3030 5 : mpFS->singleElementNS( XML_a, XML_rot, xLightRotAttrList );
3031 : }
3032 9 : mpFS->endElementNS( XML_a, XML_lightRig );
3033 : }
3034 : else
3035 : {
3036 : // a:lightRig with Word default values - Word won't open the document if this is not present
3037 0 : mpFS->singleElementNS( XML_a, XML_lightRig, XML_rig, "threePt", XML_dir, "t", FSEND );
3038 : }
3039 :
3040 9 : mpFS->endElementNS( XML_a, XML_scene3d );
3041 :
3042 9 : if( aShape3DProps.getLength() == 0 )
3043 1 : return;
3044 :
3045 8 : bool bBevelTPresent = false, bBevelBPresent = false;
3046 16 : Sequence< PropertyValue > aExtrusionColorProps, aContourColorProps;
3047 8 : sax_fastparser::FastAttributeList *aBevelTAttrList = FastSerializerHelper::createAttrList();
3048 16 : sax_fastparser::XFastAttributeListRef xBevelTAttrList( aBevelTAttrList );
3049 8 : sax_fastparser::FastAttributeList *aBevelBAttrList = FastSerializerHelper::createAttrList();
3050 16 : sax_fastparser::XFastAttributeListRef xBevelBAttrList( aBevelBAttrList );
3051 8 : sax_fastparser::FastAttributeList *aShape3DAttrList = FastSerializerHelper::createAttrList();
3052 29 : for( sal_Int32 i=0; i < aShape3DProps.getLength(); ++i )
3053 : {
3054 21 : if( aShape3DProps[i].Name == "extrusionH" || aShape3DProps[i].Name == "contourW" || aShape3DProps[i].Name == "z" )
3055 : {
3056 6 : sal_Int32 nVal = 0, nToken = XML_none;
3057 6 : aShape3DProps[i].Value >>= nVal;
3058 6 : if( aShape3DProps[i].Name == "extrusionH" )
3059 4 : nToken = XML_extrusionH;
3060 2 : else if( aShape3DProps[i].Name == "contourW" )
3061 1 : nToken = XML_contourW;
3062 1 : else if( aShape3DProps[i].Name == "z" )
3063 1 : nToken = XML_z;
3064 6 : aShape3DAttrList->add( nToken, OString::number( nVal ).getStr() );
3065 : }
3066 15 : else if( aShape3DProps[i].Name == "prstMaterial" )
3067 : {
3068 6 : OUString sVal;
3069 6 : aShape3DProps[i].Value >>= sVal;
3070 6 : aShape3DAttrList->add( XML_prstMaterial, OUStringToOString( sVal, RTL_TEXTENCODING_UTF8 ).getStr() );
3071 : }
3072 9 : else if( aShape3DProps[i].Name == "extrusionClr" )
3073 : {
3074 2 : aShape3DProps[i].Value >>= aExtrusionColorProps;
3075 : }
3076 7 : else if( aShape3DProps[i].Name == "contourClr" )
3077 : {
3078 2 : aShape3DProps[i].Value >>= aContourColorProps;
3079 : }
3080 5 : else if( aShape3DProps[i].Name == "bevelT" || aShape3DProps[i].Name == "bevelB" )
3081 : {
3082 5 : Sequence< PropertyValue > aBevelProps;
3083 5 : aShape3DProps[i].Value >>= aBevelProps;
3084 5 : if ( aBevelProps.getLength() == 0 )
3085 0 : continue;
3086 :
3087 5 : sax_fastparser::FastAttributeList *aBevelAttrList = NULL;
3088 5 : if( aShape3DProps[i].Name == "bevelT" )
3089 : {
3090 4 : bBevelTPresent = true;
3091 4 : aBevelAttrList = aBevelTAttrList;
3092 : }
3093 : else
3094 : {
3095 1 : bBevelBPresent = true;
3096 1 : aBevelAttrList = aBevelBAttrList;
3097 : }
3098 19 : for( sal_Int32 j=0; j < aBevelProps.getLength(); ++j )
3099 : {
3100 14 : if( aBevelProps[j].Name == "w" || aBevelProps[j].Name == "h" )
3101 : {
3102 9 : sal_Int32 nVal = 0, nToken = XML_none;
3103 9 : aBevelProps[j].Value >>= nVal;
3104 9 : if( aBevelProps[j].Name == "w" )
3105 4 : nToken = XML_w;
3106 5 : else if( aBevelProps[j].Name == "h" )
3107 5 : nToken = XML_h;
3108 9 : aBevelAttrList->add( nToken, OString::number( nVal ).getStr() );
3109 : }
3110 5 : else if( aBevelProps[j].Name == "prst" )
3111 : {
3112 5 : OUString sVal;
3113 5 : aBevelProps[j].Value >>= sVal;
3114 5 : aBevelAttrList->add( XML_prst, OUStringToOString( sVal, RTL_TEXTENCODING_UTF8 ).getStr() );
3115 : }
3116 5 : }
3117 :
3118 : }
3119 : }
3120 :
3121 16 : sax_fastparser::XFastAttributeListRef xAttrList( aShape3DAttrList );
3122 8 : mpFS->startElementNS( XML_a, XML_sp3d, xAttrList );
3123 8 : if( bBevelTPresent )
3124 : {
3125 4 : mpFS->singleElementNS( XML_a, XML_bevelT, xBevelTAttrList );
3126 : }
3127 8 : if( bBevelBPresent )
3128 : {
3129 1 : mpFS->singleElementNS( XML_a, XML_bevelB, xBevelBAttrList );
3130 : }
3131 8 : if( aExtrusionColorProps.getLength() > 0 )
3132 : {
3133 2 : OUString sSchemeClr;
3134 2 : sal_Int32 nColor(0);
3135 2 : sal_Int32 nTransparency(0);
3136 4 : Sequence< PropertyValue > aColorTransformations;
3137 6 : for( sal_Int32 i=0; i < aExtrusionColorProps.getLength(); ++i )
3138 : {
3139 4 : if( aExtrusionColorProps[i].Name == "schemeClr" )
3140 1 : aExtrusionColorProps[i].Value >>= sSchemeClr;
3141 3 : else if( aExtrusionColorProps[i].Name == "schemeClrTransformations" )
3142 1 : aExtrusionColorProps[i].Value >>= aColorTransformations;
3143 2 : else if( aExtrusionColorProps[i].Name == "rgbClr" )
3144 1 : aExtrusionColorProps[i].Value >>= nColor;
3145 1 : else if( aExtrusionColorProps[i].Name == "rgbClrTransparency" )
3146 1 : aExtrusionColorProps[i].Value >>= nTransparency;
3147 : }
3148 2 : mpFS->startElementNS( XML_a, XML_extrusionClr, FSEND );
3149 :
3150 2 : if( sSchemeClr.isEmpty() )
3151 1 : WriteColor( nColor, MAX_PERCENT - ( PER_PERCENT * nTransparency ) );
3152 : else
3153 1 : WriteColor( sSchemeClr, aColorTransformations );
3154 :
3155 4 : mpFS->endElementNS( XML_a, XML_extrusionClr );
3156 : }
3157 8 : if( aContourColorProps.getLength() > 0 )
3158 : {
3159 2 : OUString sSchemeClr;
3160 2 : sal_Int32 nColor(0);
3161 2 : sal_Int32 nTransparency(0);
3162 4 : Sequence< PropertyValue > aColorTransformations;
3163 6 : for( sal_Int32 i=0; i < aContourColorProps.getLength(); ++i )
3164 : {
3165 4 : if( aContourColorProps[i].Name == "schemeClr" )
3166 1 : aContourColorProps[i].Value >>= sSchemeClr;
3167 3 : else if( aContourColorProps[i].Name == "schemeClrTransformations" )
3168 1 : aContourColorProps[i].Value >>= aColorTransformations;
3169 2 : else if( aContourColorProps[i].Name == "rgbClr" )
3170 1 : aContourColorProps[i].Value >>= nColor;
3171 1 : else if( aContourColorProps[i].Name == "rgbClrTransparency" )
3172 1 : aContourColorProps[i].Value >>= nTransparency;
3173 : }
3174 2 : mpFS->startElementNS( XML_a, XML_contourClr, FSEND );
3175 :
3176 2 : if( sSchemeClr.isEmpty() )
3177 1 : WriteColor( nColor, MAX_PERCENT - ( PER_PERCENT * nTransparency ) );
3178 : else
3179 1 : WriteColor( sSchemeClr, aContourColorProps );
3180 :
3181 4 : mpFS->endElementNS( XML_a, XML_contourClr );
3182 : }
3183 16 : mpFS->endElementNS( XML_a, XML_sp3d );
3184 : }
3185 :
3186 116 : void DrawingML::WriteArtisticEffect( Reference< XPropertySet > rXPropSet )
3187 : {
3188 116 : if( !GetProperty( rXPropSet, "InteropGrabBag" ) )
3189 112 : return;
3190 :
3191 114 : PropertyValue aEffect;
3192 120 : Sequence< PropertyValue > aGrabBag;
3193 114 : mAny >>= aGrabBag;
3194 186 : for( sal_Int32 i=0; i < aGrabBag.getLength(); ++i )
3195 : {
3196 78 : if( aGrabBag[i].Name == "ArtisticEffectProperties" )
3197 : {
3198 6 : aGrabBag[i].Value >>= aEffect;
3199 6 : break;
3200 : }
3201 : }
3202 114 : sal_Int32 nEffectToken = ArtisticEffectProperties::getEffectToken( aEffect.Name );
3203 114 : if( nEffectToken == XML_none )
3204 108 : return;
3205 :
3206 12 : Sequence< PropertyValue > aAttrs;
3207 6 : aEffect.Value >>= aAttrs;
3208 6 : sax_fastparser::FastAttributeList *aAttrList = FastSerializerHelper::createAttrList();
3209 12 : OString sRelId;
3210 21 : for( sal_Int32 i=0; i < aAttrs.getLength(); ++i )
3211 : {
3212 15 : sal_Int32 nToken = ArtisticEffectProperties::getEffectToken( aAttrs[i].Name );
3213 15 : if( nToken != XML_none )
3214 : {
3215 9 : sal_Int32 nVal = 0;
3216 9 : aAttrs[i].Value >>= nVal;
3217 9 : aAttrList->add( nToken, OString::number( nVal ).getStr() );
3218 : }
3219 6 : else if( aAttrs[i].Name == "OriginalGraphic" )
3220 : {
3221 6 : Sequence< PropertyValue > aGraphic;
3222 6 : aAttrs[i].Value >>= aGraphic;
3223 12 : Sequence< sal_Int8 > aGraphicData;
3224 12 : OUString sGraphicId;
3225 18 : for( sal_Int32 j=0; j < aGraphic.getLength(); ++j )
3226 : {
3227 12 : if( aGraphic[j].Name == "Id" )
3228 6 : aGraphic[j].Value >>= sGraphicId;
3229 6 : else if( aGraphic[j].Name == "Data" )
3230 6 : aGraphic[j].Value >>= aGraphicData;
3231 : }
3232 12 : sRelId = WriteWdpPicture( sGraphicId, aGraphicData );
3233 : }
3234 : }
3235 :
3236 6 : mpFS->startElementNS( XML_a, XML_extLst, FSEND );
3237 : mpFS->startElementNS( XML_a, XML_ext,
3238 : XML_uri, "{BEBA8EAE-BF5A-486C-A8C5-ECC9F3942E4B}",
3239 6 : FSEND );
3240 : mpFS->startElementNS( XML_a14, XML_imgProps,
3241 : FSNS( XML_xmlns, XML_a14 ), "http://schemas.microsoft.com/office/drawing/2010/main",
3242 6 : FSEND );
3243 : mpFS->startElementNS( XML_a14, XML_imgLayer,
3244 : FSNS( XML_r, XML_embed), sRelId.getStr(),
3245 6 : FSEND );
3246 6 : mpFS->startElementNS( XML_a14, XML_imgEffect, FSEND );
3247 :
3248 12 : sax_fastparser::XFastAttributeListRef xAttrList( aAttrList );
3249 6 : mpFS->singleElementNS( XML_a14, nEffectToken, xAttrList );
3250 :
3251 6 : mpFS->endElementNS( XML_a14, XML_imgEffect );
3252 6 : mpFS->endElementNS( XML_a14, XML_imgLayer );
3253 6 : mpFS->endElementNS( XML_a14, XML_imgProps );
3254 6 : mpFS->endElementNS( XML_a, XML_ext );
3255 12 : mpFS->endElementNS( XML_a, XML_extLst );
3256 : }
3257 :
3258 6 : OString DrawingML::WriteWdpPicture( const OUString& rFileId, const Sequence< sal_Int8 >& rPictureData )
3259 : {
3260 6 : std::map<OUString, OUString>::iterator aCachedItem = maWdpCache.find( rFileId );
3261 6 : if( aCachedItem != maWdpCache.end() )
3262 4 : return OUStringToOString( aCachedItem->second, RTL_TEXTENCODING_UTF8 );
3263 :
3264 2 : OUString sFileName = "media/hdphoto" + OUString::number( mnWdpImageCounter++ ) + ".wdp";
3265 : uno::Reference< io::XOutputStream > xOutStream =
3266 4 : mpFB->openFragmentStream( "word/" + sFileName,
3267 8 : "image/vnd.ms-photo" );
3268 4 : OUString sId;
3269 2 : xOutStream->writeBytes( rPictureData );
3270 2 : xOutStream->closeOutput();
3271 :
3272 4 : sId = mpFB->addRelation( mpFS->getOutputStream(),
3273 : "http://schemas.microsoft.com/office/2007/relationships/hdphoto",
3274 2 : sFileName, false );
3275 :
3276 2 : maWdpCache[rFileId] = sId;
3277 4 : return OUStringToOString( sId, RTL_TEXTENCODING_UTF8 );
3278 : }
3279 :
3280 : }
3281 246 : }
3282 :
3283 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|