1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <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>
31 #include <com/sun/star/awt/CharSet.hpp>
32 #include <com/sun/star/awt/FontDescriptor.hpp>
33 #include <com/sun/star/awt/FontSlant.hpp>
34 #include <com/sun/star/awt/FontStrikeout.hpp>
35 #include <com/sun/star/awt/FontWeight.hpp>
36 #include <com/sun/star/awt/FontUnderline.hpp>
37 #include <com/sun/star/awt/Gradient.hpp>
38 #include <com/sun/star/beans/XPropertySet.hpp>
39 #include <com/sun/star/beans/XPropertyState.hpp>
40 #include <com/sun/star/beans/Property.hpp>
41 #include <com/sun/star/beans/XPropertySetInfo.hpp>
42 #include <com/sun/star/container/XEnumerationAccess.hpp>
43 #include <com/sun/star/container/XIndexAccess.hpp>
44 #include <com/sun/star/drawing/BitmapMode.hpp>
45 #include <com/sun/star/drawing/EnhancedCustomShapeAdjustmentValue.hpp>
46 #include <com/sun/star/drawing/EnhancedCustomShapeParameterType.hpp>
47 #include <com/sun/star/drawing/EnhancedCustomShapeParameterPair.hpp>
48 #include <com/sun/star/drawing/EnhancedCustomShapeSegment.hpp>
49 #include <com/sun/star/drawing/EnhancedCustomShapeSegmentCommand.hpp>
50 #include <com/sun/star/drawing/LineDash.hpp>
51 #include <com/sun/star/drawing/LineJoint.hpp>
52 #include <com/sun/star/drawing/LineStyle.hpp>
53 #include <com/sun/star/drawing/TextHorizontalAdjust.hpp>
54 #include <com/sun/star/drawing/TextVerticalAdjust.hpp>
55 #include <com/sun/star/drawing/XShape.hpp>
56 #include <com/sun/star/drawing/FillStyle.hpp>
57 #include <com/sun/star/geometry/IntegerRectangle2D.hpp>
58 #include <com/sun/star/i18n/ScriptType.hpp>
59 #include <com/sun/star/io/XOutputStream.hpp>
60 #include <com/sun/star/style/LineSpacing.hpp>
61 #include <com/sun/star/style/LineSpacingMode.hpp>
62 #include <com/sun/star/style/ParagraphAdjust.hpp>
63 #include <com/sun/star/text/WritingMode.hpp>
64 #include <com/sun/star/text/WritingMode2.hpp>
65 #include <com/sun/star/text/GraphicCrop.hpp>
66 #include <com/sun/star/text/XText.hpp>
67 #include <com/sun/star/text/XTextContent.hpp>
68 #include <com/sun/star/text/XTextField.hpp>
69 #include <com/sun/star/text/XTextRange.hpp>
70 #include <com/sun/star/style/CaseMap.hpp>
71 #include <tools/stream.hxx>
72 #include <unotools/fontdefs.hxx>
73 #include <vcl/cvtgrf.hxx>
74 #include <vcl/graph.hxx>
75 #include <vcl/settings.hxx>
76 #include <svtools/grfmgr.hxx>
77 #include <rtl/strbuf.hxx>
78 #include <sfx2/app.hxx>
79 #include <svl/languageoptions.hxx>
80 #include <filter/msfilter/escherex.hxx>
81 #include <filter/msfilter/util.hxx>
82 #include <editeng/outlobj.hxx>
83 #include <editeng/svxenum.hxx>
84 #include <svx/unoapi.hxx>
85 #include <svx/svdoashp.hxx>
86 #include <svx/unoshape.hxx>
88 using namespace ::css
;
89 using namespace ::css::beans
;
90 using namespace ::css::drawing
;
91 using namespace ::css::i18n
;
92 using namespace ::css::style
;
93 using namespace ::css::text
;
94 using namespace ::css::uno
;
95 using namespace ::css::container
;
96 using namespace ::css::text
;
98 using ::css::geometry::IntegerRectangle2D
;
99 using ::css::io::XOutputStream
;
100 using ::sax_fastparser::FSHelperPtr
;
101 using ::sax_fastparser::FastSerializerHelper
;
104 namespace drawingml
{
106 #define GETA(propName) \
107 GetProperty( rXPropSet, OUString( #propName ) )
109 #define GETAD(propName) \
110 ( GetPropertyAndState( rXPropSet, rXPropState, OUString( #propName ), eState ) && eState == beans::PropertyState_DIRECT_VALUE )
112 #define GET(variable, propName) \
113 if ( GETA(propName) ) \
116 #define CGETAD(propName) \
117 (( bCheckDirect && GetPropertyAndState( rXPropSet, rXPropState, OUString( #propName ), eState ) && eState == beans::PropertyState_DIRECT_VALUE )||GetProperty( rXPropSet, OUString( #propName ) ))
120 int DrawingML::mnImageCounter
= 1;
121 int DrawingML::mnWdpImageCounter
= 1;
122 std::map
<OUString
, OUString
> DrawingML::maWdpCache
;
124 void DrawingML::ResetCounters()
127 mnWdpImageCounter
= 1;
131 bool DrawingML::GetProperty( Reference
< XPropertySet
> rXPropertySet
, const OUString
& aName
)
135 mAny
= rXPropertySet
->getPropertyValue(aName
);
139 catch( const Exception
& )
141 /* printf ("exception when trying to get value of property: %s\n", USS(aName)); */
146 bool DrawingML::GetPropertyAndState( Reference
< XPropertySet
> rXPropertySet
, Reference
< XPropertyState
> rXPropertyState
, const OUString
& aName
, PropertyState
& eState
)
150 mAny
= rXPropertySet
->getPropertyValue(aName
);
153 eState
= rXPropertyState
->getPropertyState(aName
);
157 catch( const Exception
& )
159 /* printf ("exception when trying to get value of property: %s\n", USS(aName)); */
164 void DrawingML::WriteColor( sal_uInt32 nColor
, sal_Int32 nAlpha
)
166 // Transparency is a separate element.
167 OString sColor
= OString::number( nColor
& 0x00FFFFFF, 16 );
168 if( sColor
.getLength() < 6 )
170 OStringBuffer
sBuf( "0" );
171 int remains
= 5 - sColor
.getLength();
179 sBuf
.append( sColor
);
181 sColor
= sBuf
.getStr();
183 if( nAlpha
< MAX_PERCENT
)
185 mpFS
->startElementNS( XML_a
, XML_srgbClr
, XML_val
, sColor
.getStr(), FSEND
);
186 mpFS
->singleElementNS( XML_a
, XML_alpha
, XML_val
, OString::number(nAlpha
), FSEND
);
187 mpFS
->endElementNS( XML_a
, XML_srgbClr
);
192 mpFS
->singleElementNS( XML_a
, XML_srgbClr
, XML_val
, sColor
.getStr(), FSEND
);
196 void DrawingML::WriteColor( const OUString
& sColorSchemeName
, const Sequence
< PropertyValue
>& aTransformations
)
198 // prevent writing a tag with empty val attribute
199 if( sColorSchemeName
.isEmpty() )
202 if( aTransformations
.hasElements() )
204 mpFS
->startElementNS( XML_a
, XML_schemeClr
,
205 XML_val
, USS( sColorSchemeName
),
207 WriteColorTransformations( aTransformations
);
208 mpFS
->endElementNS( XML_a
, XML_schemeClr
);
212 mpFS
->singleElementNS( XML_a
, XML_schemeClr
,
213 XML_val
, USS( sColorSchemeName
),
218 void DrawingML::WriteColorTransformations( const Sequence
< PropertyValue
>& aTransformations
)
220 for( sal_Int32 i
= 0; i
< aTransformations
.getLength(); i
++ )
222 sal_Int32 nToken
= Color::getColorTransformationToken( aTransformations
[i
].Name
);
223 if( nToken
!= XML_TOKEN_INVALID
&& aTransformations
[i
].Value
.hasValue() )
225 sal_Int32 nValue
= aTransformations
[i
].Value
.get
<sal_Int32
>();
226 mpFS
->singleElementNS( XML_a
, nToken
, XML_val
, I32S( nValue
), FSEND
);
231 void DrawingML::WriteSolidFill( sal_uInt32 nColor
, sal_Int32 nAlpha
)
233 mpFS
->startElementNS( XML_a
, XML_solidFill
, FSEND
);
234 WriteColor( nColor
, nAlpha
);
235 mpFS
->endElementNS( XML_a
, XML_solidFill
);
238 void DrawingML::WriteSolidFill( const OUString
& sSchemeName
, const Sequence
< PropertyValue
>& aTransformations
)
240 mpFS
->startElementNS( XML_a
, XML_solidFill
, FSEND
);
241 WriteColor( sSchemeName
, aTransformations
);
242 mpFS
->endElementNS( XML_a
, XML_solidFill
);
245 void DrawingML::WriteSolidFill( Reference
< XPropertySet
> rXPropSet
)
248 if ( !GetProperty( rXPropSet
, "FillColor" ) )
250 sal_uInt32 nFillColor
= mAny
.get
<sal_uInt32
>();
252 // get InteropGrabBag and search the relevant attributes
253 OUString sColorFillScheme
;
254 sal_uInt32 nOriginalColor
= 0;
255 Sequence
< PropertyValue
> aStyleProperties
, aTransformations
;
256 if ( GetProperty( rXPropSet
, "InteropGrabBag" ) )
258 Sequence
< PropertyValue
> aGrabBag
;
260 for( sal_Int32 i
=0; i
< aGrabBag
.getLength(); ++i
)
262 if( aGrabBag
[i
].Name
== "SpPrSolidFillSchemeClr" )
263 aGrabBag
[i
].Value
>>= sColorFillScheme
;
264 else if( aGrabBag
[i
].Name
== "OriginalSolidFillClr" )
265 aGrabBag
[i
].Value
>>= nOriginalColor
;
266 else if( aGrabBag
[i
].Name
== "StyleFillRef" )
267 aGrabBag
[i
].Value
>>= aStyleProperties
;
268 else if( aGrabBag
[i
].Name
== "SpPrSolidFillSchemeClrTransformations" )
269 aGrabBag
[i
].Value
>>= aTransformations
;
273 sal_Int32 nAlpha
= MAX_PERCENT
;
274 if( GetProperty( rXPropSet
, "FillTransparence" ) )
276 sal_Int32 nTransparency
= 0;
277 mAny
>>= nTransparency
;
278 // Calculate alpha value (see oox/source/drawingml/color.cxx : getTransparency())
279 nAlpha
= (MAX_PERCENT
- ( PER_PERCENT
* nTransparency
) );
283 if ( nFillColor
!= nOriginalColor
)
285 // the user has set a different color for the shape
286 WriteSolidFill( nFillColor
& 0xffffff, nAlpha
);
288 else if ( !sColorFillScheme
.isEmpty() )
290 // the shape had a scheme color and the user didn't change it
291 WriteSolidFill( sColorFillScheme
, aTransformations
);
293 else if ( aStyleProperties
.hasElements() )
295 sal_uInt32 nThemeColor
= 0;
296 for( sal_Int32 i
=0; i
< aStyleProperties
.getLength(); ++i
)
298 if( aStyleProperties
[i
].Name
== "Color" )
300 aStyleProperties
[i
].Value
>>= nThemeColor
;
304 if ( nFillColor
!= nThemeColor
)
305 // the shape contains a theme but it wasn't being used
306 WriteSolidFill( nFillColor
& 0xffffff, nAlpha
);
307 // in case the shape used the style color and the user didn't change it,
308 // we must not write a <a: solidFill> tag.
312 // the shape had a custom color and the user didn't change it
313 WriteSolidFill( nFillColor
& 0xffffff, nAlpha
);
317 void DrawingML::WriteGradientStop( sal_uInt16 nStop
, sal_uInt32 nColor
)
319 mpFS
->startElementNS( XML_a
, XML_gs
,
320 XML_pos
, I32S( nStop
* 1000 ),
322 WriteColor( nColor
);
323 mpFS
->endElementNS( XML_a
, XML_gs
);
326 sal_uInt32
DrawingML::ColorWithIntensity( sal_uInt32 nColor
, sal_uInt32 nIntensity
)
328 return ( ( ( nColor
& 0xff ) * nIntensity
) / 100 )
329 | ( ( ( ( ( nColor
& 0xff00 ) >> 8 ) * nIntensity
) / 100 ) << 8 )
330 | ( ( ( ( ( nColor
& 0xff0000 ) >> 8 ) * nIntensity
) / 100 ) << 8 );
333 bool DrawingML::EqualGradients( awt::Gradient aGradient1
, awt::Gradient aGradient2
)
335 return aGradient1
.Style
== aGradient2
.Style
&&
336 aGradient1
.StartColor
== aGradient2
.StartColor
&&
337 aGradient1
.EndColor
== aGradient2
.EndColor
&&
338 aGradient1
.Angle
== aGradient2
.Angle
&&
339 aGradient1
.Border
== aGradient2
.Border
&&
340 aGradient1
.XOffset
== aGradient2
.XOffset
&&
341 aGradient1
.YOffset
== aGradient2
.YOffset
&&
342 aGradient1
.StartIntensity
== aGradient2
.StartIntensity
&&
343 aGradient1
.EndIntensity
== aGradient2
.EndIntensity
&&
344 aGradient1
.StepCount
== aGradient2
.StepCount
;
347 void DrawingML::WriteGradientFill( Reference
< XPropertySet
> rXPropSet
)
349 awt::Gradient aGradient
;
350 if( GETA( FillGradient
) )
352 aGradient
= *static_cast< const awt::Gradient
* >( mAny
.getValue() );
354 // get InteropGrabBag and search the relevant attributes
355 awt::Gradient aOriginalGradient
;
356 Sequence
< PropertyValue
> aGradientStops
;
357 if ( GetProperty( rXPropSet
, "InteropGrabBag" ) )
359 Sequence
< PropertyValue
> aGrabBag
;
361 for( sal_Int32 i
=0; i
< aGrabBag
.getLength(); ++i
)
362 if( aGrabBag
[i
].Name
== "GradFillDefinition" )
363 aGrabBag
[i
].Value
>>= aGradientStops
;
364 else if( aGrabBag
[i
].Name
== "OriginalGradFill" )
365 aGrabBag
[i
].Value
>>= aOriginalGradient
;
368 // check if an ooxml gradient had been imported and if the user has modified it
369 if( EqualGradients( aOriginalGradient
, aGradient
) )
371 // If we have no gradient stops that means original gradient were defined by a theme.
372 if( aGradientStops
.hasElements() )
374 mpFS
->startElementNS( XML_a
, XML_gradFill
, FSEND
);
375 WriteGrabBagGradientFill(aGradientStops
, aGradient
);
376 mpFS
->endElementNS( XML_a
, XML_gradFill
);
381 mpFS
->startElementNS( XML_a
, XML_gradFill
, FSEND
);
382 WriteGradientFill(aGradient
);
383 mpFS
->endElementNS( XML_a
, XML_gradFill
);
388 void DrawingML::WriteGrabBagGradientFill( const Sequence
< PropertyValue
>& aGradientStops
, awt::Gradient rGradient
)
390 // write back the original gradient
391 mpFS
->startElementNS( XML_a
, XML_gsLst
, FSEND
);
393 // get original stops and write them
394 for( sal_Int32 i
=0; i
< aGradientStops
.getLength(); ++i
)
396 Sequence
< PropertyValue
> aGradientStop
;
397 aGradientStops
[i
].Value
>>= aGradientStop
;
402 sal_Int16 nTransparency
= 0;
403 sal_Int32 nRgbClr
= 0;
404 Sequence
< PropertyValue
> aTransformations
;
405 for( sal_Int32 j
=0; j
< aGradientStop
.getLength(); ++j
)
407 if( aGradientStop
[j
].Name
== "SchemeClr" )
408 aGradientStop
[j
].Value
>>= sSchemeClr
;
409 else if( aGradientStop
[j
].Name
== "RgbClr" )
410 aGradientStop
[j
].Value
>>= nRgbClr
;
411 else if( aGradientStop
[j
].Name
== "Pos" )
412 aGradientStop
[j
].Value
>>= nPos
;
413 else if( aGradientStop
[j
].Name
== "Transparency" )
414 aGradientStop
[j
].Value
>>= nTransparency
;
415 else if( aGradientStop
[j
].Name
== "Transformations" )
416 aGradientStop
[j
].Value
>>= aTransformations
;
419 mpFS
->startElementNS( XML_a
, XML_gs
,
420 XML_pos
, OString::number( nPos
* 100000.0 ).getStr(),
422 if( sSchemeClr
.isEmpty() )
424 // Calculate alpha value (see oox/source/drawingml/color.cxx : getTransparency())
425 sal_Int32 nAlpha
= (MAX_PERCENT
- ( PER_PERCENT
* nTransparency
) );
426 WriteColor( nRgbClr
, nAlpha
);
430 WriteColor( sSchemeClr
, aTransformations
);
432 mpFS
->endElementNS( XML_a
, XML_gs
);
434 mpFS
->endElementNS( XML_a
, XML_gsLst
);
436 mpFS
->singleElementNS( XML_a
, XML_lin
,
437 XML_ang
, I32S( ( ( ( 3600 - rGradient
.Angle
+ 900 ) * 6000 ) % 21600000 ) ),
441 void DrawingML::WriteGradientFill( awt::Gradient rGradient
)
443 switch( rGradient
.Style
)
446 case GradientStyle_LINEAR
:
447 mpFS
->startElementNS( XML_a
, XML_gsLst
, FSEND
);
448 WriteGradientStop( 0, ColorWithIntensity( rGradient
.StartColor
, rGradient
.StartIntensity
) );
449 WriteGradientStop( 100, ColorWithIntensity( rGradient
.EndColor
, rGradient
.EndIntensity
) );
450 mpFS
->endElementNS( XML_a
, XML_gsLst
);
451 mpFS
->singleElementNS( XML_a
, XML_lin
,
452 XML_ang
, I32S( ( ( ( 3600 - rGradient
.Angle
+ 900 ) * 6000 ) % 21600000 ) ),
456 case GradientStyle_AXIAL
:
457 mpFS
->startElementNS( XML_a
, XML_gsLst
, FSEND
);
458 WriteGradientStop( 0, ColorWithIntensity( rGradient
.EndColor
, rGradient
.EndIntensity
) );
459 WriteGradientStop( 50, ColorWithIntensity( rGradient
.StartColor
, rGradient
.StartIntensity
) );
460 WriteGradientStop( 100, ColorWithIntensity( rGradient
.EndColor
, rGradient
.EndIntensity
) );
461 mpFS
->endElementNS( XML_a
, XML_gsLst
);
462 mpFS
->singleElementNS( XML_a
, XML_lin
,
463 XML_ang
, I32S( ( ( ( 3600 - rGradient
.Angle
+ 900 ) * 6000 ) % 21600000 ) ),
467 /* I don't see how to apply transformation to gradients, so
468 * elliptical will end as radial and square as
469 * rectangular. also position offsets are not applied */
470 case GradientStyle_RADIAL
:
471 case GradientStyle_ELLIPTICAL
:
472 case GradientStyle_RECT
:
473 case GradientStyle_SQUARE
:
474 mpFS
->startElementNS( XML_a
, XML_gsLst
, FSEND
);
475 WriteGradientStop( 0, ColorWithIntensity( rGradient
.EndColor
, rGradient
.EndIntensity
) );
476 WriteGradientStop( 100, ColorWithIntensity( rGradient
.StartColor
, rGradient
.StartIntensity
) );
477 mpFS
->endElementNS( XML_a
, XML_gsLst
);
478 mpFS
->singleElementNS( XML_a
, XML_path
,
479 XML_path
, ( rGradient
.Style
== awt::GradientStyle_RADIAL
|| rGradient
.Style
== awt::GradientStyle_ELLIPTICAL
) ? "circle" : "rect",
485 void DrawingML::WriteLineArrow( Reference
< XPropertySet
> rXPropSet
, bool bLineStart
)
487 ESCHER_LineEnd eLineEnd
;
488 sal_Int32 nArrowLength
;
489 sal_Int32 nArrowWidth
;
491 if ( EscherPropertyContainer::GetLineArrow( bLineStart
, rXPropSet
, eLineEnd
, nArrowLength
, nArrowWidth
) )
497 switch( nArrowLength
)
499 case ESCHER_LineShortArrow
:
503 case ESCHER_LineMediumLenArrow
:
506 case ESCHER_LineLongArrow
:
514 case ESCHER_LineNoEnd
:
517 case ESCHER_LineArrowEnd
:
520 case ESCHER_LineArrowStealthEnd
:
523 case ESCHER_LineArrowDiamondEnd
:
526 case ESCHER_LineArrowOvalEnd
:
529 case ESCHER_LineArrowOpenEnd
:
534 switch( nArrowWidth
)
536 case ESCHER_LineNarrowArrow
:
540 case ESCHER_LineMediumWidthArrow
:
543 case ESCHER_LineWideArrow
:
548 mpFS
->singleElementNS( XML_a
, bLineStart
? XML_headEnd
: XML_tailEnd
,
556 void DrawingML::WriteOutline( Reference
<XPropertySet
> rXPropSet
)
558 drawing::LineStyle
aLineStyle( drawing::LineStyle_NONE
);
560 GET( aLineStyle
, LineStyle
);
562 sal_uInt32 nLineWidth
= 0;
563 sal_uInt32 nColor
= 0;
564 bool bColorSet
= false;
565 const char* cap
= NULL
;
566 drawing::LineDash aLineDash
;
567 bool bDashSet
= false;
568 bool bNoFill
= false;
570 // get InteropGrabBag and search the relevant attributes
571 OUString sColorFillScheme
;
573 sal_uInt32 nOriginalColor
= 0;
574 sal_uInt32 nStyleColor
= 0;
575 sal_uInt32 nStyleLineWidth
= 0;
577 Sequence
<PropertyValue
> aStyleProperties
;
578 Sequence
<PropertyValue
> aTransformations
;
580 drawing::LineStyle
aStyleLineStyle(drawing::LineStyle_NONE
);
581 drawing::LineJoint
aStyleLineJoint(drawing::LineJoint_NONE
);
583 if (GetProperty(rXPropSet
, "InteropGrabBag"))
585 Sequence
<PropertyValue
> aGrabBag
;
588 for (sal_Int32 i
=0; i
< aGrabBag
.getLength(); ++i
)
590 if( aGrabBag
[i
].Name
== "SpPrLnSolidFillSchemeClr" )
591 aGrabBag
[i
].Value
>>= sColorFillScheme
;
592 else if( aGrabBag
[i
].Name
== "OriginalLnSolidFillClr" )
593 aGrabBag
[i
].Value
>>= nOriginalColor
;
594 else if( aGrabBag
[i
].Name
== "StyleLnRef" )
595 aGrabBag
[i
].Value
>>= aStyleProperties
;
596 else if( aGrabBag
[i
].Name
== "SpPrLnSolidFillSchemeClrTransformations" )
597 aGrabBag
[i
].Value
>>= aTransformations
;
599 if (aStyleProperties
.hasElements())
601 for (sal_Int32 i
=0; i
< aStyleProperties
.getLength(); ++i
)
603 if( aStyleProperties
[i
].Name
== "Color" )
604 aStyleProperties
[i
].Value
>>= nStyleColor
;
605 else if( aStyleProperties
[i
].Name
== "LineStyle" )
606 aStyleProperties
[i
].Value
>>= aStyleLineStyle
;
607 else if( aStyleProperties
[i
].Name
== "LineJoint" )
608 aStyleProperties
[i
].Value
>>= aStyleLineJoint
;
609 else if( aStyleProperties
[i
].Name
== "LineWidth" )
610 aStyleProperties
[i
].Value
>>= nStyleLineWidth
;
615 GET( nLineWidth
, LineWidth
);
619 case drawing::LineStyle_NONE
:
622 case drawing::LineStyle_DASH
:
623 if (GetProperty(rXPropSet
, "LineDash"))
625 aLineDash
= mAny
.get
<drawing::LineDash
>();
627 if (aLineDash
.Style
== DashStyle_ROUND
|| aLineDash
.Style
== DashStyle_ROUNDRELATIVE
)
632 DBG(fprintf(stderr
, "dash dots: %d dashes: %d dotlen: %d dashlen: %d distance: %d\n",
633 int( aLineDash
.Dots
), int( aLineDash
.Dashes
), int( aLineDash
.DotLen
), int( aLineDash
.DashLen
), int( aLineDash
.Distance
)));
635 /* fallthru intended */
636 case drawing::LineStyle_SOLID
:
638 if ( GETA( LineColor
) )
640 nColor
= mAny
.get
<sal_uInt32
>() & 0xffffff;
646 mpFS
->startElementNS( XML_a
, XML_ln
,
648 XML_w
, nLineWidth
> 1 && nStyleLineWidth
!= nLineWidth
?
649 I64S( oox::drawingml::convertHmmToEmu( nLineWidth
) ) :NULL
,
654 if( nColor
!= nOriginalColor
)
656 // the user has set a different color for the line
657 WriteSolidFill( nColor
);
659 else if( !sColorFillScheme
.isEmpty() )
661 // the line had a scheme color and the user didn't change it
662 WriteSolidFill( sColorFillScheme
, aTransformations
);
664 else if( aStyleProperties
.hasElements() )
666 if( nColor
!= nStyleColor
)
667 // the line style defines some color but it wasn't being used
668 WriteSolidFill( nColor
);
669 // in case the shape used the style color and the user didn't change it,
670 // we must not write a <a: solidFill> tag.
674 WriteSolidFill( nColor
);
678 if( bDashSet
&& aStyleLineStyle
!= drawing::LineStyle_DASH
)
680 // line style is a dash and it was not set by the shape style
682 if (aLineDash
.Dashes
== 1 && aLineDash
.DashLen
== 564 && aLineDash
.Distance
== 423)
684 // That's exactly the predefined "dash" value.
685 mpFS
->singleElementNS(XML_a
, XML_prstDash
,
691 mpFS
->startElementNS( XML_a
, XML_custDash
, FSEND
);
693 // Check that line-width is positive and distance between dashes\dots is positive
694 if ( nLineWidth
> 0 && aLineDash
.Distance
> 0 )
696 // Write 'dashes' first, and then 'dots'
698 if ( aLineDash
.Dashes
> 0 )
700 for( i
= 0; i
< aLineDash
.Dashes
; i
++ )
702 mpFS
->singleElementNS( XML_a
, XML_ds
,
703 XML_d
, write1000thOfAPercent( aLineDash
.DashLen
> 0 ? aLineDash
.DashLen
/ nLineWidth
* 100 : 100 ),
704 XML_sp
, write1000thOfAPercent( aLineDash
.Distance
> 0 ? aLineDash
.Distance
/ nLineWidth
* 100 : 100 ),
708 if ( aLineDash
.Dots
> 0 )
710 for( i
= 0; i
< aLineDash
.Dots
; i
++ )
712 mpFS
->singleElementNS( XML_a
, XML_ds
,
713 XML_d
, write1000thOfAPercent( aLineDash
.DotLen
> 0 ? aLineDash
.DotLen
/ nLineWidth
* 100 : 100 ),
714 XML_sp
, write1000thOfAPercent( aLineDash
.Distance
> 0 ? aLineDash
.Distance
/ nLineWidth
* 100 : 100 ),
720 SAL_WARN_IF(nLineWidth
<= 0,
721 "oox", "while writing outline - custom dash - line width was < 0 : " << nLineWidth
);
722 SAL_WARN_IF(aLineDash
.Dashes
< 0,
723 "oox", "while writing outline - custom dash - number of dashes was < 0 : " << aLineDash
.Dashes
);
724 SAL_WARN_IF(aLineDash
.Dashes
> 0 && aLineDash
.DashLen
<= 0,
725 "oox", "while writing outline - custom dash - dash length was < 0 : " << aLineDash
.DashLen
);
726 SAL_WARN_IF(aLineDash
.Dots
< 0,
727 "oox", "while writing outline - custom dash - number of dots was < 0 : " << aLineDash
.Dots
);
728 SAL_WARN_IF(aLineDash
.Dots
> 0 && aLineDash
.DotLen
<= 0,
729 "oox", "while writing outline - custom dash - dot length was < 0 : " << aLineDash
.DotLen
);
730 SAL_WARN_IF(aLineDash
.Distance
<= 0,
731 "oox", "while writing outline - custom dash - distance was < 0 : " << aLineDash
.Distance
);
733 mpFS
->endElementNS( XML_a
, XML_custDash
);
737 if( !bNoFill
&& nLineWidth
> 1 && GETA( LineJoint
) )
739 LineJoint eLineJoint
= mAny
.get
<LineJoint
>();
741 if( aStyleLineJoint
== LineJoint_NONE
|| aStyleLineJoint
!= eLineJoint
)
743 // style-defined line joint does not exist, or is different from the shape's joint
747 case LineJoint_MIDDLE
:
748 case LineJoint_BEVEL
:
749 mpFS
->singleElementNS( XML_a
, XML_bevel
, FSEND
);
752 case LineJoint_MITER
:
753 mpFS
->singleElementNS( XML_a
, XML_miter
, FSEND
);
755 case LineJoint_ROUND
:
756 mpFS
->singleElementNS( XML_a
, XML_round
, FSEND
);
764 WriteLineArrow( rXPropSet
, true );
765 WriteLineArrow( rXPropSet
, false );
769 mpFS
->singleElementNS( XML_a
, XML_noFill
, FSEND
);
772 mpFS
->endElementNS( XML_a
, XML_ln
);
775 bool lcl_URLToGraphic(const OUString
& rURL
, Graphic
& rGraphic
)
777 OString
aURLBS(OUStringToOString(rURL
, RTL_TEXTENCODING_UTF8
));
779 const char aURLBegin
[] = "vnd.sun.star.GraphicObject:";
780 sal_Int32 index
= aURLBS
.indexOf(aURLBegin
);
784 rGraphic
= GraphicObject(aURLBS
.copy(RTL_CONSTASCII_LENGTH(aURLBegin
))).GetTransformedGraphic();
791 OUString
DrawingML::WriteImage( const OUString
& rURL
, bool bRelPathToMedia
)
794 if (lcl_URLToGraphic(rURL
, aGraphic
))
796 return WriteImage( aGraphic
, bRelPathToMedia
);
800 // add link to relations
806 const char* DrawingML::GetComponentDir()
808 switch ( meDocumentType
)
810 case DOCUMENT_DOCX
: return "word";
811 case DOCUMENT_PPTX
: return "ppt";
812 case DOCUMENT_XLSX
: return "xl";
818 const char* DrawingML::GetRelationCompPrefix()
820 switch ( meDocumentType
)
822 case DOCUMENT_DOCX
: return "";
824 case DOCUMENT_XLSX
: return "../";
830 OUString
DrawingML::WriteImage( const Graphic
& rGraphic
, bool bRelPathToMedia
)
832 GfxLink aLink
= rGraphic
.GetLink ();
834 const char* pExtension
= "";
837 SvMemoryStream aStream
;
838 const void* aData
= aLink
.GetData();
839 sal_Size nDataSize
= aLink
.GetDataSize();
841 switch ( aLink
.GetType() )
843 case GFX_LINK_TYPE_NATIVE_GIF
:
844 sMediaType
= "image/gif";
848 // #i15508# added BMP type for better exports
849 // export not yet active, so adding for reference (not checked)
850 case GFX_LINK_TYPE_NATIVE_BMP
:
851 sMediaType
= "image/bmp";
855 case GFX_LINK_TYPE_NATIVE_JPG
:
856 sMediaType
= "image/jpeg";
857 pExtension
= ".jpeg";
859 case GFX_LINK_TYPE_NATIVE_PNG
:
860 sMediaType
= "image/png";
863 case GFX_LINK_TYPE_NATIVE_TIF
:
864 sMediaType
= "image/tiff";
867 case GFX_LINK_TYPE_NATIVE_WMF
:
868 sMediaType
= "image/x-wmf";
871 case GFX_LINK_TYPE_NATIVE_MET
:
872 sMediaType
= "image/x-met";
875 case GFX_LINK_TYPE_NATIVE_PCT
:
876 sMediaType
= "image/x-pict";
879 case GFX_LINK_TYPE_NATIVE_MOV
:
880 sMediaType
= "application/movie";
885 GraphicType aType
= rGraphic
.GetType();
886 if ( aType
== GRAPHIC_BITMAP
|| aType
== GRAPHIC_GDIMETAFILE
)
888 if ( aType
== GRAPHIC_BITMAP
)
890 (void)GraphicConverter::Export( aStream
, rGraphic
, CVT_PNG
);
891 sMediaType
= "image/png";
896 (void)GraphicConverter::Export( aStream
, rGraphic
, CVT_EMF
);
897 sMediaType
= "image/x-emf";
903 OSL_TRACE( "unhandled graphic type" );
904 /*Earlier, even in case of unhandled graphic types we were
905 proceeding to write the image, which would eventually
906 write an empty image with a zero size, and return a valid
907 relationID, which is incorrect.
912 aData
= aStream
.GetData();
913 nDataSize
= aStream
.GetEndOfData();
918 Reference
< XOutputStream
> xOutStream
= mpFB
->openFragmentStream( OUStringBuffer()
919 .appendAscii( GetComponentDir() )
920 .appendAscii( "/media/image" )
921 .append( (sal_Int32
) mnImageCounter
)
922 .appendAscii( pExtension
)
923 .makeStringAndClear(),
925 xOutStream
->writeBytes( Sequence
< sal_Int8
>( static_cast<const sal_Int8
*>(aData
), nDataSize
) );
926 xOutStream
->closeOutput();
928 OString sRelPathToMedia
= "media/image";
929 if ( bRelPathToMedia
)
930 sRelPathToMedia
= "../" + sRelPathToMedia
;
931 sRelId
= mpFB
->addRelation( mpFS
->getOutputStream(),
932 "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",
934 .appendAscii( GetRelationCompPrefix() )
935 .appendAscii( sRelPathToMedia
.getStr() )
936 .append( (sal_Int32
) mnImageCounter
++ )
937 .appendAscii( pExtension
)
938 .makeStringAndClear() );
943 OUString
DrawingML::WriteBlip( Reference
< XPropertySet
> rXPropSet
, const OUString
& rURL
, bool bRelPathToMedia
, const Graphic
*pGraphic
)
946 BitmapChecksum nChecksum
= 0;
947 if (!rURL
.isEmpty() && mpTextExport
)
950 if (lcl_URLToGraphic(rURL
, aGraphic
))
952 nChecksum
= aGraphic
.GetChecksum();
953 sRelId
= mpTextExport
->FindRelId(nChecksum
);
956 if (sRelId
.isEmpty())
958 sRelId
= pGraphic
? WriteImage( *pGraphic
, bRelPathToMedia
) : WriteImage( rURL
, bRelPathToMedia
);
959 if (!rURL
.isEmpty() && mpTextExport
)
960 mpTextExport
->CacheRelId(nChecksum
, sRelId
);
962 sal_Int16 nBright
= 0;
963 sal_Int32 nContrast
= 0;
965 GET( nBright
, AdjustLuminance
);
966 GET( nContrast
, AdjustContrast
);
968 mpFS
->startElementNS( XML_a
, XML_blip
,
969 FSNS( XML_r
, XML_embed
), sRelId
.toUtf8().getStr(),
971 if( nBright
|| nContrast
)
973 mpFS
->singleElementNS( XML_a
, XML_lum
,
974 XML_bright
, nBright
? I32S( nBright
*1000 ) : NULL
,
975 XML_contrast
, nContrast
? I32S( nContrast
*1000 ) : NULL
,
978 WriteArtisticEffect( rXPropSet
);
980 mpFS
->endElementNS( XML_a
, XML_blip
);
985 void DrawingML::WriteBlipMode( Reference
< XPropertySet
> rXPropSet
, const OUString
& rURL
)
987 BitmapMode
eBitmapMode( BitmapMode_NO_REPEAT
);
988 if (GetProperty( rXPropSet
, "FillBitmapMode" ) )
989 mAny
>>= eBitmapMode
;
991 DBG(fprintf(stderr
, "fill bitmap mode: %d\n", eBitmapMode
));
995 case BitmapMode_REPEAT
:
996 mpFS
->singleElementNS( XML_a
, XML_tile
, FSEND
);
998 case BitmapMode_STRETCH
:
999 WriteStretch( rXPropSet
, rURL
);
1006 void DrawingML::WriteBlipOrNormalFill( Reference
< XPropertySet
> xPropSet
, const OUString
& rURLPropName
)
1008 // check for blip and otherwise fall back to normal fill
1009 // we always store normal fill properties but OOXML
1010 // uses a choice between our fill props and BlipFill
1011 if (GetProperty ( xPropSet
, rURLPropName
))
1012 WriteBlipFill( xPropSet
, rURLPropName
);
1014 WriteFill(xPropSet
);
1017 void DrawingML::WriteBlipFill( Reference
< XPropertySet
> rXPropSet
, const OUString
& sURLPropName
)
1019 WriteBlipFill( rXPropSet
, sURLPropName
, XML_a
);
1022 void DrawingML::WriteBlipFill( Reference
< XPropertySet
> rXPropSet
, const OUString
& sURLPropName
, sal_Int32 nXmlNamespace
)
1024 if ( GetProperty( rXPropSet
, sURLPropName
) )
1028 bool bWriteMode
= false;
1029 if( sURLPropName
== "FillBitmapURL" || sURLPropName
== "BackGraphicURL")
1031 WriteBlipFill( rXPropSet
, aURL
, nXmlNamespace
, bWriteMode
);
1035 void DrawingML::WriteBlipFill( Reference
< XPropertySet
> rXPropSet
, const OUString
& sBitmapURL
, sal_Int32 nXmlNamespace
, bool bWriteMode
, bool bRelPathToMedia
)
1037 if ( !sBitmapURL
.isEmpty() )
1039 DBG(fprintf (stderr
, "URL: %s\n", OUStringToOString( sBitmapURL
, RTL_TEXTENCODING_UTF8
).getStr() ));
1041 mpFS
->startElementNS( nXmlNamespace
, XML_blipFill
, FSEND
);
1043 WriteBlip( rXPropSet
, sBitmapURL
, bRelPathToMedia
);
1047 WriteBlipMode( rXPropSet
, sBitmapURL
);
1049 else if( GetProperty( rXPropSet
, "FillBitmapStretch" ) )
1051 bool bStretch
= false;
1055 WriteStretch( rXPropSet
, sBitmapURL
);
1057 mpFS
->endElementNS( nXmlNamespace
, XML_blipFill
);
1061 void DrawingML::WritePattFill( Reference
< XPropertySet
> rXPropSet
)
1063 if ( GetProperty( rXPropSet
, "FillHatch" ) )
1065 drawing::Hatch aHatch
;
1068 mpFS
->startElementNS( XML_a
, XML_pattFill
, XML_prst
, GetHatchPattern(aHatch
), FSEND
);
1070 mpFS
->startElementNS( XML_a
, XML_fgClr
, FSEND
);
1071 WriteColor(aHatch
.Color
);
1072 mpFS
->endElementNS( XML_a
, XML_fgClr
);
1074 // In Writer hatching has no background so use white as a default value.
1075 mpFS
->startElementNS( XML_a
, XML_bgClr
, FSEND
);
1076 WriteColor(COL_WHITE
);
1077 mpFS
->endElementNS( XML_a
, XML_bgClr
);
1079 mpFS
->endElementNS( XML_a
, XML_pattFill
);
1083 void DrawingML::WriteSrcRect( Reference
< XPropertySet
> rXPropSet
, const OUString
& rURL
)
1085 GraphicObject aGraphicObject
= GraphicObject::CreateGraphicObjectFromURL(rURL
);
1086 Size aOriginalSize
= aGraphicObject
.GetPrefSize();
1087 const MapMode
& rMapMode
= aGraphicObject
.GetPrefMapMode();
1089 // GraphicCrop is in mm100, so in case the original size is in pixels, convert it over.
1090 if (rMapMode
.GetMapUnit() == MAP_PIXEL
)
1091 aOriginalSize
= Application::GetDefaultDevice()->PixelToLogic(aOriginalSize
, MapMode(MAP_100TH_MM
));
1093 if ( GetProperty( rXPropSet
, "GraphicCrop" ) )
1095 ::com::sun::star::text::GraphicCrop aGraphicCropStruct
;
1096 mAny
>>= aGraphicCropStruct
;
1098 if ( (0 != aGraphicCropStruct
.Left
) || (0 != aGraphicCropStruct
.Top
) || (0 != aGraphicCropStruct
.Right
) || (0 != aGraphicCropStruct
.Bottom
) )
1100 mpFS
->singleElementNS( XML_a
, XML_srcRect
,
1101 XML_l
, I32S(rtl::math::round(static_cast<double>(aGraphicCropStruct
.Left
) * 100000 / aOriginalSize
.Width())),
1102 XML_t
, I32S(rtl::math::round(static_cast<double>(aGraphicCropStruct
.Top
) * 100000 / aOriginalSize
.Height())),
1103 XML_r
, I32S(rtl::math::round(static_cast<double>(aGraphicCropStruct
.Right
) * 100000 / aOriginalSize
.Width())),
1104 XML_b
, I32S(rtl::math::round(static_cast<double>(aGraphicCropStruct
.Bottom
) * 100000 / aOriginalSize
.Height())),
1110 void DrawingML::WriteStretch( ::com::sun::star::uno::Reference
< ::com::sun::star::beans::XPropertySet
> rXPropSet
, const OUString
& rURL
)
1112 mpFS
->startElementNS( XML_a
, XML_stretch
, FSEND
);
1115 if ( GetProperty( rXPropSet
, "GraphicCrop" ) )
1117 ::com::sun::star::text::GraphicCrop aGraphicCropStruct
;
1118 mAny
>>= aGraphicCropStruct
;
1120 if ( (0 != aGraphicCropStruct
.Left
) || (0 != aGraphicCropStruct
.Top
) || (0 != aGraphicCropStruct
.Right
) || (0 != aGraphicCropStruct
.Bottom
) )
1122 Size
aOriginalSize( GraphicObject::CreateGraphicObjectFromURL( rURL
).GetPrefSize() );
1123 mpFS
->singleElementNS( XML_a
, XML_fillRect
,
1124 XML_l
, I32S(((aGraphicCropStruct
.Left
) * 100000)/aOriginalSize
.Width()),
1125 XML_t
, I32S(((aGraphicCropStruct
.Top
) * 100000)/aOriginalSize
.Height()),
1126 XML_r
, I32S(((aGraphicCropStruct
.Right
) * 100000)/aOriginalSize
.Width()),
1127 XML_b
, I32S(((aGraphicCropStruct
.Bottom
) * 100000)/aOriginalSize
.Height()),
1135 mpFS
->singleElementNS( XML_a
, XML_fillRect
, FSEND
);
1138 mpFS
->endElementNS( XML_a
, XML_stretch
);
1141 void DrawingML::WriteTransformation( const Rectangle
& rRect
,
1142 sal_Int32 nXmlNamespace
, bool bFlipH
, bool bFlipV
, sal_Int32 nRotation
)
1144 mpFS
->startElementNS( nXmlNamespace
, XML_xfrm
,
1145 XML_flipH
, bFlipH
? "1" : NULL
,
1146 XML_flipV
, bFlipV
? "1" : NULL
,
1147 XML_rot
, (nRotation
% 21600000) ? I32S( nRotation
) : NULL
,
1150 sal_Int32 nLeft
= rRect
.Left();
1151 sal_Int32 nTop
= rRect
.Top();
1152 if (GetDocumentType() == DOCUMENT_DOCX
&& !m_xParent
.is())
1158 mpFS
->singleElementNS( XML_a
, XML_off
, XML_x
, IS( oox::drawingml::convertHmmToEmu( nLeft
) ), XML_y
, IS( oox::drawingml::convertHmmToEmu( nTop
) ), FSEND
);
1159 mpFS
->singleElementNS( XML_a
, XML_ext
, XML_cx
, IS( oox::drawingml::convertHmmToEmu( rRect
.GetWidth() ) ), XML_cy
, IS( oox::drawingml::convertHmmToEmu( rRect
.GetHeight() ) ), FSEND
);
1161 mpFS
->endElementNS( nXmlNamespace
, XML_xfrm
);
1164 void DrawingML::WriteShapeTransformation( Reference
< XShape
> rXShape
, sal_Int32 nXmlNamespace
, bool bFlipH
, bool bFlipV
, bool bSuppressRotation
)
1166 DBG(fprintf(stderr
, "write shape transformation\n" ));
1168 sal_Int32 nRotation
=0;
1169 awt::Point aPos
= rXShape
->getPosition();
1170 awt::Size aSize
= rXShape
->getSize();
1174 awt::Point aParentPos
= m_xParent
->getPosition();
1175 aPos
.X
-= aParentPos
.X
;
1176 aPos
.Y
-= aParentPos
.Y
;
1179 if ( aSize
.Width
< 0 )
1181 if ( aSize
.Height
< 0 )
1182 aSize
.Height
= 1000;
1183 if (!bSuppressRotation
)
1185 SdrObject
* pShape
= GetSdrObjectFromXShape( rXShape
);
1186 nRotation
= pShape
? pShape
->GetRotateAngle() : 0;
1187 if (nRotation
!= 0 && nRotation
!= 18000)
1189 int faccos
=bFlipV
? -1 : 1;
1190 int facsin
=bFlipH
? -1 : 1;
1191 aPos
.X
-=(1-faccos
*cos(nRotation
*F_PI18000
))*aSize
.Width
/2-facsin
*sin(nRotation
*F_PI18000
)*aSize
.Height
/2;
1192 aPos
.Y
-=(1-faccos
*cos(nRotation
*F_PI18000
))*aSize
.Height
/2+facsin
*sin(nRotation
*F_PI18000
)*aSize
.Width
/2;
1195 // The RotateAngle property's value is independent from any flipping, and that's exactly what we need here.
1196 uno::Reference
<beans::XPropertySet
> xPropertySet(rXShape
, uno::UNO_QUERY
);
1197 uno::Reference
<beans::XPropertySetInfo
> xPropertySetInfo
= xPropertySet
->getPropertySetInfo();
1198 if (xPropertySetInfo
->hasPropertyByName("RotateAngle"))
1199 xPropertySet
->getPropertyValue("RotateAngle") >>= nRotation
;
1201 WriteTransformation( Rectangle( Point( aPos
.X
, aPos
.Y
), Size( aSize
.Width
, aSize
.Height
) ), nXmlNamespace
, bFlipH
, bFlipV
, OOX_DRAWINGML_EXPORT_ROTATE_CLOCKWISIFY(nRotation
) );
1204 void DrawingML::WriteRunProperties( Reference
< XPropertySet
> rRun
, bool bIsField
, sal_Int32 nElement
/*= XML_rPr*/ )
1206 Reference
< XPropertySet
> rXPropSet( rRun
, UNO_QUERY
);
1207 Reference
< XPropertyState
> rXPropState( rRun
, UNO_QUERY
);
1208 OUString usLanguage
;
1209 PropertyState eState
;
1210 SvtScriptType nScriptType
= SvtLanguageOptions::GetScriptTypeOfLanguage( Application::GetSettings().GetLanguageTag().getLanguageType() );
1211 bool bComplex
= ( nScriptType
== SvtScriptType::COMPLEX
);
1212 const char* bold
= NULL
;
1213 const char* italic
= NULL
;
1214 const char* underline
= NULL
;
1215 const char* strikeout
= NULL
;
1216 const char* cap
= NULL
;
1217 sal_Int32 nSize
= 1800;
1218 sal_Int32 nCharEscapement
= 0;
1219 sal_Int32 nCharKerning
= 0;
1220 bool bCheckDirect
= XML_endParaRPr
!= nElement
;
1221 if( GETA( CharHeight
) )
1222 nSize
= (sal_Int32
) (100*(*static_cast<float const *>(mAny
.getValue())));
1224 if( GETA( CharKerning
) )
1225 nCharKerning
= (sal_Int32
)(*static_cast<short const *>(mAny
.getValue()));
1226 /** While setting values in propertymap,
1227 * CharKerning converted using GetTextSpacingPoint
1228 * i.e set @ http://opengrok.libreoffice.org/xref/core/oox/source/drawingml/textcharacterproperties.cxx#129
1229 * therefore to get original value CharKerning need to be convert.
1230 * http://opengrok.libreoffice.org/xref/core/oox/source/drawingml/drawingmltypes.cxx#95
1232 nCharKerning
= ((nCharKerning
* 720)-360) / 254;
1234 if ( ( bComplex
&& GETA( CharWeightComplex
) ) || GETA( CharWeight
) )
1236 if ( *static_cast<float const *>(mAny
.getValue()) >= awt::FontWeight::SEMIBOLD
)
1240 if ( ( bComplex
&& GETA( CharPostureComplex
) ) || GETA( CharPosture
) )
1241 switch ( *static_cast<awt::FontSlant
const *>(mAny
.getValue()) )
1243 case awt::FontSlant_OBLIQUE
:
1244 case awt::FontSlant_ITALIC
:
1251 if ( CGETAD( CharUnderline
) )
1253 switch ( *static_cast<sal_Int16
const *>(mAny
.getValue()) )
1255 case awt::FontUnderline::SINGLE
:
1258 case awt::FontUnderline::DOUBLE
:
1261 case awt::FontUnderline::DOTTED
:
1262 underline
= "dotted";
1264 case awt::FontUnderline::DASH
:
1267 case awt::FontUnderline::LONGDASH
:
1268 underline
= "dashLong";
1270 case awt::FontUnderline::DASHDOT
:
1271 underline
= "dotDash";
1273 case awt::FontUnderline::DASHDOTDOT
:
1274 underline
= "dotDotDash";
1276 case awt::FontUnderline::WAVE
:
1279 case awt::FontUnderline::DOUBLEWAVE
:
1280 underline
= "wavyDbl";
1282 case awt::FontUnderline::BOLD
:
1283 underline
= "heavy";
1285 case awt::FontUnderline::BOLDDOTTED
:
1286 underline
= "dottedHeavy";
1288 case awt::FontUnderline::BOLDDASH
:
1289 underline
= "dashHeavy";
1291 case awt::FontUnderline::BOLDLONGDASH
:
1292 underline
= "dashLongHeavy";
1294 case awt::FontUnderline::BOLDDASHDOT
:
1295 underline
= "dotDashHeavy";
1297 case awt::FontUnderline::BOLDDASHDOTDOT
:
1298 underline
= "dotDotDashHeavy";
1300 case awt::FontUnderline::BOLDWAVE
:
1301 underline
= "wavyHeavy";
1306 if ( CGETAD( CharStrikeout
) )
1308 switch ( *static_cast<sal_Int16
const *>(mAny
.getValue()) )
1310 case awt::FontStrikeout::NONE
:
1311 strikeout
= "noStrike";
1313 case awt::FontStrikeout::SINGLE
:
1314 // LibO supports further values of character
1315 // strikeout, OOXML standard (20.1.10.78,
1316 // ST_TextStrikeType) however specifies only
1317 // 3 - single, double and none. Approximate
1318 // the remaining ones by single strike (better
1319 // some strike than none at all).
1320 // TODO: figure out how to do this better
1321 case awt::FontStrikeout::BOLD
:
1322 case awt::FontStrikeout::SLASH
:
1323 case awt::FontStrikeout::X
:
1324 strikeout
= "sngStrike";
1326 case awt::FontStrikeout::DOUBLE
:
1327 strikeout
= "dblStrike";
1332 if( GETA( CharLocale
) )
1334 com::sun::star::lang::Locale aLocale
;
1336 LanguageTag
aLanguageTag( aLocale
);
1337 if (!aLanguageTag
.isSystemLocale())
1338 usLanguage
= aLanguageTag
.getBcp47();
1341 if( GETAD( CharEscapement
) )
1342 mAny
>>= nCharEscapement
;
1344 if( nCharEscapement
&& GETAD( CharEscapementHeight
) )
1346 sal_uInt32 nCharEscapementHeight
= 0;
1347 mAny
>>= nCharEscapementHeight
;
1348 nSize
= (nSize
* nCharEscapementHeight
) / 100;
1349 // MSO uses default ~58% size
1350 nSize
= (nSize
/ 0.58);
1353 if( GETA( CharCaseMap
) )
1355 switch ( *static_cast<sal_Int16
const *>(mAny
.getValue()) )
1357 case CaseMap::UPPERCASE
:
1360 case CaseMap::SMALLCAPS
:
1366 mpFS
->startElementNS( XML_a
, nElement
,
1369 XML_lang
, usLanguage
.isEmpty() ? NULL
: USS( usLanguage
),
1370 XML_sz
, IS( nSize
),
1371 // For Condensed character spacing spc value is negative.
1372 XML_spc
, nCharKerning
? IS(nCharKerning
) : NULL
,
1373 XML_strike
, strikeout
,
1375 XML_baseline
, nCharEscapement
== 0 ? NULL
: IS( nCharEscapement
*1000 ),
1379 // mso doesn't like text color to be placed after typeface
1380 if( CGETAD( CharColor
) )
1382 sal_uInt32 color
= *static_cast<sal_uInt32
const *>(mAny
.getValue());
1383 DBG(fprintf(stderr
, "run color: %x auto: %x\n", static_cast<unsigned int>( color
), static_cast<unsigned int>( COL_AUTO
)));
1385 if( color
== COL_AUTO
) // nCharColor depends to the background color
1387 color
= mbIsBackgroundDark
? COL_WHITE
: COL_BLACK
;
1391 // TODO: special handle embossed/engraved
1393 WriteSolidFill( color
);
1396 if( CGETAD( CharUnderlineColor
) )
1398 sal_uInt32 color
= *static_cast<sal_uInt32
const *>(mAny
.getValue());
1400 mpFS
->startElementNS( XML_a
, XML_uFill
,FSEND
);
1401 WriteSolidFill( color
);
1402 mpFS
->endElementNS( XML_a
, XML_uFill
);
1405 if( GETA( CharFontName
) )
1407 const char* pitch
= NULL
;
1408 const char* charset
= NULL
;
1409 OUString usTypeface
;
1411 mAny
>>= usTypeface
;
1412 OUString
aSubstName( GetSubsFontName( usTypeface
, SubsFontFlags::ONLYONE
| SubsFontFlags::MS
) );
1414 mpFS
->singleElementNS( XML_a
, XML_latin
,
1415 XML_typeface
, USS(aSubstName
.getLength() ? aSubstName
: usTypeface
),
1416 XML_pitchFamily
, pitch
,
1417 XML_charset
, charset
,
1421 if( ( bComplex
&& GETAD( CharFontNameComplex
) ) || ( !bComplex
&& GETAD( CharFontNameAsian
) ) )
1423 const char* pitch
= NULL
;
1424 const char* charset
= NULL
;
1425 OUString usTypeface
;
1427 mAny
>>= usTypeface
;
1428 OUString
aSubstName( GetSubsFontName( usTypeface
, SubsFontFlags::ONLYONE
| SubsFontFlags::MS
) );
1430 mpFS
->singleElementNS( XML_a
, bComplex
? XML_cs
: XML_ea
,
1431 XML_typeface
, USS(aSubstName
.getLength() ? aSubstName
: usTypeface
),
1432 XML_pitchFamily
, pitch
,
1433 XML_charset
, charset
,
1439 Reference
< XTextField
> rXTextField
;
1440 GET( rXTextField
, TextField
);
1441 if( rXTextField
.is() )
1442 rXPropSet
.set( rXTextField
, UNO_QUERY
);
1445 // field properties starts here
1451 if( !sURL
.isEmpty() ) {
1452 OUString sRelId
= mpFB
->addRelation( mpFS
->getOutputStream(),
1453 "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink",
1456 mpFS
->singleElementNS( XML_a
, XML_hlinkClick
,
1457 FSNS( XML_r
,XML_id
), USS( sRelId
),
1462 mpFS
->endElementNS( XML_a
, nElement
);
1465 OUString
DrawingML::GetFieldValue( ::com::sun::star::uno::Reference
< ::com::sun::star::text::XTextRange
> rRun
, bool& bIsURLField
)
1467 Reference
< XPropertySet
> rXPropSet( rRun
, UNO_QUERY
);
1468 OUString aFieldType
, aFieldValue
;
1470 if( GETA( TextPortionType
) )
1472 aFieldType
= OUString( *static_cast<OUString
const *>(mAny
.getValue()) );
1473 DBG(fprintf (stderr
, "field type: %s\n", USS(aFieldType
) ));
1476 if( aFieldType
== "TextField" )
1478 Reference
< XTextField
> rXTextField
;
1479 GET( rXTextField
, TextField
);
1480 if( rXTextField
.is() )
1482 rXPropSet
.set( rXTextField
, UNO_QUERY
);
1483 if( rXPropSet
.is() )
1485 OUString
aFieldKind( rXTextField
->getPresentation( true ) );
1486 DBG(fprintf (stderr
, "field kind: %s\n", USS(aFieldKind
) ));
1487 if( aFieldKind
== "Page" )
1489 aFieldValue
= OUString("slidenum");
1491 else if( aFieldKind
== "URL" )
1494 GET( aFieldValue
, Representation
)
1504 void DrawingML::GetUUID( OStringBuffer
& rBuffer
)
1506 Sequence
< sal_uInt8
> aSeq( 16 );
1507 static const char cDigits
[17] = "0123456789ABCDEF";
1508 rtl_createUuid( (sal_uInt8
*)aSeq
.getArray(), 0, true );
1511 rBuffer
.append( '{' );
1512 for( i
= 0; i
< 4; i
++ )
1514 rBuffer
.append( cDigits
[ aSeq
[i
] >> 4 ] );
1515 rBuffer
.append( cDigits
[ aSeq
[i
] & 0xf ] );
1517 rBuffer
.append( '-' );
1520 rBuffer
.append( cDigits
[ aSeq
[i
] >> 4 ] );
1521 rBuffer
.append( cDigits
[ aSeq
[i
] & 0xf ] );
1523 rBuffer
.append( '-' );
1526 rBuffer
.append( cDigits
[ aSeq
[i
] >> 4 ] );
1527 rBuffer
.append( cDigits
[ aSeq
[i
] & 0xf ] );
1529 rBuffer
.append( '-' );
1530 for( ; i
< 10; i
++ )
1532 rBuffer
.append( cDigits
[ aSeq
[i
] >> 4 ] );
1533 rBuffer
.append( cDigits
[ aSeq
[i
] & 0xf ] );
1535 rBuffer
.append( '-' );
1536 for( ; i
< 16; i
++ )
1538 rBuffer
.append( cDigits
[ aSeq
[i
] >> 4 ] );
1539 rBuffer
.append( cDigits
[ aSeq
[i
] & 0xf ] );
1541 rBuffer
.append( '}' );
1544 void DrawingML::WriteRun( Reference
< XTextRange
> rRun
)
1546 Reference
< XPropertySet
> rXPropSet( rRun
, UNO_QUERY
);
1547 sal_Int16 nLevel
= -1;
1548 GET( nLevel
, NumberingLevel
);
1550 bool bIsURLField
= false;
1551 OUString sFieldValue
= GetFieldValue( rRun
, bIsURLField
);
1552 bool bWriteField
= !( sFieldValue
.isEmpty() || bIsURLField
);
1554 OUString sText
= rRun
->getString();
1556 //if there is no text following the bullet, add a space after the bullet
1557 if (nLevel
!=-1 && sText
.isEmpty() )
1561 sText
= sFieldValue
;
1563 if( sText
.isEmpty())
1565 Reference
< XPropertySet
> xPropSet( rRun
, UNO_QUERY
);
1569 if( !xPropSet
.is() || !( xPropSet
->getPropertyValue( "PlaceholderText" ) >>= sText
) )
1571 if( sText
.isEmpty() )
1574 catch (const Exception
&)
1580 if( ( bWriteField
) )
1582 OStringBuffer
sUUID(39);
1585 mpFS
->startElementNS( XML_a
, XML_fld
,
1586 XML_id
, sUUID
.getStr(),
1587 XML_type
, OUStringToOString( sFieldValue
, RTL_TEXTENCODING_UTF8
).getStr(),
1592 mpFS
->startElementNS( XML_a
, XML_r
, FSEND
);
1595 Reference
< XPropertySet
> xPropSet( rRun
, uno::UNO_QUERY
);
1596 WriteRunProperties( xPropSet
, bIsURLField
);
1598 mpFS
->startElementNS( XML_a
, XML_t
, FSEND
);
1599 mpFS
->writeEscaped( sText
);
1600 mpFS
->endElementNS( XML_a
, XML_t
);
1603 mpFS
->endElementNS( XML_a
, XML_fld
);
1605 mpFS
->endElementNS( XML_a
, XML_r
);
1608 OUString
GetAutoNumType(sal_Int16 nNumberingType
, bool bSDot
, bool bPBehind
, bool bPBoth
)
1610 OUString sPrefixSuffix
;
1613 sPrefixSuffix
= "ParenBoth";
1615 sPrefixSuffix
= "ParenR";
1617 sPrefixSuffix
= "Period";
1619 switch( (SvxExtNumType
)nNumberingType
)
1621 case SVX_NUM_CHARS_UPPER_LETTER_N
:
1622 case SVX_NUM_CHARS_UPPER_LETTER
:
1623 return "alphaUc" + sPrefixSuffix
;
1625 case SVX_NUM_CHARS_LOWER_LETTER_N
:
1626 case SVX_NUM_CHARS_LOWER_LETTER
:
1627 return "alphaLc" + sPrefixSuffix
;
1629 case SVX_NUM_ROMAN_UPPER
:
1630 return "romanUc" + sPrefixSuffix
;
1632 case SVX_NUM_ROMAN_LOWER
:
1633 return "romanLc" + sPrefixSuffix
;
1635 case SVX_NUM_ARABIC
:
1637 if (sPrefixSuffix
.isEmpty())
1638 return OUString("arabicPlain");
1640 return "arabic" + sPrefixSuffix
;
1649 void DrawingML::WriteParagraphNumbering( Reference
< XPropertySet
> rXPropSet
, sal_Int16 nLevel
)
1651 if( nLevel
< 0 || !GETA( NumberingRules
) )
1654 Reference
< XIndexAccess
> rXIndexAccess
;
1656 if (!(mAny
>>= rXIndexAccess
) || nLevel
>= rXIndexAccess
->getCount())
1659 DBG(fprintf (stderr
, "numbering rules\n"));
1661 Sequence
<PropertyValue
> aPropertySequence
;
1662 rXIndexAccess
->getByIndex(nLevel
) >>= aPropertySequence
;
1664 if (!aPropertySequence
.hasElements())
1667 sal_Int32 nPropertyCount
= aPropertySequence
.getLength();
1669 const PropertyValue
* pPropValue
= aPropertySequence
.getArray();
1671 sal_Int16 nNumberingType
= SVX_NUM_NUMBER_NONE
;
1673 bool bPBehind
= false;
1674 bool bPBoth
= false;
1675 sal_Unicode aBulletChar
= 0x2022; // a bullet
1676 awt::FontDescriptor aFontDesc
;
1677 bool bHasFontDesc
= false;
1678 OUString aGraphicURL
;
1679 sal_Int16 nBulletRelSize
= 0;
1680 sal_Int16 nStartWith
= 1;
1681 sal_uInt32 nBulletColor
= 0;
1682 bool bHasBulletColor
= false;
1684 for ( sal_Int32 i
= 0; i
< nPropertyCount
; i
++ )
1686 const void* pValue
= pPropValue
[ i
].Value
.getValue();
1689 OUString
aPropName( pPropValue
[ i
].Name
);
1690 DBG(fprintf (stderr
, "pro name: %s\n", OUStringToOString( aPropName
, RTL_TEXTENCODING_UTF8
).getStr()));
1691 if ( aPropName
== "NumberingType" )
1693 nNumberingType
= *( static_cast<sal_Int16
const *>(pValue
) );
1695 else if ( aPropName
== "Prefix" )
1697 if( *static_cast<OUString
const *>(pValue
) == ")")
1700 else if ( aPropName
== "Suffix" )
1702 if( *static_cast<OUString
const *>(pValue
) == ".")
1704 else if( *static_cast<OUString
const *>(pValue
) == ")")
1707 else if(aPropName
== "BulletColor")
1709 nBulletColor
= *static_cast<sal_uInt32
const *>(pValue
);
1710 bHasBulletColor
= true;
1712 else if ( aPropName
== "BulletChar" )
1714 aBulletChar
= OUString ( *( static_cast<OUString
const *>(pValue
) ) )[ 0 ];
1716 else if ( aPropName
== "BulletFont" )
1718 aFontDesc
= *static_cast<awt::FontDescriptor
const *>(pValue
);
1719 bHasFontDesc
= true;
1721 // Our numbullet dialog has set the wrong textencoding for our "StarSymbol" font,
1722 // instead of a Unicode encoding the encoding RTL_TEXTENCODING_SYMBOL was used.
1723 // Because there might exist a lot of damaged documemts I added this two lines
1724 // which fixes the bullet problem for the export.
1725 if ( aFontDesc
.Name
.equalsIgnoreAsciiCase("StarSymbol") )
1726 aFontDesc
.CharSet
= RTL_TEXTENCODING_MS_1252
;
1729 else if ( aPropName
== "BulletRelSize" )
1731 nBulletRelSize
= *static_cast<sal_Int16
const *>(pValue
);
1733 else if ( aPropName
== "StartWith" )
1735 nStartWith
= *static_cast<sal_Int16
const *>(pValue
);
1737 else if ( aPropName
== "GraphicURL" )
1739 aGraphicURL
= *static_cast<OUString
const *>(pValue
);
1740 DBG(fprintf (stderr
, "graphic url: %s\n", OUStringToOString( aGraphicURL
, RTL_TEXTENCODING_UTF8
).getStr()));
1742 else if ( aPropName
== "GraphicSize" )
1744 if ( pPropValue
[ i
].Value
.getValueType() == cppu::UnoType
<awt::Size
>::get())
1746 // don't cast awt::Size to Size as on 64-bits they are not the same.
1747 css::awt::Size aSize
;
1748 pPropValue
[ i
].Value
>>= aSize
;
1749 //aBuGraSize.nA = aSize.Width;
1750 //aBuGraSize.nB = aSize.Height;
1751 DBG(fprintf(stderr
, "graphic size: %dx%d\n", int( aSize
.Width
), int( aSize
.Height
)));
1757 if (nNumberingType
== SVX_NUM_NUMBER_NONE
)
1760 if( !aGraphicURL
.isEmpty() )
1762 OUString sRelId
= WriteImage( aGraphicURL
);
1764 mpFS
->startElementNS( XML_a
, XML_buBlip
, FSEND
);
1765 mpFS
->singleElementNS( XML_a
, XML_blip
, FSNS( XML_r
, XML_embed
), USS( sRelId
), FSEND
);
1766 mpFS
->endElementNS( XML_a
, XML_buBlip
);
1772 if (nBulletColor
== COL_AUTO
)
1774 nBulletColor
= mbIsBackgroundDark
? COL_WHITE
: COL_BLACK
;
1776 mpFS
->startElementNS( XML_a
, XML_buClr
, FSEND
);
1777 WriteColor( nBulletColor
);
1778 mpFS
->endElementNS( XML_a
, XML_buClr
);
1781 if( nBulletRelSize
&& nBulletRelSize
!= 100 )
1782 mpFS
->singleElementNS( XML_a
, XML_buSzPct
,
1783 XML_val
, IS( std::max( (sal_Int32
)25000, std::min( (sal_Int32
)400000, 1000*( (sal_Int32
)nBulletRelSize
) ) ) ), FSEND
);
1786 if ( SVX_NUM_CHAR_SPECIAL
== nNumberingType
)
1787 aBulletChar
= SubstituteBullet( aBulletChar
, aFontDesc
);
1788 mpFS
->singleElementNS( XML_a
, XML_buFont
,
1789 XML_typeface
, aFontDesc
.Name
.toUtf8().getStr(),
1790 XML_charset
, (aFontDesc
.CharSet
== awt::CharSet::SYMBOL
) ? "2" : NULL
,
1794 OUString pAutoNumType
= GetAutoNumType( nNumberingType
, bSDot
, bPBehind
, bPBoth
);
1796 if (!pAutoNumType
.isEmpty())
1798 mpFS
->singleElementNS(XML_a
, XML_buAutoNum
,
1799 XML_type
, OUStringToOString(pAutoNumType
, RTL_TEXTENCODING_UTF8
).getStr(),
1800 XML_startAt
, nStartWith
> 1 ? IS(nStartWith
) : NULL
,
1805 mpFS
->singleElementNS(XML_a
, XML_buChar
, XML_char
, USS( OUString( aBulletChar
) ), FSEND
);
1810 sal_Int32
DrawingML::getBulletMarginIndentation (Reference
< XPropertySet
> rXPropSet
,sal_Int16 nLevel
, const OUString
& propName
)
1812 if( nLevel
< 0 || !GETA( NumberingRules
) )
1815 Reference
< XIndexAccess
> rXIndexAccess
;
1817 if (!(mAny
>>= rXIndexAccess
) || nLevel
>= rXIndexAccess
->getCount())
1820 DBG(fprintf (stderr
, "numbering rules\n"));
1822 Sequence
<PropertyValue
> aPropertySequence
;
1823 rXIndexAccess
->getByIndex(nLevel
) >>= aPropertySequence
;
1825 if (!aPropertySequence
.hasElements())
1828 sal_Int32 nPropertyCount
= aPropertySequence
.getLength();
1830 const PropertyValue
* pPropValue
= aPropertySequence
.getArray();
1832 for ( sal_Int32 i
= 0; i
< nPropertyCount
; i
++ )
1834 const void* pValue
= pPropValue
[ i
].Value
.getValue();
1837 OUString
aPropName( pPropValue
[ i
].Name
);
1838 DBG(fprintf (stderr
, "pro name: %s\n", OUStringToOString( aPropName
, RTL_TEXTENCODING_UTF8
).getStr()));
1839 if ( aPropName
== propName
)
1840 return *( static_cast<sal_Int32
const *>(pValue
) );
1847 const char* DrawingML::GetAlignment( sal_Int32 nAlignment
)
1849 const char* sAlignment
= NULL
;
1851 switch( nAlignment
)
1853 case style::ParagraphAdjust_CENTER
:
1856 case style::ParagraphAdjust_RIGHT
:
1859 case style::ParagraphAdjust_BLOCK
:
1860 sAlignment
= "just";
1869 void DrawingML::WriteLinespacing( LineSpacing
& rSpacing
)
1871 if( rSpacing
.Mode
== LineSpacingMode::PROP
)
1873 mpFS
->singleElementNS( XML_a
, XML_spcPct
,
1874 XML_val
, I32S( ((sal_Int32
)rSpacing
.Height
)*1000 ),
1879 mpFS
->singleElementNS( XML_a
, XML_spcPts
,
1880 XML_val
, I32S( rSpacing
.Height
),
1885 void DrawingML::WriteParagraphProperties( Reference
< XTextContent
> rParagraph
)
1887 Reference
< XPropertySet
> rXPropSet( rParagraph
, UNO_QUERY
);
1888 Reference
< XPropertyState
> rXPropState( rParagraph
, UNO_QUERY
);
1889 PropertyState eState
;
1891 if( !rXPropSet
.is() || !rXPropState
.is() )
1894 sal_Int16 nLevel
= -1;
1895 GET( nLevel
, NumberingLevel
);
1897 sal_Int16
nAlignment( style::ParagraphAdjust_LEFT
);
1898 GET( nAlignment
, ParaAdjust
);
1900 bool bHasLinespacing
= false;
1901 LineSpacing aLineSpacing
;
1902 if( GETAD( ParaLineSpacing
) )
1903 bHasLinespacing
= ( mAny
>>= aLineSpacing
);
1906 if( GETA( WritingMode
) )
1908 sal_Int16 nWritingMode
;
1909 if( ( mAny
>>= nWritingMode
) && nWritingMode
== text::WritingMode2::RL_TB
)
1915 sal_Int32 nParaLeftMargin
= 0;
1916 sal_Int32 nParaFirstLineIndent
= 0;
1918 GET( nParaLeftMargin
, ParaLeftMargin
);
1919 GET( nParaFirstLineIndent
,ParaFirstLineIndent
);
1921 sal_Int32 nLeftMargin
= getBulletMarginIndentation ( rXPropSet
, nLevel
,"LeftMargin");
1922 sal_Int32 nLineIndentation
= getBulletMarginIndentation ( rXPropSet
, nLevel
,"FirstLineOffset");
1925 || nAlignment
!= style::ParagraphAdjust_LEFT
1926 || bHasLinespacing
)
1928 if (nParaLeftMargin
) // For Paraghraph
1929 mpFS
->startElementNS( XML_a
, XML_pPr
,
1930 XML_lvl
, nLevel
> 0 ? I32S( nLevel
) : NULL
,
1931 XML_marL
, nParaLeftMargin
> 0 ? I32S( oox::drawingml::convertHmmToEmu( nParaLeftMargin
) ) : NULL
,
1932 XML_indent
, nParaFirstLineIndent
? I32S( oox::drawingml::convertHmmToEmu( nParaFirstLineIndent
) ) : NULL
,
1933 XML_algn
, GetAlignment( nAlignment
),
1934 XML_rtl
, bRtl
? BS(bRtl
) : NULL
,
1937 mpFS
->startElementNS( XML_a
, XML_pPr
,
1938 XML_lvl
, nLevel
> 0 ? I32S( nLevel
) : NULL
,
1939 XML_marL
, nLeftMargin
> 0 ? I32S( oox::drawingml::convertHmmToEmu( nLeftMargin
) ) : NULL
,
1940 XML_indent
, nLineIndentation
? I32S( oox::drawingml::convertHmmToEmu( nLineIndentation
) ) : NULL
,
1941 XML_algn
, GetAlignment( nAlignment
),
1942 XML_rtl
, bRtl
? BS(bRtl
) : NULL
,
1947 if( bHasLinespacing
)
1949 mpFS
->startElementNS( XML_a
, XML_lnSpc
, FSEND
);
1950 WriteLinespacing( aLineSpacing
);
1951 mpFS
->endElementNS( XML_a
, XML_lnSpc
);
1954 WriteParagraphNumbering( rXPropSet
, nLevel
);
1956 mpFS
->endElementNS( XML_a
, XML_pPr
);
1960 void DrawingML::WriteParagraph( Reference
< XTextContent
> rParagraph
)
1962 Reference
< XEnumerationAccess
> access( rParagraph
, UNO_QUERY
);
1966 Reference
< XEnumeration
> enumeration( access
->createEnumeration() );
1967 if( !enumeration
.is() )
1970 mpFS
->startElementNS( XML_a
, XML_p
, FSEND
);
1973 bool bPropertiesWritten
= false;
1974 while( enumeration
->hasMoreElements() )
1976 Reference
< XTextRange
> run
;
1977 Any
any ( enumeration
->nextElement() );
1981 if( !bPropertiesWritten
)
1983 WriteParagraphProperties( rParagraph
);
1984 bPropertiesWritten
= true;
1989 Reference
< XPropertySet
> rXPropSet( rParagraph
, UNO_QUERY
);
1990 WriteRunProperties( rXPropSet
, false, XML_endParaRPr
);
1992 mpFS
->endElementNS( XML_a
, XML_p
);
1995 void DrawingML::WriteText( Reference
< XInterface
> rXIface
, const OUString
& presetWarp
, bool bBodyPr
, bool bText
, sal_Int32 nXmlNamespace
)
1997 Reference
< XText
> xXText( rXIface
, UNO_QUERY
);
1998 Reference
< XPropertySet
> rXPropSet( rXIface
, UNO_QUERY
);
2003 #define DEFLRINS 254
2004 #define DEFTBINS 127
2005 sal_Int32 nLeft
, nRight
, nTop
, nBottom
;
2006 nLeft
= nRight
= DEFLRINS
;
2007 nTop
= nBottom
= DEFTBINS
;
2009 // top inset looks a bit different compared to ppt export
2010 // check if something related doesn't work as expected
2011 GET( nLeft
, TextLeftDistance
);
2012 GET( nRight
, TextRightDistance
);
2013 GET( nTop
, TextUpperDistance
);
2014 GET( nBottom
, TextLowerDistance
);
2016 TextVerticalAdjust
eVerticalAlignment( TextVerticalAdjust_TOP
);
2017 const char* sVerticalAlignment
= NULL
;
2018 GET( eVerticalAlignment
, TextVerticalAdjust
);
2019 if( eVerticalAlignment
!= TextVerticalAdjust_TOP
)
2020 sVerticalAlignment
= GetTextVerticalAdjust(eVerticalAlignment
);
2022 const char* sWritingMode
= NULL
;
2023 bool bVertical
= false;
2024 if( GETA( TextWritingMode
) )
2028 if( ( mAny
>>= eMode
) && eMode
== WritingMode_TB_RL
)
2030 sWritingMode
= "vert";
2035 if ( GETA( CustomShapeGeometry
) )
2037 Sequence
< PropertyValue
> aProps
;
2038 if ( mAny
>>= aProps
)
2040 for ( sal_Int32 i
= 0, nElems
= aProps
.getLength(); i
< nElems
; ++i
)
2042 sal_Int32 nTextRotateAngle
= 0;
2043 if ( aProps
[ i
].Name
== "TextPreRotateAngle" && ( aProps
[ i
].Value
>>= nTextRotateAngle
) )
2045 if ( nTextRotateAngle
== -90 )
2047 sWritingMode
= "vert";
2050 else if ( nTextRotateAngle
== -270 )
2052 sWritingMode
= "vert270";
2061 TextHorizontalAdjust
eHorizontalAlignment( TextHorizontalAdjust_CENTER
);
2062 bool bHorizontalCenter
= false;
2063 GET( eHorizontalAlignment
, TextHorizontalAdjust
);
2064 if( eHorizontalAlignment
== TextHorizontalAdjust_CENTER
)
2065 bHorizontalCenter
= true;
2066 else if( bVertical
&& eHorizontalAlignment
== TextHorizontalAdjust_LEFT
)
2067 sVerticalAlignment
= "b";
2069 bool bHasWrap
= false;
2071 // Only custom shapes obey the TextWordWrap option, normal text always wraps.
2072 if( dynamic_cast<SvxCustomShape
*>(rXIface
.get()) && GETA( TextWordWrap
) )
2080 const char* pWrap
= bHasWrap
&& !bWrap
? "none" : NULL
;
2081 if (GetDocumentType() == DOCUMENT_DOCX
)
2083 // In case of DOCX, if we want to have the same effect as
2084 // TextShape's automatic word wrapping, then we need to set
2085 // wrapping to square.
2086 uno::Reference
<lang::XServiceInfo
> xServiceInfo(rXIface
, uno::UNO_QUERY
);
2087 if (xServiceInfo
.is() && xServiceInfo
->supportsService("com.sun.star.drawing.TextShape"))
2090 mpFS
->startElementNS( (nXmlNamespace
? nXmlNamespace
: XML_a
), XML_bodyPr
,
2092 XML_lIns
, (nLeft
!= DEFLRINS
) ? IS( oox::drawingml::convertHmmToEmu( nLeft
) ) : NULL
,
2093 XML_rIns
, (nRight
!= DEFLRINS
) ? IS( oox::drawingml::convertHmmToEmu( nRight
) ) : NULL
,
2094 XML_tIns
, (nTop
!= DEFTBINS
) ? IS( oox::drawingml::convertHmmToEmu( nTop
) ) : NULL
,
2095 XML_bIns
, (nBottom
!= DEFTBINS
) ? IS( oox::drawingml::convertHmmToEmu( nBottom
) ) : NULL
,
2096 XML_anchor
, sVerticalAlignment
,
2097 XML_anchorCtr
, bHorizontalCenter
? "1" : NULL
,
2098 XML_vert
, sWritingMode
,
2100 if( presetWarp
!= NULL
&& !presetWarp
.isEmpty())
2102 mpFS
->singleElementNS(XML_a
, XML_prstTxWarp
, XML_prst
, presetWarp
.toUtf8().getStr(),
2105 if (GetDocumentType() == DOCUMENT_DOCX
)
2107 sal_Bool bTextAutoGrowHeight
= sal_False
;
2108 GET(bTextAutoGrowHeight
, TextAutoGrowHeight
);
2109 mpFS
->singleElementNS(XML_a
, (bTextAutoGrowHeight
? XML_spAutoFit
: XML_noAutofit
), FSEND
);
2111 mpFS
->endElementNS((nXmlNamespace
? nXmlNamespace
: XML_a
), XML_bodyPr
);
2114 Reference
< XEnumerationAccess
> access( xXText
, UNO_QUERY
);
2115 if( !access
.is() || !bText
)
2118 Reference
< XEnumeration
> enumeration( access
->createEnumeration() );
2119 if( !enumeration
.is() )
2122 uno::Reference
<drawing::XShape
> xShape(rXIface
, uno::UNO_QUERY
);
2123 SdrObject
* pSdrObject
= xShape
.is() ? GetSdrObjectFromXShape(xShape
) : 0;
2124 const SdrTextObj
* pTxtObj
= PTR_CAST(SdrTextObj
, pSdrObject
);
2125 if (pTxtObj
&& mpTextExport
)
2127 const OutlinerParaObject
* pParaObj
= 0;
2128 bool bOwnParaObj
= false;
2132 When the object is actively being edited, that text is not set into
2133 the objects normal text object, but lives in a separate object.
2135 if (pTxtObj
->IsTextEditActive())
2137 pParaObj
= pTxtObj
->GetEditOutlinerParaObject();
2141 pParaObj
= pTxtObj
->GetOutlinerParaObject();
2145 // this is reached only in case some text is attached to the shape
2146 mpTextExport
->WriteOutliner(*pParaObj
);
2153 while( enumeration
->hasMoreElements() )
2155 Reference
< XTextContent
> paragraph
;
2156 Any
any ( enumeration
->nextElement() );
2158 if( any
>>= paragraph
)
2159 WriteParagraph( paragraph
);
2164 void DrawingML::WritePresetShape( const char* pShape
)
2166 mpFS
->startElementNS( XML_a
, XML_prstGeom
,
2169 mpFS
->singleElementNS( XML_a
, XML_avLst
, FSEND
);
2170 mpFS
->endElementNS( XML_a
, XML_prstGeom
);
2173 std::map
< OString
, std::vector
<OString
> > lcl_getAdjNames()
2175 std::map
< OString
, std::vector
<OString
> > aRet
;
2177 OUString
aPath("$BRAND_BASE_DIR/" LIBO_SHARE_FOLDER
"/filter/oox-drawingml-adj-names");
2178 rtl::Bootstrap::expandMacros(aPath
);
2179 SvFileStream
aStream(aPath
, StreamMode::READ
);
2180 if (aStream
.GetError() != ERRCODE_NONE
)
2181 SAL_WARN("oox", "failed to open oox-drawingml-adj-names");
2183 bool bNotDone
= aStream
.ReadLine(aLine
);
2186 sal_Int32 nIndex
= 0;
2187 // Each line is in a "key\tvalue" format: read the key, the rest is the value.
2188 OString aKey
= aLine
.getToken(0, '\t', nIndex
);
2189 OString aValue
= aLine
.copy(nIndex
);
2190 aRet
[aKey
].push_back(aValue
);
2191 bNotDone
= aStream
.ReadLine(aLine
);
2196 void DrawingML::WritePresetShape( const char* pShape
, MSO_SPT eShapeType
, bool bPredefinedHandlesUsed
, sal_Int32 nAdjustmentsWhichNeedsToBeConverted
, const PropertyValue
& rProp
)
2198 static std::map
< OString
, std::vector
<OString
> > aAdjMap
= lcl_getAdjNames();
2199 // If there are predefined adj names for this shape type, look them up now.
2200 std::vector
<OString
> aAdjustments
;
2201 if (aAdjMap
.find(OString(pShape
)) != aAdjMap
.end())
2202 aAdjustments
= aAdjMap
[OString(pShape
)];
2204 mpFS
->startElementNS( XML_a
, XML_prstGeom
,
2207 mpFS
->startElementNS( XML_a
, XML_avLst
, FSEND
);
2209 Sequence
< drawing::EnhancedCustomShapeAdjustmentValue
> aAdjustmentSeq
;
2210 if ( ( rProp
.Value
>>= aAdjustmentSeq
)
2211 && eShapeType
!= mso_sptActionButtonForwardNext
// we have adjustments values for these type of shape, but MSO doesn't like them
2212 && eShapeType
!= mso_sptActionButtonBackPrevious
// so they are now disabled
2213 && OString(pShape
) != "rect" //some shape types are commented out in pCustomShapeTypeTranslationTable[] & are being defaulted to rect & rect does not have adjustment values/name.
2216 DBG(fprintf(stderr
, "adj seq len: %d\n", int( aAdjustmentSeq
.getLength() )));
2217 if ( bPredefinedHandlesUsed
)
2218 EscherPropertyContainer::LookForPolarHandles( eShapeType
, nAdjustmentsWhichNeedsToBeConverted
);
2220 sal_Int32 nValue
, nLength
= aAdjustmentSeq
.getLength();
2221 //aAdjustments will give info about the number of adj values for a particular geometry. For example for hexagon aAdjustments.size() will be 2 and for circular arrow it will be 5 as per lcl_getAdjNames.
2222 if(aAdjustments
.size() == static_cast<sal_uInt32
>(nLength
))// In case there is a mismatch do not write the XML_gd tag.
2224 for( sal_Int32 i
=0; i
< nLength
; i
++ )
2226 if( EscherPropertyContainer::GetAdjustmentValue( aAdjustmentSeq
[ i
], i
, nAdjustmentsWhichNeedsToBeConverted
, nValue
) )
2228 // If the document model doesn't have an adjustment name (e.g. shape was created from VML), then take it from the predefined list.
2230 if (aAdjustmentSeq
[i
].Name
.isEmpty() && static_cast<sal_uInt32
>(i
) < aAdjustments
.size())
2231 aAdjName
= aAdjustments
[i
];
2233 mpFS
->singleElementNS( XML_a
, XML_gd
,
2234 XML_name
, aAdjustmentSeq
[ i
].Name
.getLength() > 0 ? USS(aAdjustmentSeq
[ i
].Name
) : aAdjName
.getStr(),
2235 XML_fmla
, OString("val " + OString::number( nValue
)).getStr(),
2242 mpFS
->endElementNS( XML_a
, XML_avLst
);
2243 mpFS
->endElementNS( XML_a
, XML_prstGeom
);
2246 void DrawingML::WriteCustomGeometry( Reference
< XShape
> rXShape
)
2248 uno::Reference
< beans::XPropertySet
> aXPropSet
;
2249 uno::Any
aAny( rXShape
->queryInterface(cppu::UnoType
<beans::XPropertySet
>::get()));
2251 if ( ! (aAny
>>= aXPropSet
) )
2256 aAny
= aXPropSet
->getPropertyValue( "CustomShapeGeometry" );
2257 if ( !aAny
.hasValue() )
2260 catch( const ::uno::Exception
& )
2267 uno::Sequence
< beans::PropertyValue
> const * pGeometrySeq
=
2268 static_cast<uno::Sequence
< beans::PropertyValue
> const *>(aAny
.getValue());
2272 for( int i
= 0; i
< pGeometrySeq
->getLength(); ++i
)
2274 const beans::PropertyValue
& rProp
= (*pGeometrySeq
)[ i
];
2275 if ( rProp
.Name
== "Path" )
2277 uno::Sequence
<beans::PropertyValue
> aPathProp
;
2278 rProp
.Value
>>= aPathProp
;
2280 uno::Sequence
<drawing::EnhancedCustomShapeParameterPair
> aPairs
;
2281 uno::Sequence
<drawing::EnhancedCustomShapeSegment
> aSegments
;
2282 uno::Sequence
<awt::Size
> aPathSize
;
2283 for (int j
= 0; j
< aPathProp
.getLength(); ++j
)
2285 const beans::PropertyValue
& rPathProp
= aPathProp
[j
];
2286 if (rPathProp
.Name
== "Coordinates")
2287 rPathProp
.Value
>>= aPairs
;
2288 else if (rPathProp
.Name
== "Segments")
2289 rPathProp
.Value
>>= aSegments
;
2290 else if (rPathProp
.Name
== "SubViewSize")
2291 rPathProp
.Value
>>= aPathSize
;
2294 if ( !aPairs
.hasElements() )
2297 if ( !aSegments
.hasElements() )
2299 aSegments
= uno::Sequence
<drawing::EnhancedCustomShapeSegment
>(4);
2300 aSegments
[0].Count
= 1;
2301 aSegments
[0].Command
= drawing::EnhancedCustomShapeSegmentCommand::MOVETO
;
2302 aSegments
[1].Count
= (sal_Int16
)std::min( aPairs
.getLength() - 1, (sal_Int32
)32767 );
2303 aSegments
[1].Command
= drawing::EnhancedCustomShapeSegmentCommand::LINETO
;
2304 aSegments
[2].Count
= 0;
2305 aSegments
[2].Command
= drawing::EnhancedCustomShapeSegmentCommand::CLOSESUBPATH
;
2306 aSegments
[3].Count
= 0;
2307 aSegments
[3].Command
= drawing::EnhancedCustomShapeSegmentCommand::ENDSUBPATH
;
2310 int nExpectedPairCount
= 0;
2311 for( int j
= 0; j
< aSegments
.getLength(); ++j
)
2313 nExpectedPairCount
+= aSegments
[j
].Count
;
2316 if ( nExpectedPairCount
> aPairs
.getLength() )
2318 SAL_WARN("oox", "Segments need " << nExpectedPairCount
<< " coordinates, but Coordinates have only " << aPairs
.getLength() << " pairs.");
2322 mpFS
->startElementNS( XML_a
, XML_custGeom
, FSEND
);
2323 mpFS
->singleElementNS( XML_a
, XML_avLst
, FSEND
);
2324 mpFS
->singleElementNS( XML_a
, XML_gdLst
, FSEND
);
2325 mpFS
->singleElementNS( XML_a
, XML_ahLst
, FSEND
);
2326 mpFS
->singleElementNS( XML_a
, XML_rect
, XML_l
, "l", XML_t
, "t",
2327 XML_r
, "r", XML_b
, "b", FSEND
);
2328 mpFS
->startElementNS( XML_a
, XML_pathLst
, FSEND
);
2330 if ( aPathSize
.hasElements() )
2332 mpFS
->startElementNS( XML_a
, XML_path
,
2333 XML_w
, I64S( aPathSize
[0].Width
),
2334 XML_h
, I64S( aPathSize
[0].Height
),
2340 aPairs
[0].First
.Value
>>= nXMin
;
2341 sal_Int32 nXMax
= nXMin
;
2343 aPairs
[0].Second
.Value
>>= nYMin
;
2344 sal_Int32 nYMax
= nYMin
;
2346 for ( int j
= 0; j
< aPairs
.getLength(); ++j
)
2348 sal_Int32
nCandidate(0);
2349 if ((aPairs
[j
].First
.Value
>>= nCandidate
) && nCandidate
< nXMin
)
2351 if ((aPairs
[j
].Second
.Value
>>= nCandidate
) && nCandidate
< nYMin
)
2353 if ((aPairs
[j
].First
.Value
>>= nCandidate
) && nCandidate
> nXMax
)
2355 if ((aPairs
[j
].Second
.Value
>>= nCandidate
) && nCandidate
> nYMax
)
2358 mpFS
->startElementNS( XML_a
, XML_path
,
2359 XML_w
, I64S( nXMax
- nXMin
),
2360 XML_h
, I64S( nYMax
- nYMin
),
2366 for( int j
= 0; j
< aSegments
.getLength(); ++j
)
2368 if ( aSegments
[ j
].Command
== drawing::EnhancedCustomShapeSegmentCommand::CLOSESUBPATH
)
2370 mpFS
->singleElementNS( XML_a
, XML_close
, FSEND
);
2372 for ( int k
= 0; k
< aSegments
[j
].Count
; ++k
)
2374 switch( aSegments
[ j
].Command
)
2376 case drawing::EnhancedCustomShapeSegmentCommand::MOVETO
:
2378 mpFS
->startElementNS( XML_a
, XML_moveTo
, FSEND
);
2380 sal_Int32
nX(0), nY(0);
2381 aPairs
[nPairIndex
].First
.Value
>>= nX
;
2382 aPairs
[nPairIndex
].Second
.Value
>>= nY
;
2384 mpFS
->singleElementNS( XML_a
, XML_pt
,
2389 mpFS
->endElementNS( XML_a
, XML_moveTo
);
2393 case drawing::EnhancedCustomShapeSegmentCommand::LINETO
:
2395 mpFS
->startElementNS( XML_a
, XML_lnTo
, FSEND
);
2397 sal_Int32
nX(0), nY(0);
2398 aPairs
[nPairIndex
].First
.Value
>>= nX
;
2399 aPairs
[nPairIndex
].Second
.Value
>>= nY
;
2401 mpFS
->singleElementNS( XML_a
, XML_pt
,
2405 mpFS
->endElementNS( XML_a
, XML_lnTo
);
2409 case drawing::EnhancedCustomShapeSegmentCommand::CURVETO
:
2411 mpFS
->startElementNS( XML_a
, XML_cubicBezTo
, FSEND
);
2412 for( sal_uInt8 l
= 0; l
<= 2; ++l
)
2414 sal_Int32
nX(0), nY(0);
2415 aPairs
[nPairIndex
+l
].First
.Value
>>= nX
;
2416 aPairs
[nPairIndex
+l
].Second
.Value
>>= nY
;
2418 mpFS
->singleElementNS( XML_a
, XML_pt
,
2424 mpFS
->endElementNS( XML_a
, XML_cubicBezTo
);
2428 case drawing::EnhancedCustomShapeSegmentCommand::ANGLEELLIPSETO
:
2429 case drawing::EnhancedCustomShapeSegmentCommand::ANGLEELLIPSE
:
2434 case drawing::EnhancedCustomShapeSegmentCommand::ARCTO
:
2435 case drawing::EnhancedCustomShapeSegmentCommand::ARC
:
2436 case drawing::EnhancedCustomShapeSegmentCommand::CLOCKWISEARCTO
:
2437 case drawing::EnhancedCustomShapeSegmentCommand::CLOCKWISEARC
:
2442 case drawing::EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTX
:
2443 case drawing::EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTY
:
2448 case drawing::EnhancedCustomShapeSegmentCommand::QUADRATICCURVETO
:
2450 mpFS
->startElementNS( XML_a
, XML_quadBezTo
, FSEND
);
2451 for( sal_uInt8 l
= 0; l
< 2; ++l
)
2453 sal_Int32
nX(0), nY(0);
2454 aPairs
[nPairIndex
+l
].First
.Value
>>= nX
;
2455 aPairs
[nPairIndex
+l
].Second
.Value
>>= nY
;
2457 mpFS
->singleElementNS( XML_a
, XML_pt
,
2463 mpFS
->endElementNS( XML_a
, XML_quadBezTo
);
2467 case drawing::EnhancedCustomShapeSegmentCommand::ARCANGLETO
:
2478 mpFS
->endElementNS( XML_a
, XML_path
);
2479 mpFS
->endElementNS( XML_a
, XML_pathLst
);
2480 mpFS
->endElementNS( XML_a
, XML_custGeom
);
2487 void DrawingML::WritePolyPolygon( const tools::PolyPolygon
& rPolyPolygon
)
2489 if( rPolyPolygon
.Count() < 1 )
2492 mpFS
->startElementNS( XML_a
, XML_custGeom
, FSEND
);
2493 mpFS
->singleElementNS( XML_a
, XML_avLst
, FSEND
);
2494 mpFS
->singleElementNS( XML_a
, XML_gdLst
, FSEND
);
2495 mpFS
->singleElementNS( XML_a
, XML_ahLst
, FSEND
);
2496 mpFS
->singleElementNS( XML_a
, XML_rect
,
2503 mpFS
->startElementNS( XML_a
, XML_pathLst
, FSEND
);
2505 for( sal_uInt16 i
= 0; i
< rPolyPolygon
.Count(); i
++ )
2508 const Polygon
& rPoly
= rPolyPolygon
[ i
];
2509 Rectangle
aRect( rPoly
.GetBoundRect() );
2511 mpFS
->startElementNS( XML_a
, XML_path
,
2512 XML_w
, I64S( aRect
.GetWidth() ),
2513 XML_h
, I64S( aRect
.GetHeight() ),
2516 if( rPoly
.GetSize() > 0 )
2518 mpFS
->startElementNS( XML_a
, XML_moveTo
, FSEND
);
2520 mpFS
->singleElementNS( XML_a
, XML_pt
,
2521 XML_x
, I64S( rPoly
[ 0 ].X() - aRect
.Left() ),
2522 XML_y
, I64S( rPoly
[ 0 ].Y() - aRect
.Top() ),
2525 mpFS
->endElementNS( XML_a
, XML_moveTo
);
2528 for( sal_uInt16 j
= 1; j
< rPoly
.GetSize(); j
++ )
2530 enum PolyFlags flags
= rPoly
.GetFlags(j
);
2531 if( flags
== POLY_CONTROL
)
2533 // a:cubicBezTo can only contain 3 a:pt elements, so we need to make sure of this
2534 if( j
+2 < rPoly
.GetSize() && rPoly
.GetFlags(j
+1) == POLY_CONTROL
&& rPoly
.GetFlags(j
+2) != POLY_CONTROL
)
2537 mpFS
->startElementNS( XML_a
, XML_cubicBezTo
, FSEND
);
2538 for( sal_uInt8 k
= 0; k
<= 2; ++k
)
2540 mpFS
->singleElementNS( XML_a
, XML_pt
,
2541 XML_x
, I64S( rPoly
[j
+k
].X() - aRect
.Left() ),
2542 XML_y
, I64S( rPoly
[j
+k
].Y() - aRect
.Top() ),
2546 mpFS
->endElementNS( XML_a
, XML_cubicBezTo
);
2550 else if( flags
== POLY_NORMAL
)
2552 mpFS
->startElementNS( XML_a
, XML_lnTo
, FSEND
);
2553 mpFS
->singleElementNS( XML_a
, XML_pt
,
2554 XML_x
, I64S( rPoly
[j
].X() - aRect
.Left() ),
2555 XML_y
, I64S( rPoly
[j
].Y() - aRect
.Top() ),
2557 mpFS
->endElementNS( XML_a
, XML_lnTo
);
2561 mpFS
->endElementNS( XML_a
, XML_path
);
2564 mpFS
->endElementNS( XML_a
, XML_pathLst
);
2566 mpFS
->endElementNS( XML_a
, XML_custGeom
);
2569 void DrawingML::WriteConnectorConnections( EscherConnectorListEntry
& rConnectorEntry
, sal_Int32 nStartID
, sal_Int32 nEndID
)
2571 if( nStartID
!= -1 )
2573 mpFS
->singleElementNS( XML_a
, XML_stCxn
,
2574 XML_id
, I32S( nStartID
),
2575 XML_idx
, I64S( rConnectorEntry
.GetConnectorRule( true ) ),
2580 mpFS
->singleElementNS( XML_a
, XML_endCxn
,
2581 XML_id
, I32S( nEndID
),
2582 XML_idx
, I64S( rConnectorEntry
.GetConnectorRule( false ) ),
2587 sal_Unicode
DrawingML::SubstituteBullet( sal_Unicode cBulletId
, ::com::sun::star::awt::FontDescriptor
& rFontDesc
)
2589 if ( IsStarSymbol(rFontDesc
.Name
) )
2591 rtl_TextEncoding eCharSet
= rFontDesc
.CharSet
;
2592 cBulletId
= msfilter::util::bestFitOpenSymbolToMSFont(cBulletId
, eCharSet
, rFontDesc
.Name
);
2593 rFontDesc
.CharSet
= eCharSet
;
2599 sax_fastparser::FSHelperPtr
DrawingML::CreateOutputStream (
2600 const OUString
& sFullStream
,
2601 const OUString
& sRelativeStream
,
2602 const Reference
< XOutputStream
>& xParentRelation
,
2603 const char* sContentType
,
2604 const char* sRelationshipType
,
2605 OUString
* pRelationshipId
)
2607 OUString sRelationshipId
;
2608 if (xParentRelation
.is())
2609 sRelationshipId
= GetFB()->addRelation( xParentRelation
, OUString::createFromAscii( sRelationshipType
), sRelativeStream
);
2611 sRelationshipId
= GetFB()->addRelation( OUString::createFromAscii( sRelationshipType
), sRelativeStream
);
2613 if( pRelationshipId
)
2614 *pRelationshipId
= sRelationshipId
;
2616 sax_fastparser::FSHelperPtr p
= GetFB()->openFragmentStreamWithSerializer( sFullStream
, OUString::createFromAscii( sContentType
) );
2621 void DrawingML::WriteFill( Reference
< XPropertySet
> xPropSet
)
2623 if ( !GetProperty( xPropSet
, "FillStyle" ) )
2625 FillStyle
aFillStyle( FillStyle_NONE
);
2626 xPropSet
->getPropertyValue( "FillStyle" ) >>= aFillStyle
;
2628 if ( aFillStyle
== FillStyle_SOLID
&& GetProperty( xPropSet
, "FillTransparence" ) )
2630 // map full transparent background to no fill
2632 xPropSet
->getPropertyValue( "FillTransparence" ) >>= nVal
;
2634 aFillStyle
= FillStyle_NONE
;
2637 switch( aFillStyle
)
2639 case FillStyle_SOLID
:
2640 WriteSolidFill( xPropSet
);
2642 case FillStyle_GRADIENT
:
2643 WriteGradientFill( xPropSet
);
2645 case FillStyle_BITMAP
:
2646 WriteBlipFill( xPropSet
, "FillBitmapURL" );
2648 case FillStyle_HATCH
:
2649 WritePattFill( xPropSet
);
2651 case FillStyle_NONE
:
2652 mpFS
->singleElementNS( XML_a
, XML_noFill
, FSEND
);
2661 void DrawingML::WriteStyleProperties( sal_Int32 nTokenId
, const Sequence
< PropertyValue
>& aProperties
)
2663 if( aProperties
.getLength() > 0 )
2665 OUString sSchemeClr
;
2666 sal_uInt32 nIdx
= 0;
2667 Sequence
< PropertyValue
> aTransformations
;
2668 for( sal_Int32 i
=0; i
< aProperties
.getLength(); ++i
)
2670 if( aProperties
[i
].Name
== "SchemeClr" )
2671 aProperties
[i
].Value
>>= sSchemeClr
;
2672 else if( aProperties
[i
].Name
== "Idx" )
2673 aProperties
[i
].Value
>>= nIdx
;
2674 else if( aProperties
[i
].Name
== "Transformations" )
2675 aProperties
[i
].Value
>>= aTransformations
;
2677 mpFS
->startElementNS( XML_a
, nTokenId
, XML_idx
, I32S( nIdx
), FSEND
);
2678 WriteColor( sSchemeClr
, aTransformations
);
2679 mpFS
->endElementNS( XML_a
, nTokenId
);
2683 // write mock <a:*Ref> tag
2684 mpFS
->singleElementNS( XML_a
, nTokenId
, XML_idx
, I32S( 0 ), FSEND
);
2688 void DrawingML::WriteShapeStyle( Reference
< XPropertySet
> xPropSet
)
2690 // check existence of the grab bag
2691 if ( !GetProperty( xPropSet
, "InteropGrabBag" ) )
2694 // extract the relevant properties from the grab bag
2695 Sequence
< PropertyValue
> aGrabBag
;
2696 Sequence
< PropertyValue
> aFillRefProperties
, aLnRefProperties
, aEffectRefProperties
;
2698 for( sal_Int32 i
=0; i
< aGrabBag
.getLength(); ++i
)
2700 if( aGrabBag
[i
].Name
== "StyleFillRef" )
2701 aGrabBag
[i
].Value
>>= aFillRefProperties
;
2702 else if( aGrabBag
[i
].Name
== "StyleLnRef" )
2703 aGrabBag
[i
].Value
>>= aLnRefProperties
;
2704 else if( aGrabBag
[i
].Name
== "StyleEffectRef" )
2705 aGrabBag
[i
].Value
>>= aEffectRefProperties
;
2708 WriteStyleProperties( XML_lnRef
, aLnRefProperties
);
2709 WriteStyleProperties( XML_fillRef
, aFillRefProperties
);
2710 WriteStyleProperties( XML_effectRef
, aEffectRefProperties
);
2712 // write mock <a:fontRef>
2713 mpFS
->singleElementNS( XML_a
, XML_fontRef
, XML_idx
, "minor", FSEND
);
2716 void DrawingML::WriteShapeEffect( const OUString
& sName
, const Sequence
< PropertyValue
>& aEffectProps
)
2718 if( aEffectProps
.getLength() == 0 )
2721 // assign the proper tag and enable bContainsColor if necessary
2722 sal_Int32 nEffectToken
= 0;
2723 bool bContainsColor
= false;
2724 if( sName
== "outerShdw" )
2726 nEffectToken
= FSNS( XML_a
, XML_outerShdw
);
2727 bContainsColor
= true;
2729 else if( sName
== "innerShdw" )
2731 nEffectToken
= FSNS( XML_a
, XML_innerShdw
);
2732 bContainsColor
= true;
2734 else if( sName
== "glow" )
2736 nEffectToken
= FSNS( XML_a
, XML_glow
);
2737 bContainsColor
= true;
2739 else if( sName
== "softEdge" )
2740 nEffectToken
= FSNS( XML_a
, XML_softEdge
);
2741 else if( sName
== "reflection" )
2742 nEffectToken
= FSNS( XML_a
, XML_reflection
);
2743 else if( sName
== "blur" )
2744 nEffectToken
= FSNS( XML_a
, XML_blur
);
2746 OUString sSchemeClr
;
2747 sal_uInt32 nRgbClr
= 0;
2748 sal_Int32 nAlpha
= MAX_PERCENT
;
2749 Sequence
< PropertyValue
> aTransformations
;
2750 sax_fastparser::FastAttributeList
*aOuterShdwAttrList
= FastSerializerHelper::createAttrList();
2751 sax_fastparser::XFastAttributeListRef
xOuterShdwAttrList( aOuterShdwAttrList
);
2752 for( sal_Int32 i
=0; i
< aEffectProps
.getLength(); ++i
)
2754 if( aEffectProps
[i
].Name
== "Attribs" )
2756 // read tag attributes
2757 uno::Sequence
< beans::PropertyValue
> aOuterShdwProps
;
2758 aEffectProps
[i
].Value
>>= aOuterShdwProps
;
2759 for( sal_Int32 j
=0; j
< aOuterShdwProps
.getLength(); ++j
)
2761 if( aOuterShdwProps
[j
].Name
== "algn" )
2764 aOuterShdwProps
[j
].Value
>>= sVal
;
2765 aOuterShdwAttrList
->add( XML_algn
, OUStringToOString( sVal
, RTL_TEXTENCODING_UTF8
).getStr() );
2767 else if( aOuterShdwProps
[j
].Name
== "blurRad" )
2770 aOuterShdwProps
[j
].Value
>>= nVal
;
2771 aOuterShdwAttrList
->add( XML_blurRad
, OString::number( nVal
).getStr() );
2773 else if( aOuterShdwProps
[j
].Name
== "dir" )
2776 aOuterShdwProps
[j
].Value
>>= nVal
;
2777 aOuterShdwAttrList
->add( XML_dir
, OString::number( nVal
).getStr() );
2779 else if( aOuterShdwProps
[j
].Name
== "dist" )
2782 aOuterShdwProps
[j
].Value
>>= nVal
;
2783 aOuterShdwAttrList
->add( XML_dist
, OString::number( nVal
).getStr() );
2785 else if( aOuterShdwProps
[j
].Name
== "kx" )
2788 aOuterShdwProps
[j
].Value
>>= nVal
;
2789 aOuterShdwAttrList
->add( XML_kx
, OString::number( nVal
).getStr() );
2791 else if( aOuterShdwProps
[j
].Name
== "ky" )
2794 aOuterShdwProps
[j
].Value
>>= nVal
;
2795 aOuterShdwAttrList
->add( XML_ky
, OString::number( nVal
).getStr() );
2797 else if( aOuterShdwProps
[j
].Name
== "rotWithShape" )
2800 aOuterShdwProps
[j
].Value
>>= nVal
;
2801 aOuterShdwAttrList
->add( XML_rotWithShape
, OString::number( nVal
).getStr() );
2803 else if( aOuterShdwProps
[j
].Name
== "sx" )
2806 aOuterShdwProps
[j
].Value
>>= nVal
;
2807 aOuterShdwAttrList
->add( XML_sx
, OString::number( nVal
).getStr() );
2809 else if( aOuterShdwProps
[j
].Name
== "sy" )
2812 aOuterShdwProps
[j
].Value
>>= nVal
;
2813 aOuterShdwAttrList
->add( XML_sy
, OString::number( nVal
).getStr() );
2815 else if( aOuterShdwProps
[j
].Name
== "rad" )
2818 aOuterShdwProps
[j
].Value
>>= nVal
;
2819 aOuterShdwAttrList
->add( XML_rad
, OString::number( nVal
).getStr() );
2821 else if( aOuterShdwProps
[j
].Name
== "endA" )
2824 aOuterShdwProps
[j
].Value
>>= nVal
;
2825 aOuterShdwAttrList
->add( XML_endA
, OString::number( nVal
).getStr() );
2827 else if( aOuterShdwProps
[j
].Name
== "endPos" )
2830 aOuterShdwProps
[j
].Value
>>= nVal
;
2831 aOuterShdwAttrList
->add( XML_endPos
, OString::number( nVal
).getStr() );
2833 else if( aOuterShdwProps
[j
].Name
== "fadeDir" )
2836 aOuterShdwProps
[j
].Value
>>= nVal
;
2837 aOuterShdwAttrList
->add( XML_fadeDir
, OString::number( nVal
).getStr() );
2839 else if( aOuterShdwProps
[j
].Name
== "stA" )
2842 aOuterShdwProps
[j
].Value
>>= nVal
;
2843 aOuterShdwAttrList
->add( XML_stA
, OString::number( nVal
).getStr() );
2845 else if( aOuterShdwProps
[j
].Name
== "stPos" )
2848 aOuterShdwProps
[j
].Value
>>= nVal
;
2849 aOuterShdwAttrList
->add( XML_stPos
, OString::number( nVal
).getStr() );
2851 else if( aOuterShdwProps
[j
].Name
== "grow" )
2854 aOuterShdwProps
[j
].Value
>>= nVal
;
2855 aOuterShdwAttrList
->add( XML_grow
, OString::number( nVal
).getStr() );
2859 else if(aEffectProps
[i
].Name
== "RgbClr")
2861 aEffectProps
[i
].Value
>>= nRgbClr
;
2863 else if(aEffectProps
[i
].Name
== "RgbClrTransparency")
2865 sal_Int32 nTransparency
;
2866 if (aEffectProps
[i
].Value
>>= nTransparency
)
2867 // Calculate alpha value (see oox/source/drawingml/color.cxx : getTransparency())
2868 nAlpha
= MAX_PERCENT
- ( PER_PERCENT
* nTransparency
);
2870 else if(aEffectProps
[i
].Name
== "SchemeClr")
2872 aEffectProps
[i
].Value
>>= sSchemeClr
;
2874 else if(aEffectProps
[i
].Name
== "SchemeClrTransformations")
2876 aEffectProps
[i
].Value
>>= aTransformations
;
2880 if( nEffectToken
> 0 )
2882 mpFS
->startElement( nEffectToken
, xOuterShdwAttrList
);
2884 if( bContainsColor
)
2886 if( sSchemeClr
.isEmpty() )
2887 WriteColor( nRgbClr
, nAlpha
);
2889 WriteColor( sSchemeClr
, aTransformations
);
2892 mpFS
->endElement( nEffectToken
);
2896 void DrawingML::WriteShapeEffects( Reference
< XPropertySet
> rXPropSet
)
2898 if( !GetProperty( rXPropSet
, "InteropGrabBag" ) )
2901 Sequence
< PropertyValue
> aGrabBag
, aEffects
;
2903 for( sal_Int32 i
=0; i
< aGrabBag
.getLength(); ++i
)
2905 if( aGrabBag
[i
].Name
== "EffectProperties" )
2907 aGrabBag
[i
].Value
>>= aEffects
;
2911 if( aEffects
.getLength() == 0 )
2913 bool bHasShadow
= false;
2914 rXPropSet
->getPropertyValue( "Shadow" ) >>= bHasShadow
;
2917 Sequence
< PropertyValue
> aShadowGrabBag( 3 );
2918 Sequence
< PropertyValue
> aShadowAttribsGrabBag( 2 );
2920 double dX
= +0.0, dY
= +0.0;
2921 rXPropSet
->getPropertyValue( "ShadowXDistance" ) >>= dX
;
2922 rXPropSet
->getPropertyValue( "ShadowYDistance" ) >>= dY
;
2924 aShadowAttribsGrabBag
[0].Name
= "dist";
2925 aShadowAttribsGrabBag
[0].Value
= Any(static_cast< sal_Int32
>(sqrt(dX
*dX
+ dY
*dY
) * 360));
2926 aShadowAttribsGrabBag
[1].Name
= "dir";
2927 aShadowAttribsGrabBag
[1].Value
= Any(static_cast< sal_Int32
>(atan2(dY
,dX
) * 180 * 60000 / M_PI
));
2929 aShadowGrabBag
[0].Name
= "Attribs";
2930 aShadowGrabBag
[0].Value
= Any(aShadowAttribsGrabBag
);
2931 aShadowGrabBag
[1].Name
= "RgbClr";
2932 aShadowGrabBag
[1].Value
= rXPropSet
->getPropertyValue( "ShadowColor" );
2933 aShadowGrabBag
[2].Name
= "RgbClrTransparency";
2934 aShadowGrabBag
[2].Value
= rXPropSet
->getPropertyValue( "ShadowTransparence" );
2936 mpFS
->startElementNS(XML_a
, XML_effectLst
, FSEND
);
2937 WriteShapeEffect( "outerShdw", aShadowGrabBag
);
2938 mpFS
->endElementNS(XML_a
, XML_effectLst
);
2943 mpFS
->startElementNS(XML_a
, XML_effectLst
, FSEND
);
2945 for( sal_Int32 i
=0; i
< aEffects
.getLength(); ++i
)
2947 Sequence
< PropertyValue
> aEffectProps
;
2948 aEffects
[i
].Value
>>= aEffectProps
;
2949 WriteShapeEffect( aEffects
[i
].Name
, aEffectProps
);
2952 mpFS
->endElementNS(XML_a
, XML_effectLst
);
2955 void DrawingML::WriteShape3DEffects( Reference
< XPropertySet
> xPropSet
)
2957 // check existence of the grab bag
2958 if( !GetProperty( xPropSet
, "InteropGrabBag" ) )
2961 // extract the relevant properties from the grab bag
2962 Sequence
< PropertyValue
> aGrabBag
, aEffectProps
, aLightRigProps
, aShape3DProps
;
2964 for( sal_Int32 i
=0; i
< aGrabBag
.getLength(); ++i
)
2966 if( aGrabBag
[i
].Name
== "3DEffectProperties" )
2968 Sequence
< PropertyValue
> a3DEffectProps
;
2969 aGrabBag
[i
].Value
>>= a3DEffectProps
;
2970 for( sal_Int32 j
=0; j
< a3DEffectProps
.getLength(); ++j
)
2972 if( a3DEffectProps
[j
].Name
== "Camera" )
2973 a3DEffectProps
[j
].Value
>>= aEffectProps
;
2974 else if( a3DEffectProps
[j
].Name
== "LightRig" )
2975 a3DEffectProps
[j
].Value
>>= aLightRigProps
;
2976 else if( a3DEffectProps
[j
].Name
== "Shape3D" )
2977 a3DEffectProps
[j
].Value
>>= aShape3DProps
;
2982 if( aEffectProps
.getLength() == 0 && aLightRigProps
.getLength() == 0 && aShape3DProps
.getLength() == 0 )
2985 bool bCameraRotationPresent
= false;
2986 sax_fastparser::FastAttributeList
*aCameraAttrList
= FastSerializerHelper::createAttrList();
2987 sax_fastparser::XFastAttributeListRef
xCameraAttrList( aCameraAttrList
);
2988 sax_fastparser::FastAttributeList
*aCameraRotationAttrList
= FastSerializerHelper::createAttrList();
2989 sax_fastparser::XFastAttributeListRef
xRotAttrList( aCameraRotationAttrList
);
2990 for( sal_Int32 i
=0; i
< aEffectProps
.getLength(); ++i
)
2992 if( aEffectProps
[i
].Name
== "prst" )
2995 aEffectProps
[i
].Value
>>= sVal
;
2996 aCameraAttrList
->add( XML_prst
, OUStringToOString( sVal
, RTL_TEXTENCODING_UTF8
).getStr() );
2998 else if( aEffectProps
[i
].Name
== "fov" )
3001 aEffectProps
[i
].Value
>>= fVal
;
3002 aCameraAttrList
->add( XML_fov
, OString::number( fVal
* 60000 ).getStr() );
3004 else if( aEffectProps
[i
].Name
== "zoom" )
3007 aEffectProps
[i
].Value
>>= fVal
;
3008 aCameraAttrList
->add( XML_zoom
, OString::number( fVal
* 100000 ).getStr() );
3010 else if( aEffectProps
[i
].Name
== "rotLat" ||
3011 aEffectProps
[i
].Name
== "rotLon" ||
3012 aEffectProps
[i
].Name
== "rotRev" )
3014 sal_Int32 nVal
= 0, nToken
= XML_none
;
3015 aEffectProps
[i
].Value
>>= nVal
;
3016 if( aEffectProps
[i
].Name
== "rotLat" )
3018 else if( aEffectProps
[i
].Name
== "rotLon" )
3020 else if( aEffectProps
[i
].Name
== "rotRev" )
3022 aCameraRotationAttrList
->add( nToken
, OString::number( nVal
).getStr() );
3023 bCameraRotationPresent
= true;
3027 bool bLightRigRotationPresent
= false;
3028 sax_fastparser::FastAttributeList
*aLightRigAttrList
= FastSerializerHelper::createAttrList();
3029 sax_fastparser::XFastAttributeListRef
xLightAttrList( aLightRigAttrList
);
3030 sax_fastparser::FastAttributeList
*aLightRigRotationAttrList
= FastSerializerHelper::createAttrList();
3031 sax_fastparser::XFastAttributeListRef
xLightRotAttrList( aLightRigRotationAttrList
);
3032 for( sal_Int32 i
=0; i
< aLightRigProps
.getLength(); ++i
)
3034 if( aLightRigProps
[i
].Name
== "rig" || aLightRigProps
[i
].Name
== "dir" )
3037 sal_Int32 nToken
= XML_none
;
3038 aLightRigProps
[i
].Value
>>= sVal
;
3039 if( aLightRigProps
[i
].Name
== "rig" )
3041 else if( aLightRigProps
[i
].Name
== "dir" )
3043 aLightRigAttrList
->add( nToken
, OUStringToOString( sVal
, RTL_TEXTENCODING_UTF8
).getStr() );
3045 else if( aLightRigProps
[i
].Name
== "rotLat" ||
3046 aLightRigProps
[i
].Name
== "rotLon" ||
3047 aLightRigProps
[i
].Name
== "rotRev" )
3049 sal_Int32 nVal
= 0, nToken
= XML_none
;
3050 aLightRigProps
[i
].Value
>>= nVal
;
3051 if( aLightRigProps
[i
].Name
== "rotLat" )
3053 else if( aLightRigProps
[i
].Name
== "rotLon" )
3055 else if( aLightRigProps
[i
].Name
== "rotRev" )
3057 aLightRigRotationAttrList
->add( nToken
, OString::number( nVal
).getStr() );
3058 bLightRigRotationPresent
= true;
3062 mpFS
->startElementNS( XML_a
, XML_scene3d
, FSEND
);
3064 if( aEffectProps
.getLength() > 0 )
3066 mpFS
->startElementNS( XML_a
, XML_camera
, xCameraAttrList
);
3067 if( bCameraRotationPresent
)
3069 mpFS
->singleElementNS( XML_a
, XML_rot
, xRotAttrList
);
3071 mpFS
->endElementNS( XML_a
, XML_camera
);
3075 // a:camera with Word default values - Word won't open the document if this is not present
3076 mpFS
->singleElementNS( XML_a
, XML_camera
, XML_prst
, "orthographicFront", FSEND
);
3079 if( aEffectProps
.getLength() > 0 )
3081 mpFS
->startElementNS( XML_a
, XML_lightRig
, xLightAttrList
);
3082 if( bLightRigRotationPresent
)
3084 mpFS
->singleElementNS( XML_a
, XML_rot
, xLightRotAttrList
);
3086 mpFS
->endElementNS( XML_a
, XML_lightRig
);
3090 // a:lightRig with Word default values - Word won't open the document if this is not present
3091 mpFS
->singleElementNS( XML_a
, XML_lightRig
, XML_rig
, "threePt", XML_dir
, "t", FSEND
);
3094 mpFS
->endElementNS( XML_a
, XML_scene3d
);
3096 if( aShape3DProps
.getLength() == 0 )
3099 bool bBevelTPresent
= false, bBevelBPresent
= false;
3100 Sequence
< PropertyValue
> aExtrusionColorProps
, aContourColorProps
;
3101 sax_fastparser::FastAttributeList
*aBevelTAttrList
= FastSerializerHelper::createAttrList();
3102 sax_fastparser::XFastAttributeListRef
xBevelTAttrList( aBevelTAttrList
);
3103 sax_fastparser::FastAttributeList
*aBevelBAttrList
= FastSerializerHelper::createAttrList();
3104 sax_fastparser::XFastAttributeListRef
xBevelBAttrList( aBevelBAttrList
);
3105 sax_fastparser::FastAttributeList
*aShape3DAttrList
= FastSerializerHelper::createAttrList();
3106 for( sal_Int32 i
=0; i
< aShape3DProps
.getLength(); ++i
)
3108 if( aShape3DProps
[i
].Name
== "extrusionH" || aShape3DProps
[i
].Name
== "contourW" || aShape3DProps
[i
].Name
== "z" )
3110 sal_Int32 nVal
= 0, nToken
= XML_none
;
3111 aShape3DProps
[i
].Value
>>= nVal
;
3112 if( aShape3DProps
[i
].Name
== "extrusionH" )
3113 nToken
= XML_extrusionH
;
3114 else if( aShape3DProps
[i
].Name
== "contourW" )
3115 nToken
= XML_contourW
;
3116 else if( aShape3DProps
[i
].Name
== "z" )
3118 aShape3DAttrList
->add( nToken
, OString::number( nVal
).getStr() );
3120 else if( aShape3DProps
[i
].Name
== "prstMaterial" )
3123 aShape3DProps
[i
].Value
>>= sVal
;
3124 aShape3DAttrList
->add( XML_prstMaterial
, OUStringToOString( sVal
, RTL_TEXTENCODING_UTF8
).getStr() );
3126 else if( aShape3DProps
[i
].Name
== "extrusionClr" )
3128 aShape3DProps
[i
].Value
>>= aExtrusionColorProps
;
3130 else if( aShape3DProps
[i
].Name
== "contourClr" )
3132 aShape3DProps
[i
].Value
>>= aContourColorProps
;
3134 else if( aShape3DProps
[i
].Name
== "bevelT" || aShape3DProps
[i
].Name
== "bevelB" )
3136 Sequence
< PropertyValue
> aBevelProps
;
3137 aShape3DProps
[i
].Value
>>= aBevelProps
;
3138 if ( aBevelProps
.getLength() == 0 )
3141 sax_fastparser::FastAttributeList
*aBevelAttrList
= NULL
;
3142 if( aShape3DProps
[i
].Name
== "bevelT" )
3144 bBevelTPresent
= true;
3145 aBevelAttrList
= aBevelTAttrList
;
3149 bBevelBPresent
= true;
3150 aBevelAttrList
= aBevelBAttrList
;
3152 for( sal_Int32 j
=0; j
< aBevelProps
.getLength(); ++j
)
3154 if( aBevelProps
[j
].Name
== "w" || aBevelProps
[j
].Name
== "h" )
3156 sal_Int32 nVal
= 0, nToken
= XML_none
;
3157 aBevelProps
[j
].Value
>>= nVal
;
3158 if( aBevelProps
[j
].Name
== "w" )
3160 else if( aBevelProps
[j
].Name
== "h" )
3162 aBevelAttrList
->add( nToken
, OString::number( nVal
).getStr() );
3164 else if( aBevelProps
[j
].Name
== "prst" )
3167 aBevelProps
[j
].Value
>>= sVal
;
3168 aBevelAttrList
->add( XML_prst
, OUStringToOString( sVal
, RTL_TEXTENCODING_UTF8
).getStr() );
3175 sax_fastparser::XFastAttributeListRef
xAttrList( aShape3DAttrList
);
3176 mpFS
->startElementNS( XML_a
, XML_sp3d
, xAttrList
);
3177 if( bBevelTPresent
)
3179 mpFS
->singleElementNS( XML_a
, XML_bevelT
, xBevelTAttrList
);
3181 if( bBevelBPresent
)
3183 mpFS
->singleElementNS( XML_a
, XML_bevelB
, xBevelBAttrList
);
3185 if( aExtrusionColorProps
.getLength() > 0 )
3187 OUString sSchemeClr
;
3188 sal_Int32
nColor(0);
3189 sal_Int32
nTransparency(0);
3190 Sequence
< PropertyValue
> aColorTransformations
;
3191 for( sal_Int32 i
=0; i
< aExtrusionColorProps
.getLength(); ++i
)
3193 if( aExtrusionColorProps
[i
].Name
== "schemeClr" )
3194 aExtrusionColorProps
[i
].Value
>>= sSchemeClr
;
3195 else if( aExtrusionColorProps
[i
].Name
== "schemeClrTransformations" )
3196 aExtrusionColorProps
[i
].Value
>>= aColorTransformations
;
3197 else if( aExtrusionColorProps
[i
].Name
== "rgbClr" )
3198 aExtrusionColorProps
[i
].Value
>>= nColor
;
3199 else if( aExtrusionColorProps
[i
].Name
== "rgbClrTransparency" )
3200 aExtrusionColorProps
[i
].Value
>>= nTransparency
;
3202 mpFS
->startElementNS( XML_a
, XML_extrusionClr
, FSEND
);
3204 if( sSchemeClr
.isEmpty() )
3205 WriteColor( nColor
, MAX_PERCENT
- ( PER_PERCENT
* nTransparency
) );
3207 WriteColor( sSchemeClr
, aColorTransformations
);
3209 mpFS
->endElementNS( XML_a
, XML_extrusionClr
);
3211 if( aContourColorProps
.getLength() > 0 )
3213 OUString sSchemeClr
;
3214 sal_Int32
nColor(0);
3215 sal_Int32
nTransparency(0);
3216 Sequence
< PropertyValue
> aColorTransformations
;
3217 for( sal_Int32 i
=0; i
< aContourColorProps
.getLength(); ++i
)
3219 if( aContourColorProps
[i
].Name
== "schemeClr" )
3220 aContourColorProps
[i
].Value
>>= sSchemeClr
;
3221 else if( aContourColorProps
[i
].Name
== "schemeClrTransformations" )
3222 aContourColorProps
[i
].Value
>>= aColorTransformations
;
3223 else if( aContourColorProps
[i
].Name
== "rgbClr" )
3224 aContourColorProps
[i
].Value
>>= nColor
;
3225 else if( aContourColorProps
[i
].Name
== "rgbClrTransparency" )
3226 aContourColorProps
[i
].Value
>>= nTransparency
;
3228 mpFS
->startElementNS( XML_a
, XML_contourClr
, FSEND
);
3230 if( sSchemeClr
.isEmpty() )
3231 WriteColor( nColor
, MAX_PERCENT
- ( PER_PERCENT
* nTransparency
) );
3233 WriteColor( sSchemeClr
, aContourColorProps
);
3235 mpFS
->endElementNS( XML_a
, XML_contourClr
);
3237 mpFS
->endElementNS( XML_a
, XML_sp3d
);
3240 void DrawingML::WriteArtisticEffect( Reference
< XPropertySet
> rXPropSet
)
3242 if( !GetProperty( rXPropSet
, "InteropGrabBag" ) )
3245 PropertyValue aEffect
;
3246 Sequence
< PropertyValue
> aGrabBag
;
3248 for( sal_Int32 i
=0; i
< aGrabBag
.getLength(); ++i
)
3250 if( aGrabBag
[i
].Name
== "ArtisticEffectProperties" )
3252 aGrabBag
[i
].Value
>>= aEffect
;
3256 sal_Int32 nEffectToken
= ArtisticEffectProperties::getEffectToken( aEffect
.Name
);
3257 if( nEffectToken
== XML_none
)
3260 Sequence
< PropertyValue
> aAttrs
;
3261 aEffect
.Value
>>= aAttrs
;
3262 sax_fastparser::FastAttributeList
*aAttrList
= FastSerializerHelper::createAttrList();
3264 for( sal_Int32 i
=0; i
< aAttrs
.getLength(); ++i
)
3266 sal_Int32 nToken
= ArtisticEffectProperties::getEffectToken( aAttrs
[i
].Name
);
3267 if( nToken
!= XML_none
)
3270 aAttrs
[i
].Value
>>= nVal
;
3271 aAttrList
->add( nToken
, OString::number( nVal
).getStr() );
3273 else if( aAttrs
[i
].Name
== "OriginalGraphic" )
3275 Sequence
< PropertyValue
> aGraphic
;
3276 aAttrs
[i
].Value
>>= aGraphic
;
3277 Sequence
< sal_Int8
> aGraphicData
;
3278 OUString sGraphicId
;
3279 for( sal_Int32 j
=0; j
< aGraphic
.getLength(); ++j
)
3281 if( aGraphic
[j
].Name
== "Id" )
3282 aGraphic
[j
].Value
>>= sGraphicId
;
3283 else if( aGraphic
[j
].Name
== "Data" )
3284 aGraphic
[j
].Value
>>= aGraphicData
;
3286 sRelId
= WriteWdpPicture( sGraphicId
, aGraphicData
);
3290 mpFS
->startElementNS( XML_a
, XML_extLst
, FSEND
);
3291 mpFS
->startElementNS( XML_a
, XML_ext
,
3292 XML_uri
, "{BEBA8EAE-BF5A-486C-A8C5-ECC9F3942E4B}",
3294 mpFS
->startElementNS( XML_a14
, XML_imgProps
,
3295 FSNS( XML_xmlns
, XML_a14
), "http://schemas.microsoft.com/office/drawing/2010/main",
3297 mpFS
->startElementNS( XML_a14
, XML_imgLayer
,
3298 FSNS( XML_r
, XML_embed
), sRelId
.getStr(),
3300 mpFS
->startElementNS( XML_a14
, XML_imgEffect
, FSEND
);
3302 sax_fastparser::XFastAttributeListRef
xAttrList( aAttrList
);
3303 mpFS
->singleElementNS( XML_a14
, nEffectToken
, xAttrList
);
3305 mpFS
->endElementNS( XML_a14
, XML_imgEffect
);
3306 mpFS
->endElementNS( XML_a14
, XML_imgLayer
);
3307 mpFS
->endElementNS( XML_a14
, XML_imgProps
);
3308 mpFS
->endElementNS( XML_a
, XML_ext
);
3309 mpFS
->endElementNS( XML_a
, XML_extLst
);
3312 OString
DrawingML::WriteWdpPicture( const OUString
& rFileId
, const Sequence
< sal_Int8
>& rPictureData
)
3314 std::map
<OUString
, OUString
>::iterator aCachedItem
= maWdpCache
.find( rFileId
);
3315 if( aCachedItem
!= maWdpCache
.end() )
3316 return OUStringToOString( aCachedItem
->second
, RTL_TEXTENCODING_UTF8
);
3318 OUString sFileName
= "media/hdphoto" + OUString::number( mnWdpImageCounter
++ ) + ".wdp";
3319 uno::Reference
< io::XOutputStream
> xOutStream
=
3320 mpFB
->openFragmentStream( "word/" + sFileName
,
3321 "image/vnd.ms-photo" );
3323 xOutStream
->writeBytes( rPictureData
);
3324 xOutStream
->closeOutput();
3326 sId
= mpFB
->addRelation( mpFS
->getOutputStream(),
3327 "http://schemas.microsoft.com/office/2007/relationships/hdphoto",
3330 maWdpCache
[rFileId
] = sId
;
3331 return OUStringToOString( sId
, RTL_TEXTENCODING_UTF8
);
3337 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */