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