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 "oox/core/xmlfilterbase.hxx"
21 #include "oox/export/drawingml.hxx"
22 #include "oox/export/utils.hxx"
23 #include <oox/token/tokens.hxx>
26 #include <com/sun/star/awt/CharSet.hpp>
27 #include <com/sun/star/awt/FontDescriptor.hpp>
28 #include <com/sun/star/awt/FontSlant.hpp>
29 #include <com/sun/star/awt/FontWeight.hpp>
30 #include <com/sun/star/awt/FontUnderline.hpp>
31 #include <com/sun/star/awt/Gradient.hpp>
32 #include <com/sun/star/beans/XPropertySet.hpp>
33 #include <com/sun/star/beans/XPropertyState.hpp>
34 #include <com/sun/star/beans/Property.hpp>
35 #include <com/sun/star/beans/XPropertySetInfo.hpp>
36 #include <com/sun/star/container/XEnumerationAccess.hpp>
37 #include <com/sun/star/container/XIndexAccess.hpp>
38 #include <com/sun/star/drawing/BitmapMode.hpp>
39 #include <com/sun/star/drawing/EnhancedCustomShapeAdjustmentValue.hpp>
40 #include <com/sun/star/drawing/LineDash.hpp>
41 #include <com/sun/star/drawing/LineJoint.hpp>
42 #include <com/sun/star/drawing/LineStyle.hpp>
43 #include <com/sun/star/drawing/TextHorizontalAdjust.hpp>
44 #include <com/sun/star/drawing/TextVerticalAdjust.hpp>
45 #include <com/sun/star/drawing/XShape.hpp>
46 #include <com/sun/star/drawing/FillStyle.hpp>
47 #include <com/sun/star/geometry/IntegerRectangle2D.hpp>
48 #include <com/sun/star/i18n/ScriptType.hpp>
49 #include <com/sun/star/io/XOutputStream.hpp>
50 #include <com/sun/star/style/LineSpacing.hpp>
51 #include <com/sun/star/style/LineSpacingMode.hpp>
52 #include <com/sun/star/style/ParagraphAdjust.hpp>
53 #include <com/sun/star/text/WritingMode.hpp>
54 #include <com/sun/star/text/GraphicCrop.hpp>
55 #include <com/sun/star/text/XText.hpp>
56 #include <com/sun/star/text/XTextContent.hpp>
57 #include <com/sun/star/text/XTextField.hpp>
58 #include <com/sun/star/text/XTextRange.hpp>
59 #include <tools/stream.hxx>
60 #include <tools/string.hxx>
61 #include <unotools/fontdefs.hxx>
62 #include <vcl/cvtgrf.hxx>
63 #include <vcl/graph.hxx>
64 #include <svtools/grfmgr.hxx>
65 #include <rtl/strbuf.hxx>
66 #include <sfx2/app.hxx>
67 #include <svl/languageoptions.hxx>
68 #include <filter/msfilter/escherex.hxx>
69 #include <filter/msfilter/util.hxx>
70 #include <editeng/svxenum.hxx>
71 #include <svx/unoapi.hxx>
72 #include <svx/svdoashp.hxx>
74 using namespace ::com::sun::star
;
75 using namespace ::com::sun::star::beans
;
76 using namespace ::com::sun::star::drawing
;
77 using namespace ::com::sun::star::i18n
;
78 using namespace ::com::sun::star::style
;
79 using namespace ::com::sun::star::text
;
80 using namespace ::com::sun::star::uno
;
81 using ::com::sun::star::beans::PropertyState
;
82 using ::com::sun::star::beans::PropertyValue
;
83 using ::com::sun::star::beans::XPropertySet
;
84 using ::com::sun::star::beans::XPropertyState
;
85 using ::com::sun::star::container::XEnumeration
;
86 using ::com::sun::star::container::XEnumerationAccess
;
87 using ::com::sun::star::container::XIndexAccess
;
88 using ::com::sun::star::geometry::IntegerRectangle2D
;
89 using ::com::sun::star::io::XOutputStream
;
90 using ::com::sun::star::style::LineSpacing
;
91 using ::com::sun::star::text::XText
;
92 using ::com::sun::star::text::XTextContent
;
93 using ::com::sun::star::text::XTextField
;
94 using ::com::sun::star::text::XTextRange
;
95 using ::sax_fastparser::FSHelperPtr
;
97 DBG(extern void dump_pset(Reference
< XPropertySet
> rXPropSet
));
100 namespace drawingml
{
102 #define GETA(propName) \
103 GetProperty( rXPropSet, String( #propName ) )
105 #define GETAD(propName) \
106 ( GetPropertyAndState( rXPropSet, rXPropState, String( #propName ), eState ) && eState == beans::PropertyState_DIRECT_VALUE )
108 #define GET(variable, propName) \
109 if ( GETA(propName) ) \
113 int DrawingML::mnImageCounter
= 1;
115 void DrawingML::ResetCounters()
120 bool DrawingML::GetProperty( Reference
< XPropertySet
> rXPropSet
, OUString aName
)
122 bool bRetValue
= false;
125 mAny
= rXPropSet
->getPropertyValue( aName
);
126 if ( mAny
.hasValue() )
128 } catch( const Exception
& ) { /* printf ("exception when trying to get value of property: %s\n", USS(aName)); */ }
133 bool DrawingML::GetPropertyAndState( Reference
< XPropertySet
> rXPropSet
, Reference
< XPropertyState
> rXPropState
, String aName
, PropertyState
& eState
)
135 bool bRetValue
= false;
138 mAny
= rXPropSet
->getPropertyValue( aName
);
139 if ( mAny
.hasValue() ) {
141 eState
= rXPropState
->getPropertyState( aName
);
143 } catch( const Exception
& ) { /* printf ("exception when trying to get value of property: %s\n", USS(aName)); */ }
148 void DrawingML::WriteColor( sal_uInt32 nColor
)
150 OString sColor
= OString::valueOf( ( sal_Int64
) nColor
, 16 );
151 if( sColor
.getLength() < 6 ) {
152 OStringBuffer
sBuf( "0" );
153 int remains
= 5 - sColor
.getLength();
155 while( remains
> 0 ) {
160 sBuf
.append( sColor
);
162 sColor
= sBuf
.getStr();
164 mpFS
->singleElementNS( XML_a
, XML_srgbClr
, XML_val
, sColor
.getStr(), FSEND
);
167 void DrawingML::WriteSolidFill( sal_uInt32 nColor
)
169 mpFS
->startElementNS( XML_a
, XML_solidFill
, FSEND
);
170 WriteColor( nColor
);
171 mpFS
->endElementNS( XML_a
, XML_solidFill
);
174 void DrawingML::WriteSolidFill( Reference
< XPropertySet
> rXPropSet
)
176 if ( GetProperty( rXPropSet
, "FillColor" ) )
177 WriteSolidFill( *((sal_uInt32
*) mAny
.getValue()) & 0xffffff );
180 void DrawingML::WriteGradientStop( sal_uInt16 nStop
, sal_uInt32 nColor
)
182 mpFS
->startElementNS( XML_a
, XML_gs
,
183 XML_pos
, I32S( nStop
* 1000 ),
185 WriteColor( nColor
);
186 mpFS
->endElementNS( XML_a
, XML_gs
);
189 sal_uInt32
DrawingML::ColorWithIntensity( sal_uInt32 nColor
, sal_uInt32 nIntensity
)
191 return ( ( ( nColor
& 0xff ) * nIntensity
) / 100 )
192 | ( ( ( ( ( nColor
& 0xff00 ) >> 8 ) * nIntensity
) / 100 ) << 8 )
193 | ( ( ( ( ( nColor
& 0xff0000 ) >> 8 ) * nIntensity
) / 100 ) << 8 );
196 void DrawingML::WriteGradientFill( Reference
< XPropertySet
> rXPropSet
)
198 awt::Gradient aGradient
;
199 if( GETA( FillGradient
) ) {
200 aGradient
= *static_cast< const awt::Gradient
* >( mAny
.getValue() );
202 mpFS
->startElementNS( XML_a
, XML_gradFill
, FSEND
);
204 switch( aGradient
.Style
) {
206 case GradientStyle_LINEAR
:
207 mpFS
->startElementNS( XML_a
, XML_gsLst
, FSEND
);
208 WriteGradientStop( 0, ColorWithIntensity( aGradient
.StartColor
, aGradient
.StartIntensity
) );
209 WriteGradientStop( 100, ColorWithIntensity( aGradient
.EndColor
, aGradient
.EndIntensity
) );
210 mpFS
->endElementNS( XML_a
, XML_gsLst
);
211 mpFS
->singleElementNS( XML_a
, XML_lin
,
212 XML_ang
, I32S( ( ( ( 3600 - aGradient
.Angle
+ 900 ) * 6000 ) % 21600000 ) ),
216 case GradientStyle_AXIAL
:
217 mpFS
->startElementNS( XML_a
, XML_gsLst
, FSEND
);
218 WriteGradientStop( 0, ColorWithIntensity( aGradient
.EndColor
, aGradient
.EndIntensity
) );
219 WriteGradientStop( 50, ColorWithIntensity( aGradient
.StartColor
, aGradient
.StartIntensity
) );
220 WriteGradientStop( 100, ColorWithIntensity( aGradient
.EndColor
, aGradient
.EndIntensity
) );
221 mpFS
->endElementNS( XML_a
, XML_gsLst
);
222 mpFS
->singleElementNS( XML_a
, XML_lin
,
223 XML_ang
, I32S( ( ( ( 3600 - aGradient
.Angle
+ 900 ) * 6000 ) % 21600000 ) ),
227 /* I don't see how to apply transformation to gradients, so
228 * elliptical will end as radial and square as
229 * rectangular. also position offsets are not applied */
230 case GradientStyle_RADIAL
:
231 case GradientStyle_ELLIPTICAL
:
232 case GradientStyle_RECT
:
233 case GradientStyle_SQUARE
:
234 mpFS
->startElementNS( XML_a
, XML_gsLst
, FSEND
);
235 WriteGradientStop( 0, ColorWithIntensity( aGradient
.EndColor
, aGradient
.EndIntensity
) );
236 WriteGradientStop( 100, ColorWithIntensity( aGradient
.StartColor
, aGradient
.StartIntensity
) );
237 mpFS
->endElementNS( XML_a
, XML_gsLst
);
238 mpFS
->singleElementNS( XML_a
, XML_path
,
239 XML_path
, ( aGradient
.Style
== awt::GradientStyle_RADIAL
|| aGradient
.Style
== awt::GradientStyle_ELLIPTICAL
) ? "circle" : "rect",
244 mpFS
->endElementNS( XML_a
, XML_gradFill
);
249 void DrawingML::WriteLineArrow( Reference
< XPropertySet
> rXPropSet
, sal_Bool bLineStart
)
251 ESCHER_LineEnd eLineEnd
;
252 sal_Int32 nArrowLength
;
253 sal_Int32 nArrowWidth
;
255 if ( EscherPropertyContainer::GetLineArrow( bLineStart
, rXPropSet
, eLineEnd
, nArrowLength
, nArrowWidth
) ) {
260 switch( nArrowLength
) {
261 case ESCHER_LineShortArrow
:
265 case ESCHER_LineMediumLenArrow
:
268 case ESCHER_LineLongArrow
:
275 case ESCHER_LineNoEnd
:
278 case ESCHER_LineArrowEnd
:
281 case ESCHER_LineArrowStealthEnd
:
284 case ESCHER_LineArrowDiamondEnd
:
287 case ESCHER_LineArrowOvalEnd
:
290 case ESCHER_LineArrowOpenEnd
:
295 switch( nArrowWidth
) {
296 case ESCHER_LineNarrowArrow
:
300 case ESCHER_LineMediumWidthArrow
:
303 case ESCHER_LineWideArrow
:
308 mpFS
->singleElementNS( XML_a
, bLineStart
? XML_headEnd
: XML_tailEnd
,
316 void DrawingML::WriteOutline( Reference
< XPropertySet
> rXPropSet
)
318 drawing::LineStyle
aLineStyle( drawing::LineStyle_NONE
);
320 GET( aLineStyle
, LineStyle
);
322 sal_uInt32 nLineWidth
= 0;
323 sal_uInt32 nColor
= 0;
324 sal_Bool bColorSet
= sal_False
;
325 const char* cap
= NULL
;
326 drawing::LineDash aLineDash
;
327 sal_Bool bDashSet
= sal_False
;
328 bool bNoFill
= false;
330 GET( nLineWidth
, LineWidth
);
332 switch( aLineStyle
) {
333 case drawing::LineStyle_NONE
:
336 case drawing::LineStyle_DASH
:
337 if( GETA( LineDash
) ) {
338 aLineDash
= *(drawing::LineDash
*) mAny
.getValue();
340 if( aLineDash
.Style
== DashStyle_ROUND
|| aLineDash
.Style
== DashStyle_ROUNDRELATIVE
)
343 DBG(printf("dash dots: %d dashes: %d dotlen: %d dashlen: %d distance: %d\n",
344 int( aLineDash
.Dots
), int( aLineDash
.Dashes
), int( aLineDash
.DotLen
), int( aLineDash
.DashLen
), int( aLineDash
.Distance
)));
346 /* fallthru intended */
347 case drawing::LineStyle_SOLID
:
349 if ( GETA( LineColor
) ) {
350 nColor
= *((sal_uInt32
*) mAny
.getValue()) & 0xffffff;
351 bColorSet
= sal_True
;
356 mpFS
->startElementNS( XML_a
, XML_ln
,
358 XML_w
, nLineWidth
> 1 ? I64S( MM100toEMU( nLineWidth
) ) : NULL
,
361 WriteSolidFill( nColor
);
364 mpFS
->startElementNS( XML_a
, XML_custDash
, FSEND
);
366 for( i
= 0; i
< aLineDash
.Dots
; i
++ )
367 mpFS
->singleElementNS( XML_a
, XML_ds
,
368 XML_d
, aLineDash
.DotLen
? I64S( aLineDash
.DotLen
*1000 ) : "100000",
369 XML_sp
, I64S( aLineDash
.Distance
*1000 ),
371 for( i
= 0; i
< aLineDash
.Dashes
; i
++ )
372 mpFS
->singleElementNS( XML_a
, XML_ds
,
373 XML_d
, aLineDash
.DashLen
? I64S( aLineDash
.DashLen
*1000 ) : "100000",
374 XML_sp
, I64S( aLineDash
.Distance
*1000 ),
376 mpFS
->endElementNS( XML_a
, XML_custDash
);
379 if( !bNoFill
&& nLineWidth
> 1 && GETA( LineJoint
) ) {
380 LineJoint eLineJoint
;
383 switch( eLineJoint
) {
385 case LineJoint_MIDDLE
:
386 case LineJoint_BEVEL
:
387 mpFS
->singleElementNS( XML_a
, XML_bevel
, FSEND
);
390 case LineJoint_MITER
:
391 mpFS
->singleElementNS( XML_a
, XML_miter
, FSEND
);
393 case LineJoint_ROUND
:
394 mpFS
->singleElementNS( XML_a
, XML_round
, FSEND
);
401 WriteLineArrow( rXPropSet
, sal_True
);
402 WriteLineArrow( rXPropSet
, sal_False
);
406 mpFS
->singleElementNS( XML_a
, XML_noFill
, FSEND
);
409 mpFS
->endElementNS( XML_a
, XML_ln
);
412 OUString
DrawingML::WriteImage( const OUString
& rURL
)
414 OString
aURLBS(OUStringToOString(rURL
, RTL_TEXTENCODING_UTF8
));
416 const char aURLBegin
[] = "vnd.sun.star.GraphicObject:";
417 sal_Int32 index
= aURLBS
.indexOf(aURLBegin
);
421 DBG(printf ("begin: %ld %s\n", long( sizeof( aURLBegin
) ), USS( rURL
) + RTL_CONSTASCII_LENGTH( aURLBegin
) ));
422 Graphic aGraphic
= GraphicObject( aURLBS
.copy(RTL_CONSTASCII_LENGTH(aURLBegin
)) ).GetTransformedGraphic ();
424 return WriteImage( aGraphic
);
426 // add link to relations
432 const char* DrawingML::GetComponentDir()
434 switch ( meDocumentType
)
436 case DOCUMENT_DOCX
: return "word";
437 case DOCUMENT_PPTX
: return "ppt";
438 case DOCUMENT_XLSX
: return "xl";
444 const char* DrawingML::GetRelationCompPrefix()
446 switch ( meDocumentType
)
448 case DOCUMENT_DOCX
: return "";
450 case DOCUMENT_XLSX
: return "../";
456 OUString
DrawingML::WriteImage( const Graphic
& rGraphic
)
458 GfxLink aLink
= rGraphic
.GetLink ();
460 const char* pExtension
= "";
463 SvMemoryStream aStream
;
464 const void* aData
= aLink
.GetData();
465 sal_Size nDataSize
= aLink
.GetDataSize();
467 switch ( aLink
.GetType() ) {
468 case GFX_LINK_TYPE_NATIVE_GIF
:
469 sMediaType
= "image/gif";
472 case GFX_LINK_TYPE_NATIVE_JPG
:
473 sMediaType
= "image/jpeg";
474 pExtension
= ".jpeg";
476 case GFX_LINK_TYPE_NATIVE_PNG
:
477 sMediaType
= "image/png";
480 case GFX_LINK_TYPE_NATIVE_TIF
:
481 sMediaType
= "image/tiff";
482 pExtension
= ".tiff";
484 case GFX_LINK_TYPE_NATIVE_WMF
:
485 sMediaType
= "image/x-wmf";
488 case GFX_LINK_TYPE_NATIVE_MET
:
489 sMediaType
= "image/x-met";
492 case GFX_LINK_TYPE_NATIVE_PCT
:
493 sMediaType
= "image/x-pict";
497 GraphicType aType
= rGraphic
.GetType();
498 if ( aType
== GRAPHIC_BITMAP
) {
499 GraphicConverter::Export( aStream
, rGraphic
, CVT_PNG
);
500 sMediaType
= "image/png";
502 } else if ( aType
== GRAPHIC_GDIMETAFILE
) {
503 GraphicConverter::Export( aStream
, rGraphic
, CVT_EMF
);
504 sMediaType
= "image/x-emf";
507 OSL_TRACE( "unhandled graphic type" );
511 aData
= aStream
.GetData();
512 nDataSize
= aStream
.GetEndOfData();
517 Reference
< XOutputStream
> xOutStream
= mpFB
->openFragmentStream( OUStringBuffer()
518 .appendAscii( GetComponentDir() )
519 .appendAscii( "/media/image" )
520 .append( (sal_Int32
) mnImageCounter
)
521 .appendAscii( pExtension
)
522 .makeStringAndClear(),
524 xOutStream
->writeBytes( Sequence
< sal_Int8
>( (const sal_Int8
*) aData
, nDataSize
) );
525 xOutStream
->closeOutput();
527 sRelId
= mpFB
->addRelation( mpFS
->getOutputStream(),
528 "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",
530 .appendAscii( GetRelationCompPrefix() )
531 .appendAscii( "media/image" )
532 .append( (sal_Int32
) mnImageCounter
++ )
533 .appendAscii( pExtension
)
534 .makeStringAndClear() );
539 OUString
DrawingML::WriteBlip( Reference
< XPropertySet
> rXPropSet
, OUString
& rURL
, const Graphic
*pGraphic
)
541 OUString sRelId
= pGraphic
? WriteImage( *pGraphic
) : WriteImage( rURL
);
542 sal_Int16 nBright
= 0;
543 sal_Int32 nContrast
= 0;
545 GET( nBright
, AdjustLuminance
);
546 GET( nContrast
, AdjustContrast
);
548 mpFS
->startElementNS( XML_a
, XML_blip
,
549 FSNS( XML_r
, XML_embed
), OUStringToOString( sRelId
, RTL_TEXTENCODING_UTF8
).getStr(),
551 if( nBright
|| nContrast
)
552 mpFS
->singleElementNS( XML_a
, XML_lum
,
553 XML_bright
, nBright
? I32S( nBright
*1000 ) : NULL
,
554 XML_contrast
, nContrast
? I32S( nContrast
*1000 ) : NULL
,
557 mpFS
->endElementNS( XML_a
, XML_blip
);
562 void DrawingML::WriteBlipMode( Reference
< XPropertySet
> rXPropSet
)
564 BitmapMode
eBitmapMode( BitmapMode_NO_REPEAT
);
565 if (GetProperty( rXPropSet
, "FillBitmapMode" ) )
566 mAny
>>= eBitmapMode
;
568 DBG(printf("fill bitmap mode: %d\n", eBitmapMode
));
570 switch (eBitmapMode
) {
571 case BitmapMode_REPEAT
:
572 mpFS
->singleElementNS( XML_a
, XML_tile
, FSEND
);
574 case BitmapMode_STRETCH
:
575 mpFS
->startElementNS( XML_a
, XML_stretch
, FSEND
);
576 mpFS
->singleElementNS( XML_a
, XML_fillRect
, FSEND
);
577 mpFS
->endElementNS( XML_a
, XML_stretch
);
584 void DrawingML::WriteBlipFill( Reference
< XPropertySet
> rXPropSet
, OUString sURLPropName
)
586 WriteBlipFill( rXPropSet
, sURLPropName
, XML_a
);
589 void DrawingML::WriteBlipFill( Reference
< XPropertySet
> rXPropSet
, OUString sURLPropName
, sal_Int32 nXmlNamespace
)
591 if ( GetProperty( rXPropSet
, sURLPropName
) ) {
595 DBG(printf ("URL: %s\n", OUStringToOString( aURL
, RTL_TEXTENCODING_UTF8
).getStr() ));
600 mpFS
->startElementNS( nXmlNamespace
, XML_blipFill
, FSEND
);
602 WriteBlip( rXPropSet
, aURL
);
604 if( sURLPropName
== "FillBitmapURL" )
605 WriteBlipMode( rXPropSet
);
606 else if( GetProperty( rXPropSet
, "FillBitmapStretch" ) ) {
607 bool bStretch
= false;
614 mpFS
->endElementNS( nXmlNamespace
, XML_blipFill
);
618 void DrawingML::WriteSrcRect( Reference
< XPropertySet
> rXPropSet
, const OUString
& rURL
)
620 Size
aOriginalSize( GraphicObject::CreateGraphicObjectFromURL( rURL
).GetPrefSize() );
622 if ( GetProperty( rXPropSet
, "GraphicCrop" ) )
624 ::com::sun::star::text::GraphicCrop aGraphicCropStruct
;
625 mAny
>>= aGraphicCropStruct
;
627 if ( (0 != aGraphicCropStruct
.Left
) || (0 != aGraphicCropStruct
.Top
) || (0 != aGraphicCropStruct
.Right
) || (0 != aGraphicCropStruct
.Bottom
) )
629 mpFS
->singleElementNS( XML_a
, XML_srcRect
,
630 XML_l
, I32S(((aGraphicCropStruct
.Left
) * 100000)/aOriginalSize
.Width()),
631 XML_t
, I32S(((aGraphicCropStruct
.Top
) * 100000)/aOriginalSize
.Height()),
632 XML_r
, I32S(((aGraphicCropStruct
.Right
) * 100000)/aOriginalSize
.Width()),
633 XML_b
, I32S(((aGraphicCropStruct
.Bottom
) * 100000)/aOriginalSize
.Height()),
639 void DrawingML::WriteStretch()
641 mpFS
->startElementNS( XML_a
, XML_stretch
, FSEND
);
642 mpFS
->singleElementNS( XML_a
, XML_fillRect
, FSEND
);
643 mpFS
->endElementNS( XML_a
, XML_stretch
);
646 void DrawingML::WriteTransformation( const Rectangle
& rRect
,
647 sal_Int32 nXmlNamespace
, sal_Bool bFlipH
, sal_Bool bFlipV
, sal_Int32 nRotation
)
649 mpFS
->startElementNS( nXmlNamespace
, XML_xfrm
,
650 XML_flipH
, bFlipH
? "1" : NULL
,
651 XML_flipV
, bFlipV
? "1" : NULL
,
652 XML_rot
, (nRotation
% 21600000) ? I32S( nRotation
) : NULL
,
655 mpFS
->singleElementNS( XML_a
, XML_off
, XML_x
, IS( MM100toEMU( rRect
.Left() ) ), XML_y
, IS( MM100toEMU( rRect
.Top() ) ), FSEND
);
656 mpFS
->singleElementNS( XML_a
, XML_ext
, XML_cx
, IS( MM100toEMU( rRect
.GetWidth() ) ), XML_cy
, IS( MM100toEMU( rRect
.GetHeight() ) ), FSEND
);
658 mpFS
->endElementNS( nXmlNamespace
, XML_xfrm
);
661 void DrawingML::WriteShapeTransformation( Reference
< XShape
> rXShape
, sal_Int32 nXmlNamespace
, sal_Bool bFlipH
, sal_Bool bFlipV
, sal_Bool bSuppressRotation
)
663 DBG(printf( "write shape transformation\n" ));
665 sal_Int32 nRotation
=0;
666 awt::Point aPos
= rXShape
->getPosition();
667 awt::Size aSize
= rXShape
->getSize();
669 if ( aSize
.Width
< 0 )
671 if ( aSize
.Height
< 0 )
673 if (!bSuppressRotation
)
675 SdrObject
* pShape
= (SdrObject
*) GetSdrObjectFromXShape( rXShape
);
676 nRotation
=pShape
->GetRotateAngle();
677 int faccos
=bFlipV
? -1 : 1;
678 int facsin
=bFlipH
? -1 : 1;
679 aPos
.X
-=(1-faccos
*cos(nRotation
*F_PI18000
))*aSize
.Width
/2-facsin
*sin(nRotation
*F_PI18000
)*aSize
.Height
/2;
680 aPos
.Y
-=(1-faccos
*cos(nRotation
*F_PI18000
))*aSize
.Height
/2+facsin
*sin(nRotation
*F_PI18000
)*aSize
.Width
/2;
682 if (!bSuppressRotation
)
684 if (bFlipV
) {nRotation
=(nRotation
+18000)%36000;}
686 WriteTransformation( Rectangle( Point( aPos
.X
, aPos
.Y
), Size( aSize
.Width
, aSize
.Height
) ), nXmlNamespace
, bFlipH
, bFlipV
, PPTX_EXPORT_ROTATE_CLOCKWISIFY(nRotation
) );
689 void DrawingML::WriteRunProperties( Reference
< XPropertySet
> rRun
, sal_Bool bIsField
)
691 Reference
< XPropertySet
> rXPropSet( rRun
, UNO_QUERY
);
692 Reference
< XPropertyState
> rXPropState( rRun
, UNO_QUERY
);
694 PropertyState eState
;
695 sal_Int16 nScriptType
= SvtLanguageOptions::GetScriptTypeOfLanguage( Application::GetSettings().GetLanguageTag().getLanguageType() );
696 sal_Bool bComplex
= ( nScriptType
== ScriptType::COMPLEX
);
697 const char* bold
= NULL
;
698 const char* italic
= NULL
;
699 const char* underline
= NULL
;
700 sal_Int32 nSize
= 1800;
701 sal_Int32 nCharEscapement
= 0;
703 if( GETAD( CharHeight
) )
704 nSize
= (sal_Int32
) (100*(*((float*) mAny
.getValue())));
706 if ( ( bComplex
&& GETAD( CharWeightComplex
) ) || GETAD( CharWeight
) )
707 if ( *((float*) mAny
.getValue()) >= awt::FontWeight::SEMIBOLD
)
710 if ( ( bComplex
&& GETAD( CharPostureComplex
) ) || GETAD( CharPosture
) )
711 switch ( *((awt::FontSlant
*) mAny
.getValue()) )
713 case awt::FontSlant_OBLIQUE
:
714 case awt::FontSlant_ITALIC
:
721 if ( GETAD( CharUnderline
) )
722 switch ( *((sal_Int16
*) mAny
.getValue()) )
724 case awt::FontUnderline::SINGLE
:
727 case awt::FontUnderline::DOUBLE
:
730 case awt::FontUnderline::DOTTED
:
731 underline
= "dotted";
733 case awt::FontUnderline::DASH
:
736 case awt::FontUnderline::LONGDASH
:
737 underline
= "dashLong";
739 case awt::FontUnderline::DASHDOT
:
740 underline
= "dotDash";
742 case awt::FontUnderline::DASHDOTDOT
:
743 underline
= "dotDotDash";
745 case awt::FontUnderline::WAVE
:
748 case awt::FontUnderline::DOUBLEWAVE
:
749 underline
= "wavyDbl";
751 case awt::FontUnderline::BOLD
:
754 case awt::FontUnderline::BOLDDOTTED
:
755 underline
= "dottedHeavy";
757 case awt::FontUnderline::BOLDDASH
:
758 underline
= "dashHeavy";
760 case awt::FontUnderline::BOLDLONGDASH
:
761 underline
= "dashLongHeavy";
763 case awt::FontUnderline::BOLDDASHDOT
:
764 underline
= "dotDashHeavy";
766 case awt::FontUnderline::BOLDDASHDOTDOT
:
767 underline
= "dotDotDashHeavy";
769 case awt::FontUnderline::BOLDWAVE
:
770 underline
= "wavyHeavy";
774 if( GETA( CharLocale
) ) {
775 com::sun::star::lang::Locale eLocale
;
778 OUStringBuffer usLanguageBuffer
= eLocale
.Language
;
779 if( !eLocale
.Country
.isEmpty() ) {
780 usLanguageBuffer
.appendAscii( "-" );
781 usLanguageBuffer
.append( eLocale
.Country
);
784 if( usLanguageBuffer
.getLength() )
785 usLanguage
= usLanguageBuffer
.makeStringAndClear();
788 if( GETAD( CharEscapement
) )
789 mAny
>>= nCharEscapement
;
791 if( nCharEscapement
&& GETAD( CharEscapementHeight
) ) {
792 sal_uInt32 nCharEscapementHeight
= 0;
793 mAny
>>= nCharEscapementHeight
;
794 nSize
= (nSize
* nCharEscapementHeight
) / 100;
795 // MSO uses default ~58% size
796 nSize
= (nSize
/ 0.58);
799 mpFS
->startElementNS( XML_a
, XML_rPr
,
802 XML_lang
, usLanguage
.isEmpty() ? NULL
: USS( usLanguage
),
803 XML_sz
, nSize
== 1800 ? NULL
: IS( nSize
),
805 XML_baseline
, nCharEscapement
== 0 ? NULL
: IS( nCharEscapement
*1000 ),
808 // mso doesn't like text color to be placed after typeface
809 if( GETAD( CharColor
) ) {
810 sal_uInt32 color
= *((sal_uInt32
*) mAny
.getValue());
811 DBG(printf("run color: %x auto: %x\n", static_cast<unsigned int>( color
), static_cast<unsigned int>( COL_AUTO
)));
813 if( color
== COL_AUTO
) { // nCharColor depends to the background color
814 sal_Bool bIsDark
= sal_False
;
815 GET( bIsDark
, IsBackgroundDark
);
816 color
= bIsDark
? 0xffffff : 0x000000;
820 // TODO: special handle embossed/engraved
822 WriteSolidFill( color
);
825 if( GETAD( CharFontName
) ) {
826 const char* pitch
= NULL
;
827 const char* charset
= NULL
;
831 OUString
aSubstName( GetSubsFontName( usTypeface
, SUBSFONT_ONLYONE
| SUBSFONT_MS
) );
833 mpFS
->singleElementNS( XML_a
, XML_latin
,
834 XML_typeface
, USS(aSubstName
.getLength() ? aSubstName
: usTypeface
),
835 XML_pitchFamily
, pitch
,
836 XML_charset
, charset
,
840 if( ( bComplex
&& GETAD( CharFontNameComplex
) ) || ( !bComplex
&& GETAD( CharFontNameAsian
) ) ) {
841 const char* pitch
= NULL
;
842 const char* charset
= NULL
;
846 OUString
aSubstName( GetSubsFontName( usTypeface
, SUBSFONT_ONLYONE
| SUBSFONT_MS
) );
848 mpFS
->singleElementNS( XML_a
, bComplex
? XML_cs
: XML_ea
,
849 XML_typeface
, USS(aSubstName
.getLength() ? aSubstName
: usTypeface
),
850 XML_pitchFamily
, pitch
,
851 XML_charset
, charset
,
856 Reference
< XTextField
> rXTextField
;
857 GET( rXTextField
, TextField
);
858 if( rXTextField
.is() )
859 rXPropSet
.set( rXTextField
, UNO_QUERY
);
862 // field properties starts here
867 if( !sURL
.isEmpty() ) {
868 OUString sRelId
= mpFB
->addRelation( mpFS
->getOutputStream(),
869 "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink",
872 mpFS
->singleElementNS( XML_a
, XML_hlinkClick
,
873 FSNS( XML_r
,XML_id
), USS( sRelId
),
878 mpFS
->endElementNS( XML_a
, XML_rPr
);
881 const char* DrawingML::GetFieldType( ::com::sun::star::uno::Reference
< ::com::sun::star::text::XTextRange
> rRun
, sal_Bool
& bIsField
)
883 const char* sType
= NULL
;
884 Reference
< XPropertySet
> rXPropSet( rRun
, UNO_QUERY
);
887 if( GETA( TextPortionType
) ) {
888 aFieldType
= OUString( *(OUString
*)mAny
.getValue() );
889 DBG(printf ("field type: %s\n", USS(aFieldType
) ));
892 if( aFieldType
== "TextField" ) {
893 Reference
< XTextField
> rXTextField
;
894 GET( rXTextField
, TextField
);
895 if( rXTextField
.is() ) {
897 rXPropSet
.set( rXTextField
, UNO_QUERY
);
898 if( rXPropSet
.is() ) {
899 OUString
aFieldKind( rXTextField
->getPresentation( sal_True
) );
900 DBG(printf ("field kind: %s\n", USS(aFieldKind
) ));
901 if( aFieldKind
== "Page" ) {
904 // else if( aFieldKind == "URL" ) {
905 // do not return here
906 // and make URL field text run with hyperlink property later
915 void DrawingML::GetUUID( OStringBuffer
& rBuffer
)
917 Sequence
< sal_uInt8
> aSeq( 16 );
918 static char cDigits
[17] = "0123456789ABCDEF";
919 rtl_createUuid( (sal_uInt8
*)aSeq
.getArray(), 0, sal_True
);
922 rBuffer
.append( '{' );
923 for( i
= 0; i
< 4; i
++ ) {
924 rBuffer
.append( cDigits
[ aSeq
[i
] >> 4 ] );
925 rBuffer
.append( cDigits
[ aSeq
[i
] & 0xf ] );
927 rBuffer
.append( '-' );
928 for( ; i
< 6; i
++ ) {
929 rBuffer
.append( cDigits
[ aSeq
[i
] >> 4 ] );
930 rBuffer
.append( cDigits
[ aSeq
[i
] & 0xf ] );
932 rBuffer
.append( '-' );
933 for( ; i
< 8; i
++ ) {
934 rBuffer
.append( cDigits
[ aSeq
[i
] >> 4 ] );
935 rBuffer
.append( cDigits
[ aSeq
[i
] & 0xf ] );
937 rBuffer
.append( '-' );
938 for( ; i
< 10; i
++ ) {
939 rBuffer
.append( cDigits
[ aSeq
[i
] >> 4 ] );
940 rBuffer
.append( cDigits
[ aSeq
[i
] & 0xf ] );
942 rBuffer
.append( '-' );
943 for( ; i
< 16; i
++ ) {
944 rBuffer
.append( cDigits
[ aSeq
[i
] >> 4 ] );
945 rBuffer
.append( cDigits
[ aSeq
[i
] & 0xf ] );
947 rBuffer
.append( '}' );
950 void DrawingML::WriteRun( Reference
< XTextRange
> rRun
)
952 const char* sFieldType
;
953 sal_Bool bIsField
= sal_False
;
954 OUString sText
= rRun
->getString();
956 if( sText
.isEmpty()) {
957 Reference
< XPropertySet
> xPropSet( rRun
, UNO_QUERY
);
960 if( !xPropSet
.is() || !( xPropSet
->getPropertyValue( "PlaceholderText" ) >>= sText
) )
962 if( sText
.isEmpty() )
965 catch (const Exception
&) {
970 sFieldType
= GetFieldType( rRun
, bIsField
);
971 if( ( sFieldType
!= NULL
) ) {
972 OStringBuffer
sUUID(39);
975 mpFS
->startElementNS( XML_a
, XML_fld
,
976 XML_id
, sUUID
.getStr(),
977 XML_type
, sFieldType
,
980 mpFS
->startElementNS( XML_a
, XML_r
, FSEND
);
982 Reference
< XPropertySet
> xPropSet( rRun
, uno::UNO_QUERY
);
983 WriteRunProperties( xPropSet
, bIsField
);
985 mpFS
->startElementNS( XML_a
, XML_t
, FSEND
);
986 mpFS
->writeEscaped( sText
);
987 mpFS
->endElementNS( XML_a
, XML_t
);
990 mpFS
->endElementNS( XML_a
, XML_fld
);
992 mpFS
->endElementNS( XML_a
, XML_r
);
997 pAutoNumType = #x "ParenBoth"; \
998 else if( bPBehind ) \
999 pAutoNumType = #x "ParenR"; \
1001 pAutoNumType = #x "Period";
1003 inline static const char* GetAutoNumType( sal_Int16 nNumberingType
, bool bSDot
, bool bPBehind
, bool bPBoth
)
1005 const char* pAutoNumType
= NULL
;
1007 switch( (SvxExtNumType
)nNumberingType
)
1009 case SVX_NUM_CHARS_UPPER_LETTER_N
:
1010 case SVX_NUM_CHARS_UPPER_LETTER
:
1013 case SVX_NUM_CHARS_LOWER_LETTER_N
:
1014 case SVX_NUM_CHARS_LOWER_LETTER
:
1017 case SVX_NUM_ROMAN_UPPER
:
1020 case SVX_NUM_ROMAN_LOWER
:
1023 case SVX_NUM_ARABIC
:
1026 pAutoNumType
= "arabicPlain";
1032 return pAutoNumType
;
1035 void DrawingML::WriteParagraphNumbering( Reference
< XPropertySet
> rXPropSet
, sal_Int16 nLevel
)
1037 if( nLevel
>= 0 && GETA( NumberingRules
) )
1039 Reference
< XIndexAccess
> rXIndexAccess
;
1041 if ( ( mAny
>>= rXIndexAccess
) && nLevel
< rXIndexAccess
->getCount() )
1043 DBG(printf ("numbering rules\n"));
1045 Sequence
< PropertyValue
> aPropertySequence
;
1046 rXIndexAccess
->getByIndex( nLevel
) >>= aPropertySequence
;
1048 const PropertyValue
* pPropValue
= aPropertySequence
.getArray();
1050 sal_Int32 nPropertyCount
= aPropertySequence
.getLength();
1052 if ( nPropertyCount
) {
1054 sal_Int16 nNumberingType
= -1;
1056 bool bPBehind
= false;
1057 bool bPBoth
= false;
1058 sal_Unicode aBulletChar
= 0x2022; // a bullet
1059 awt::FontDescriptor aFontDesc
;
1060 bool bHasFontDesc
= false;
1061 OUString aGraphicURL
;
1062 sal_Int16 nBulletRelSize
= 0;
1064 for ( sal_Int32 i
= 0; i
< nPropertyCount
; i
++ ) {
1065 const void* pValue
= pPropValue
[ i
].Value
.getValue();
1067 OUString
aPropName( pPropValue
[ i
].Name
);
1068 DBG(printf ("pro name: %s\n", OUStringToOString( aPropName
, RTL_TEXTENCODING_UTF8
).getStr()));
1069 if ( aPropName
== "NumberingType" )
1070 nNumberingType
= *( (sal_Int16
*)pValue
);
1071 else if ( aPropName
== "Prefix" ) {
1072 if( *(OUString
*)pValue
== ")")
1074 } else if ( aPropName
== "Suffix" ) {
1075 if( *(OUString
*)pValue
== ".")
1077 else if( *(OUString
*)pValue
== ")")
1079 } else if ( aPropName
== "BulletChar" )
1081 aBulletChar
= String ( *( (String
*)pValue
) ).GetChar( 0 );
1082 //printf ("bullet char: %d\n", aBulletChar.getStr());
1084 else if ( aPropName
== "BulletFont" )
1086 aFontDesc
= *( (awt::FontDescriptor
*)pValue
);
1087 bHasFontDesc
= true;
1089 // Our numbullet dialog has set the wrong textencoding for our "StarSymbol" font,
1090 // instead of a Unicode encoding the encoding RTL_TEXTENCODING_SYMBOL was used.
1091 // Because there might exist a lot of damaged documemts I added this two lines
1092 // which fixes the bullet problem for the export.
1093 if ( aFontDesc
.Name
== "StarSymbol" )
1094 aFontDesc
.CharSet
= RTL_TEXTENCODING_MS_1252
;
1096 } else if ( aPropName
== "BulletRelSize" ) {
1097 nBulletRelSize
= *( (sal_Int16
*)pValue
);
1098 } else if ( aPropName
== "GraphicURL" ) {
1099 aGraphicURL
= ( *(OUString
*)pValue
);
1100 DBG(printf ("graphic url: %s\n", OUStringToOString( aGraphicURL
, RTL_TEXTENCODING_UTF8
).getStr()));
1101 } else if ( aPropName
== "GraphicSize" )
1103 if ( pPropValue
[ i
].Value
.getValueType() == ::getCppuType( (awt::Size
*)0) )
1105 // don't cast awt::Size to Size as on 64-bits they are not the same.
1106 ::com::sun::star::awt::Size aSize
;
1107 pPropValue
[ i
].Value
>>= aSize
;
1108 //aBuGraSize.nA = aSize.Width;
1109 //aBuGraSize.nB = aSize.Height;
1110 DBG(printf("graphic size: %dx%d\n", int( aSize
.Width
), int( aSize
.Height
)));
1116 const char* pAutoNumType
= GetAutoNumType( nNumberingType
, bSDot
, bPBehind
, bPBoth
);
1119 if( !aGraphicURL
.isEmpty() ) {
1120 OUString sRelId
= WriteImage( aGraphicURL
);
1122 mpFS
->startElementNS( XML_a
, XML_buBlip
, FSEND
);
1123 mpFS
->singleElementNS( XML_a
, XML_blip
, FSNS( XML_r
, XML_embed
), USS( sRelId
), FSEND
);
1124 mpFS
->endElementNS( XML_a
, XML_buBlip
);
1126 if( nBulletRelSize
&& nBulletRelSize
!= 100 )
1127 mpFS
->singleElementNS( XML_a
, XML_buSzPct
,
1128 XML_val
, IS( std::min( (sal_Int32
)25000, std::max( (sal_Int32
)400000, 1000*( (sal_Int32
)nBulletRelSize
) ) ) ), FSEND
);
1130 mpFS
->singleElementNS( XML_a
, XML_buFont
,
1131 XML_typeface
, OUStringToOString( aFontDesc
.Name
, RTL_TEXTENCODING_UTF8
).getStr(),
1132 XML_charset
, (aFontDesc
.CharSet
== awt::CharSet::SYMBOL
) ? "2" : NULL
,
1136 mpFS
->singleElementNS( XML_a
, XML_buAutoNum
, XML_type
, pAutoNumType
, FSEND
);
1138 aBulletChar
= SubstituteBullet( aBulletChar
, aFontDesc
);
1139 mpFS
->singleElementNS( XML_a
, XML_buChar
, XML_char
, USS( OUString( aBulletChar
) ), FSEND
);
1148 const char* DrawingML::GetAlignment( sal_Int32 nAlignment
)
1150 const char* sAlignment
= NULL
;
1152 switch( nAlignment
) {
1153 case style::ParagraphAdjust_CENTER
:
1156 case style::ParagraphAdjust_RIGHT
:
1159 case style::ParagraphAdjust_BLOCK
:
1160 sAlignment
= "just";
1169 void DrawingML::WriteLinespacing( LineSpacing
& rSpacing
)
1171 if( rSpacing
.Mode
== LineSpacingMode::PROP
)
1172 mpFS
->singleElementNS( XML_a
, XML_spcPct
,
1173 XML_val
, I32S( ((sal_Int32
)rSpacing
.Height
)*1000 ),
1176 mpFS
->singleElementNS( XML_a
, XML_spcPts
,
1177 XML_val
, I32S( rSpacing
.Height
),
1181 void DrawingML::WriteParagraphProperties( Reference
< XTextContent
> rParagraph
)
1183 Reference
< XPropertySet
> rXPropSet( rParagraph
, UNO_QUERY
);
1184 Reference
< XPropertyState
> rXPropState( rParagraph
, UNO_QUERY
);
1185 PropertyState eState
;
1187 if( !rXPropSet
.is() || !rXPropState
.is() )
1190 sal_Int16 nLevel
= -1;
1191 GET( nLevel
, NumberingLevel
);
1193 sal_Int16
nAlignment( style::ParagraphAdjust_LEFT
);
1194 GET( nAlignment
, ParaAdjust
);
1196 sal_Bool bHasLinespacing
= sal_False
;
1197 LineSpacing aLineSpacing
;
1198 if( GETAD( ParaLineSpacing
) )
1199 bHasLinespacing
= ( mAny
>>= aLineSpacing
);
1202 || nAlignment
!= style::ParagraphAdjust_LEFT
1203 || bHasLinespacing
) {
1204 mpFS
->startElementNS( XML_a
, XML_pPr
,
1205 XML_lvl
, nLevel
> 0 ? I32S( nLevel
) : NULL
,
1207 XML_algn
, GetAlignment( nAlignment
),
1210 if( bHasLinespacing
) {
1211 mpFS
->startElementNS( XML_a
, XML_lnSpc
, FSEND
);
1212 WriteLinespacing( aLineSpacing
);
1213 mpFS
->endElementNS( XML_a
, XML_lnSpc
);
1216 WriteParagraphNumbering( rXPropSet
, nLevel
);
1218 mpFS
->endElementNS( XML_a
, XML_pPr
);
1222 void DrawingML::WriteParagraph( Reference
< XTextContent
> rParagraph
)
1224 Reference
< XEnumerationAccess
> access( rParagraph
, UNO_QUERY
);
1228 Reference
< XEnumeration
> enumeration( access
->createEnumeration() );
1229 if( !enumeration
.is() )
1232 mpFS
->startElementNS( XML_a
, XML_p
, FSEND
);
1234 sal_Bool bPropertiesWritten
= sal_False
;
1235 while( enumeration
->hasMoreElements() ) {
1236 Reference
< XTextRange
> run
;
1237 Any
any ( enumeration
->nextElement() );
1240 if( !bPropertiesWritten
) {
1241 WriteParagraphProperties( rParagraph
);
1242 bPropertiesWritten
= sal_True
;
1247 mpFS
->singleElementNS( XML_a
, XML_endParaRPr
, FSEND
);
1249 mpFS
->endElementNS( XML_a
, XML_p
);
1252 void DrawingML::WriteText( Reference
< XInterface
> rXIface
)
1254 Reference
< XText
> xXText( rXIface
, UNO_QUERY
);
1255 Reference
< XPropertySet
> rXPropSet( rXIface
, UNO_QUERY
);
1260 #define DEFLRINS 254
1261 #define DEFTBINS 127
1262 sal_Int32 nLeft
, nRight
, nTop
, nBottom
;
1263 nLeft
= nRight
= DEFLRINS
;
1264 nTop
= nBottom
= DEFTBINS
;
1266 // top inset looks a bit different compared to ppt export
1267 // check if something related doesn't work as expected
1268 GET( nLeft
, TextLeftDistance
);
1269 GET( nRight
, TextRightDistance
);
1270 GET( nTop
, TextUpperDistance
);
1271 GET( nBottom
, TextLowerDistance
);
1273 TextVerticalAdjust
eVerticalAlignment( TextVerticalAdjust_TOP
);
1274 const char* sVerticalAlignment
= NULL
;
1275 GET( eVerticalAlignment
, TextVerticalAdjust
);
1276 switch( eVerticalAlignment
) {
1277 case TextVerticalAdjust_BOTTOM
:
1278 sVerticalAlignment
= "b";
1280 case TextVerticalAdjust_CENTER
:
1281 sVerticalAlignment
= "ctr";
1283 case TextVerticalAdjust_TOP
:
1288 const char* sWritingMode
= NULL
;
1289 sal_Bool bVertical
= sal_False
;
1290 if( GETA( TextWritingMode
) ) {
1293 if( ( mAny
>>= eMode
) && eMode
== WritingMode_TB_RL
) {
1294 sWritingMode
= "vert";
1295 bVertical
= sal_True
;
1299 if ( GETA( CustomShapeGeometry
) )
1301 Sequence
< PropertyValue
> aProps
;
1302 if ( mAny
>>= aProps
)
1304 for ( sal_Int32 i
= 0, nElems
= aProps
.getLength(); i
< nElems
; ++i
)
1306 sal_Int32 nTextRotateAngle
= 0;
1307 if ( aProps
[ i
].Name
.equals( "TextPreRotateAngle" ) && ( aProps
[ i
].Value
>>= nTextRotateAngle
) )
1309 if ( nTextRotateAngle
== -90 )
1311 sWritingMode
= "vert";
1312 bVertical
= sal_True
;
1320 TextHorizontalAdjust
eHorizontalAlignment( TextHorizontalAdjust_CENTER
);
1321 bool bHorizontalCenter
= false;
1322 GET( eHorizontalAlignment
, TextHorizontalAdjust
);
1323 if( eHorizontalAlignment
== TextHorizontalAdjust_CENTER
)
1324 bHorizontalCenter
= true;
1325 else if( bVertical
&& eHorizontalAlignment
== TextHorizontalAdjust_LEFT
)
1326 sVerticalAlignment
= "b";
1328 sal_Bool bHasWrap
= sal_False
;
1329 sal_Bool bWrap
= sal_False
;
1330 if( GETA( TextWordWrap
) ) {
1332 bHasWrap
= sal_True
;
1335 mpFS
->singleElementNS( XML_a
, XML_bodyPr
,
1336 XML_wrap
, bHasWrap
&& !bWrap
? "none" : NULL
,
1337 XML_lIns
, (nLeft
!= DEFLRINS
) ? IS( MM100toEMU( nLeft
) ) : NULL
,
1338 XML_rIns
, (nRight
!= DEFLRINS
) ? IS( MM100toEMU( nRight
) ) : NULL
,
1339 XML_tIns
, (nTop
!= DEFTBINS
) ? IS( MM100toEMU( nTop
) ) : NULL
,
1340 XML_bIns
, (nBottom
!= DEFTBINS
) ? IS( MM100toEMU( nBottom
) ) : NULL
,
1341 XML_anchor
, sVerticalAlignment
,
1342 XML_anchorCtr
, bHorizontalCenter
? "1" : NULL
,
1343 XML_vert
, sWritingMode
,
1346 Reference
< XEnumerationAccess
> access( xXText
, UNO_QUERY
);
1350 Reference
< XEnumeration
> enumeration( access
->createEnumeration() );
1351 if( !enumeration
.is() )
1354 while( enumeration
->hasMoreElements() ) {
1355 Reference
< XTextContent
> paragraph
;
1356 Any
any ( enumeration
->nextElement() );
1358 if( any
>>= paragraph
)
1359 WriteParagraph( paragraph
);
1364 void DrawingML::WritePresetShape( const char* pShape
)
1366 mpFS
->startElementNS( XML_a
, XML_prstGeom
,
1369 mpFS
->singleElementNS( XML_a
, XML_avLst
, FSEND
);
1370 mpFS
->endElementNS( XML_a
, XML_prstGeom
);
1373 void DrawingML::WritePresetShape( const char* pShape
, MSO_SPT eShapeType
, sal_Bool bPredefinedHandlesUsed
, sal_Int32 nAdjustmentsWhichNeedsToBeConverted
, const PropertyValue
& rProp
)
1375 mpFS
->startElementNS( XML_a
, XML_prstGeom
,
1378 mpFS
->startElementNS( XML_a
, XML_avLst
, FSEND
);
1380 Sequence
< drawing::EnhancedCustomShapeAdjustmentValue
> aAdjustmentSeq
;
1381 if ( ( rProp
.Value
>>= aAdjustmentSeq
)
1382 && eShapeType
!= mso_sptActionButtonForwardNext
// we have adjustments values for these type of shape, but MSO doesn't like them
1383 && eShapeType
!= mso_sptActionButtonBackPrevious
// so they are now disabled
1385 DBG(printf("adj seq len: %d\n", int( aAdjustmentSeq
.getLength() )));
1386 if ( bPredefinedHandlesUsed
)
1387 EscherPropertyContainer::LookForPolarHandles( eShapeType
, nAdjustmentsWhichNeedsToBeConverted
);
1389 sal_Int32 nValue
, nLength
= aAdjustmentSeq
.getLength();
1390 for( sal_Int32 i
=0; i
< nLength
; i
++ )
1391 if( EscherPropertyContainer::GetAdjustmentValue( aAdjustmentSeq
[ i
], i
, nAdjustmentsWhichNeedsToBeConverted
, nValue
) )
1392 mpFS
->singleElementNS( XML_a
, XML_gd
,
1393 XML_name
, aAdjustmentSeq
[ i
].Name
.getLength() > 0 ? USS(aAdjustmentSeq
[ i
].Name
) : (nLength
> 1 ? OString( "adj" + OString::valueOf( i
+ 1 ) ).getStr() : "adj"),
1394 XML_fmla
, OString("val " + OString::valueOf( nValue
)).getStr(),
1398 mpFS
->endElementNS( XML_a
, XML_avLst
);
1399 mpFS
->endElementNS( XML_a
, XML_prstGeom
);
1402 void DrawingML::WritePolyPolygon( const PolyPolygon
& rPolyPolygon
)
1404 if( rPolyPolygon
.Count() < 1 )
1407 mpFS
->startElementNS( XML_a
, XML_custGeom
, FSEND
);
1408 mpFS
->singleElementNS( XML_a
, XML_avLst
, FSEND
);
1409 mpFS
->singleElementNS( XML_a
, XML_gdLst
, FSEND
);
1410 mpFS
->singleElementNS( XML_a
, XML_ahLst
, FSEND
);
1411 mpFS
->singleElementNS( XML_a
, XML_rect
,
1418 mpFS
->startElementNS( XML_a
, XML_pathLst
, FSEND
);
1420 for( sal_uInt16 i
= 0; i
< rPolyPolygon
.Count(); i
++ ) {
1422 const Polygon
& rPoly
= rPolyPolygon
[ i
];
1423 Rectangle
aRect( rPoly
.GetBoundRect() );
1424 sal_Bool bBezier
= sal_False
;
1426 mpFS
->startElementNS( XML_a
, XML_path
,
1427 XML_w
, I64S( aRect
.GetWidth() ),
1428 XML_h
, I64S( aRect
.GetHeight() ),
1431 if( rPoly
.GetSize() > 0 )
1433 mpFS
->startElementNS( XML_a
, XML_moveTo
, FSEND
);
1435 mpFS
->singleElementNS( XML_a
, XML_pt
,
1436 XML_x
, I64S( rPoly
[ 0 ].X() - aRect
.Left() ),
1437 XML_y
, I64S( rPoly
[ 0 ].Y() - aRect
.Top() ),
1440 mpFS
->endElementNS( XML_a
, XML_moveTo
);
1443 for( sal_uInt16 j
= 1; j
< rPoly
.GetSize(); j
++ )
1445 enum PolyFlags flags
= rPoly
.GetFlags(j
);
1446 if( flags
== POLY_CONTROL
&& !bBezier
)
1448 mpFS
->startElementNS( XML_a
, XML_cubicBezTo
, FSEND
);
1451 else if( flags
== POLY_NORMAL
&& !bBezier
)
1452 mpFS
->startElementNS( XML_a
, XML_lnTo
, FSEND
);
1454 mpFS
->singleElementNS( XML_a
, XML_pt
,
1455 XML_x
, I64S( rPoly
[j
].X() - aRect
.Left() ),
1456 XML_y
, I64S( rPoly
[j
].Y() - aRect
.Top() ),
1459 if( ( flags
== POLY_NORMAL
|| flags
== POLY_SYMMTR
) && bBezier
)
1461 mpFS
->endElementNS( XML_a
, XML_cubicBezTo
);
1462 bBezier
= sal_False
;
1464 else if( flags
== POLY_NORMAL
&& !bBezier
)
1465 mpFS
->endElementNS( XML_a
, XML_lnTo
);
1466 else if( bBezier
&& ( j
% 3 ) == 0 )
1468 // //a:cubicBezTo can only contain 3 //a:pt elements, so we
1469 // need to break things up...
1470 mpFS
->endElementNS( XML_a
, XML_cubicBezTo
);
1471 mpFS
->startElementNS( XML_a
, XML_cubicBezTo
, FSEND
);
1475 mpFS
->endElementNS( XML_a
, XML_path
);
1478 mpFS
->endElementNS( XML_a
, XML_pathLst
);
1480 mpFS
->endElementNS( XML_a
, XML_custGeom
);
1483 void DrawingML::WriteConnectorConnections( EscherConnectorListEntry
& rConnectorEntry
, sal_Int32 nStartID
, sal_Int32 nEndID
)
1485 if( nStartID
!= -1 )
1486 mpFS
->singleElementNS( XML_a
, XML_stCxn
,
1487 XML_id
, I32S( nStartID
),
1488 XML_idx
, I64S( rConnectorEntry
.GetConnectorRule( sal_True
) ),
1491 mpFS
->singleElementNS( XML_a
, XML_endCxn
,
1492 XML_id
, I32S( nEndID
),
1493 XML_idx
, I64S( rConnectorEntry
.GetConnectorRule( sal_False
) ),
1497 sal_Unicode
DrawingML::SubstituteBullet( sal_Unicode cBulletId
, ::com::sun::star::awt::FontDescriptor
& rFontDesc
)
1499 if ( rFontDesc
.Name
.equalsIgnoreAsciiCase("starsymbol") || rFontDesc
.Name
.equalsIgnoreAsciiCase("opensymbol") )
1501 rtl_TextEncoding eCharSet
= rFontDesc
.CharSet
;
1502 cBulletId
= msfilter::util::bestFitOpenSymbolToMSFont(cBulletId
, eCharSet
, rFontDesc
.Name
);
1503 rFontDesc
.CharSet
= eCharSet
;
1509 sax_fastparser::FSHelperPtr
DrawingML::CreateOutputStream (
1510 const OUString
& sFullStream
,
1511 const OUString
& sRelativeStream
,
1512 const Reference
< XOutputStream
>& xParentRelation
,
1513 const char* sContentType
,
1514 const char* sRelationshipType
,
1515 OUString
* pRelationshipId
)
1517 OUString sRelationshipId
;
1518 if (xParentRelation
.is())
1519 sRelationshipId
= GetFB()->addRelation( xParentRelation
, OUString::createFromAscii( sRelationshipType
), sRelativeStream
);
1521 sRelationshipId
= GetFB()->addRelation( OUString::createFromAscii( sRelationshipType
), sRelativeStream
);
1523 if( pRelationshipId
)
1524 *pRelationshipId
= sRelationshipId
;
1526 sax_fastparser::FSHelperPtr p
= GetFB()->openFragmentStreamWithSerializer( sFullStream
, OUString::createFromAscii( sContentType
) );
1531 void DrawingML::WriteFill( Reference
< XPropertySet
> xPropSet
)
1533 if ( !GetProperty( xPropSet
, "FillStyle" ) )
1535 FillStyle
aFillStyle( FillStyle_NONE
);
1536 xPropSet
->getPropertyValue( "FillStyle" ) >>= aFillStyle
;
1538 if( aFillStyle
== FillStyle_HATCH
)
1541 if ( aFillStyle
== FillStyle_SOLID
&& GetProperty( xPropSet
, "FillTransparence" ) )
1543 // map full transparent background to no fill
1545 xPropSet
->getPropertyValue( "FillTransparence" ) >>= nVal
;
1547 aFillStyle
= FillStyle_NONE
;
1550 switch( aFillStyle
)
1552 case FillStyle_SOLID
:
1553 WriteSolidFill( xPropSet
);
1555 case FillStyle_GRADIENT
:
1556 WriteGradientFill( xPropSet
);
1558 case FillStyle_BITMAP
:
1559 WriteBlipFill( xPropSet
, "FillBitmapURL" );
1561 case FillStyle_NONE
:
1562 mpFS
->singleElementNS( XML_a
, XML_noFill
, FSEND
);
1574 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */