Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include "oox/core/xmlfilterbase.hxx"
21 : #include "oox/export/drawingml.hxx"
22 : #include "oox/export/utils.hxx"
23 : #include <oox/token/tokens.hxx>
24 :
25 : #include <cstdio>
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/drawing/BitmapMode.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/XText.hpp>
55 : #include <com/sun/star/text/XTextContent.hpp>
56 : #include <com/sun/star/text/XTextField.hpp>
57 : #include <com/sun/star/text/XTextRange.hpp>
58 : #include <tools/stream.hxx>
59 : #include <tools/string.hxx>
60 : #include <unotools/fontdefs.hxx>
61 : #include <vcl/cvtgrf.hxx>
62 : #include <vcl/graph.hxx>
63 : #include <svtools/grfmgr.hxx>
64 : #include <rtl/strbuf.hxx>
65 : #include <sfx2/app.hxx>
66 : #include <svl/languageoptions.hxx>
67 : #include <filter/msfilter/escherex.hxx>
68 : #include <filter/msfilter/util.hxx>
69 : #include <editeng/svxenum.hxx>
70 : #include <svx/unoapi.hxx>
71 : #include <svx/svdoashp.hxx>
72 :
73 : using namespace ::com::sun::star;
74 : using namespace ::com::sun::star::beans;
75 : using namespace ::com::sun::star::drawing;
76 : using namespace ::com::sun::star::i18n;
77 : using namespace ::com::sun::star::style;
78 : using namespace ::com::sun::star::text;
79 : using namespace ::com::sun::star::uno;
80 : using ::com::sun::star::beans::PropertyState;
81 : using ::com::sun::star::beans::PropertyValue;
82 : using ::com::sun::star::beans::XPropertySet;
83 : using ::com::sun::star::beans::XPropertyState;
84 : using ::com::sun::star::container::XEnumeration;
85 : using ::com::sun::star::container::XEnumerationAccess;
86 : using ::com::sun::star::container::XIndexAccess;
87 : using ::com::sun::star::io::XOutputStream;
88 : using ::com::sun::star::style::LineSpacing;
89 : using ::com::sun::star::text::XText;
90 : using ::com::sun::star::text::XTextContent;
91 : using ::com::sun::star::text::XTextField;
92 : using ::com::sun::star::text::XTextRange;
93 : using ::sax_fastparser::FSHelperPtr;
94 :
95 : DBG(extern void dump_pset(Reference< XPropertySet > rXPropSet));
96 :
97 : namespace oox {
98 : namespace drawingml {
99 :
100 : #define GETA(propName) \
101 : GetProperty( rXPropSet, String( #propName ) )
102 :
103 : #define GETAD(propName) \
104 : ( GetPropertyAndState( rXPropSet, rXPropState, String( #propName ), eState ) && eState == beans::PropertyState_DIRECT_VALUE )
105 :
106 : #define GET(variable, propName) \
107 : if ( GETA(propName) ) \
108 : mAny >>= variable;
109 :
110 : // not thread safe
111 : int DrawingML::mnImageCounter = 1;
112 :
113 0 : void DrawingML::ResetCounters()
114 : {
115 0 : mnImageCounter = 1;
116 0 : }
117 :
118 0 : bool DrawingML::GetProperty( Reference< XPropertySet > rXPropSet, String aName )
119 : {
120 0 : bool bRetValue = false;
121 :
122 : try {
123 0 : mAny = rXPropSet->getPropertyValue( aName );
124 0 : if ( mAny.hasValue() )
125 0 : bRetValue = true;
126 0 : } catch( const Exception& ) { /* printf ("exception when trying to get value of property: %s\n", USS(aName)); */ }
127 :
128 0 : return bRetValue;
129 : }
130 :
131 0 : bool DrawingML::GetPropertyAndState( Reference< XPropertySet > rXPropSet, Reference< XPropertyState > rXPropState, String aName, PropertyState& eState )
132 : {
133 0 : bool bRetValue = false;
134 :
135 : try {
136 0 : mAny = rXPropSet->getPropertyValue( aName );
137 0 : if ( mAny.hasValue() ) {
138 0 : bRetValue = true;
139 0 : eState = rXPropState->getPropertyState( aName );
140 : }
141 0 : } catch( const Exception& ) { /* printf ("exception when trying to get value of property: %s\n", USS(aName)); */ }
142 :
143 0 : return bRetValue;
144 : }
145 :
146 0 : void DrawingML::WriteColor( sal_uInt32 nColor )
147 : {
148 0 : OString sColor = OString::valueOf( ( sal_Int64 ) nColor, 16 );
149 0 : if( sColor.getLength() < 6 ) {
150 0 : OStringBuffer sBuf( "0" );
151 0 : int remains = 5 - sColor.getLength();
152 :
153 0 : while( remains > 0 ) {
154 0 : sBuf.append( "0" );
155 0 : remains--;
156 : }
157 :
158 0 : sBuf.append( sColor );
159 :
160 0 : sColor = sBuf.getStr();
161 : }
162 0 : mpFS->singleElementNS( XML_a, XML_srgbClr, XML_val, sColor.getStr(), FSEND );
163 0 : }
164 :
165 0 : void DrawingML::WriteSolidFill( sal_uInt32 nColor )
166 : {
167 0 : mpFS->startElementNS( XML_a, XML_solidFill, FSEND );
168 0 : WriteColor( nColor );
169 0 : mpFS->endElementNS( XML_a, XML_solidFill );
170 0 : }
171 :
172 0 : void DrawingML::WriteSolidFill( Reference< XPropertySet > rXPropSet )
173 : {
174 0 : if ( GetProperty( rXPropSet, S( "FillColor" ) ) )
175 0 : WriteSolidFill( *((sal_uInt32*) mAny.getValue()) & 0xffffff );
176 0 : }
177 :
178 0 : void DrawingML::WriteGradientStop( sal_uInt16 nStop, sal_uInt32 nColor )
179 : {
180 : mpFS->startElementNS( XML_a, XML_gs,
181 : XML_pos, I32S( nStop * 1000 ),
182 0 : FSEND );
183 0 : WriteColor( nColor );
184 0 : mpFS->endElementNS( XML_a, XML_gs );
185 0 : }
186 :
187 0 : sal_uInt32 DrawingML::ColorWithIntensity( sal_uInt32 nColor, sal_uInt32 nIntensity )
188 : {
189 : return ( ( ( nColor & 0xff ) * nIntensity ) / 100 )
190 : | ( ( ( ( ( nColor & 0xff00 ) >> 8 ) * nIntensity ) / 100 ) << 8 )
191 0 : | ( ( ( ( ( nColor & 0xff0000 ) >> 8 ) * nIntensity ) / 100 ) << 8 );
192 : }
193 :
194 0 : void DrawingML::WriteGradientFill( Reference< XPropertySet > rXPropSet )
195 : {
196 0 : awt::Gradient aGradient;
197 0 : if( GETA( FillGradient ) ) {
198 0 : aGradient = *static_cast< const awt::Gradient* >( mAny.getValue() );
199 :
200 0 : mpFS->startElementNS( XML_a, XML_gradFill, FSEND );
201 :
202 0 : switch( aGradient.Style ) {
203 : default:
204 : case GradientStyle_LINEAR:
205 0 : mpFS->startElementNS( XML_a, XML_gsLst, FSEND );
206 0 : WriteGradientStop( 0, ColorWithIntensity( aGradient.StartColor, aGradient.StartIntensity ) );
207 0 : WriteGradientStop( 100, ColorWithIntensity( aGradient.EndColor, aGradient.EndIntensity ) );
208 0 : mpFS->endElementNS( XML_a, XML_gsLst );
209 : mpFS->singleElementNS( XML_a, XML_lin,
210 : XML_ang, I32S( ( ( ( 3600 - aGradient.Angle + 900 ) * 6000 ) % 21600000 ) ),
211 0 : FSEND );
212 0 : break;
213 :
214 : case GradientStyle_AXIAL:
215 0 : mpFS->startElementNS( XML_a, XML_gsLst, FSEND );
216 0 : WriteGradientStop( 0, ColorWithIntensity( aGradient.EndColor, aGradient.EndIntensity ) );
217 0 : WriteGradientStop( 50, ColorWithIntensity( aGradient.StartColor, aGradient.StartIntensity ) );
218 0 : WriteGradientStop( 100, ColorWithIntensity( aGradient.EndColor, aGradient.EndIntensity ) );
219 0 : mpFS->endElementNS( XML_a, XML_gsLst );
220 : mpFS->singleElementNS( XML_a, XML_lin,
221 : XML_ang, I32S( ( ( ( 3600 - aGradient.Angle + 900 ) * 6000 ) % 21600000 ) ),
222 0 : FSEND );
223 0 : break;
224 :
225 : /* I don't see how to apply transformation to gradients, so
226 : * elliptical will end as radial and square as
227 : * rectangular. also position offsets are not applied */
228 : case GradientStyle_RADIAL:
229 : case GradientStyle_ELLIPTICAL:
230 : case GradientStyle_RECT:
231 : case GradientStyle_SQUARE:
232 0 : mpFS->startElementNS( XML_a, XML_gsLst, FSEND );
233 0 : WriteGradientStop( 0, ColorWithIntensity( aGradient.EndColor, aGradient.EndIntensity ) );
234 0 : WriteGradientStop( 100, ColorWithIntensity( aGradient.StartColor, aGradient.StartIntensity ) );
235 0 : mpFS->endElementNS( XML_a, XML_gsLst );
236 : mpFS->singleElementNS( XML_a, XML_path,
237 : XML_path, ( aGradient.Style == awt::GradientStyle_RADIAL || aGradient.Style == awt::GradientStyle_ELLIPTICAL ) ? "circle" : "rect",
238 0 : FSEND );
239 0 : break;
240 : }
241 :
242 0 : mpFS->endElementNS( XML_a, XML_gradFill );
243 : }
244 :
245 0 : }
246 :
247 0 : void DrawingML::WriteLineArrow( Reference< XPropertySet > rXPropSet, sal_Bool bLineStart )
248 : {
249 : ESCHER_LineEnd eLineEnd;
250 : sal_Int32 nArrowLength;
251 : sal_Int32 nArrowWidth;
252 :
253 0 : if ( EscherPropertyContainer::GetLineArrow( bLineStart, rXPropSet, eLineEnd, nArrowLength, nArrowWidth ) ) {
254 : const char* len;
255 : const char* type;
256 : const char* width;
257 :
258 0 : switch( nArrowLength ) {
259 : case ESCHER_LineShortArrow:
260 0 : len = "sm";
261 0 : break;
262 : default:
263 : case ESCHER_LineMediumLenArrow:
264 0 : len = "med";
265 0 : break;
266 : case ESCHER_LineLongArrow:
267 0 : len = "lg";
268 0 : break;
269 : }
270 :
271 0 : switch( eLineEnd ) {
272 : default:
273 : case ESCHER_LineNoEnd:
274 0 : type = "none";
275 0 : break;
276 : case ESCHER_LineArrowEnd:
277 0 : type = "triangle";
278 0 : break;
279 : case ESCHER_LineArrowStealthEnd:
280 0 : type = "stealth";
281 0 : break;
282 : case ESCHER_LineArrowDiamondEnd:
283 0 : type = "diamond";
284 0 : break;
285 : case ESCHER_LineArrowOvalEnd:
286 0 : type = "oval";
287 0 : break;
288 : case ESCHER_LineArrowOpenEnd:
289 0 : type = "arrow";
290 0 : break;
291 : }
292 :
293 0 : switch( nArrowWidth ) {
294 : case ESCHER_LineNarrowArrow:
295 0 : width = "sm";
296 0 : break;
297 : default:
298 : case ESCHER_LineMediumWidthArrow:
299 0 : width = "med";
300 0 : break;
301 : case ESCHER_LineWideArrow:
302 0 : width = "lg";
303 0 : break;
304 : }
305 :
306 : mpFS->singleElementNS( XML_a, bLineStart ? XML_headEnd : XML_tailEnd,
307 : XML_len, len,
308 : XML_type, type,
309 : XML_w, width,
310 0 : FSEND );
311 : }
312 0 : }
313 :
314 0 : void DrawingML::WriteOutline( Reference< XPropertySet > rXPropSet )
315 : {
316 0 : drawing::LineStyle aLineStyle( drawing::LineStyle_NONE );
317 :
318 0 : GET( aLineStyle, LineStyle );
319 :
320 0 : if( aLineStyle == drawing::LineStyle_NONE )
321 0 : return;
322 :
323 0 : sal_uInt32 nLineWidth = 0;
324 0 : sal_uInt32 nColor = 0;
325 0 : sal_Bool bColorSet = sal_False;
326 0 : const char* cap = NULL;
327 0 : drawing::LineDash aLineDash;
328 0 : sal_Bool bDashSet = sal_False;
329 :
330 0 : GET( nLineWidth, LineWidth );
331 :
332 0 : switch( aLineStyle ) {
333 : case drawing::LineStyle_DASH:
334 0 : if( GETA( LineDash ) ) {
335 0 : aLineDash = *(drawing::LineDash*) mAny.getValue();
336 0 : bDashSet = sal_True;
337 0 : if( aLineDash.Style == DashStyle_ROUND || aLineDash.Style == DashStyle_ROUNDRELATIVE )
338 0 : cap = "rnd";
339 :
340 : DBG(printf("dash dots: %d dashes: %d dotlen: %d dashlen: %d distance: %d\n",
341 : int( aLineDash.Dots ), int( aLineDash.Dashes ), int( aLineDash.DotLen ), int( aLineDash.DashLen ), int( aLineDash.Distance )));
342 : }
343 : /* fallthru intended */
344 : case drawing::LineStyle_SOLID:
345 : default:
346 0 : if ( GETA( LineColor ) ) {
347 0 : nColor = *((sal_uInt32*) mAny.getValue()) & 0xffffff;
348 0 : bColorSet = sal_True;
349 : }
350 0 : break;
351 : }
352 :
353 : mpFS->startElementNS( XML_a, XML_ln,
354 : XML_cap, cap,
355 0 : XML_w, nLineWidth > 1 ? I64S( MM100toEMU( nLineWidth ) ) : NULL,
356 0 : FSEND );
357 0 : if( bColorSet )
358 0 : WriteSolidFill( nColor );
359 :
360 0 : if( bDashSet ) {
361 0 : mpFS->startElementNS( XML_a, XML_custDash, FSEND );
362 : int i;
363 0 : for( i = 0; i < aLineDash.Dots; i ++ )
364 : mpFS->singleElementNS( XML_a, XML_ds,
365 0 : XML_d, aLineDash.DotLen ? I64S( aLineDash.DotLen*1000 ) : "100000",
366 : XML_sp, I64S( aLineDash.Distance*1000 ),
367 0 : FSEND );
368 0 : for( i = 0; i < aLineDash.Dashes; i ++ )
369 : mpFS->singleElementNS( XML_a, XML_ds,
370 0 : XML_d, aLineDash.DashLen ? I64S( aLineDash.DashLen*1000 ) : "100000",
371 : XML_sp, I64S( aLineDash.Distance*1000 ),
372 0 : FSEND );
373 0 : mpFS->endElementNS( XML_a, XML_custDash );
374 : }
375 :
376 0 : if( nLineWidth > 1 && GETA( LineJoint ) ) {
377 : LineJoint eLineJoint;
378 :
379 0 : mAny >>= eLineJoint;
380 0 : switch( eLineJoint ) {
381 : case LineJoint_NONE:
382 : case LineJoint_MIDDLE:
383 : case LineJoint_BEVEL:
384 0 : mpFS->singleElementNS( XML_a, XML_bevel, FSEND );
385 0 : break;
386 : default:
387 : case LineJoint_MITER:
388 0 : mpFS->singleElementNS( XML_a, XML_miter, FSEND );
389 0 : break;
390 : case LineJoint_ROUND:
391 0 : mpFS->singleElementNS( XML_a, XML_round, FSEND );
392 0 : break;
393 : }
394 : }
395 :
396 0 : WriteLineArrow( rXPropSet, sal_True );
397 0 : WriteLineArrow( rXPropSet, sal_False );
398 :
399 0 : mpFS->endElementNS( XML_a, XML_ln );
400 : }
401 :
402 0 : OUString DrawingML::WriteImage( const OUString& rURL )
403 : {
404 0 : OString aURLBS(OUStringToOString(rURL, RTL_TEXTENCODING_UTF8));
405 :
406 0 : const char aURLBegin[] = "vnd.sun.star.GraphicObject:";
407 0 : sal_Int32 index = aURLBS.indexOf(aURLBegin);
408 :
409 0 : if ( index != -1 )
410 : {
411 : DBG(printf ("begin: %ld %s\n", long( sizeof( aURLBegin ) ), USS( rURL ) + RTL_CONSTASCII_LENGTH( aURLBegin ) ));
412 0 : Graphic aGraphic = GraphicObject( aURLBS.copy(RTL_CONSTASCII_LENGTH(aURLBegin)) ).GetTransformedGraphic ();
413 :
414 0 : return WriteImage( aGraphic );
415 : } else {
416 : // add link to relations
417 : }
418 :
419 0 : return OUString();
420 : }
421 :
422 1 : const char* DrawingML::GetComponentDir()
423 : {
424 1 : switch ( meDocumentType )
425 : {
426 1 : case DOCUMENT_DOCX: return "word";
427 0 : case DOCUMENT_PPTX: return "ppt";
428 0 : case DOCUMENT_XLSX: return "xl";
429 : }
430 :
431 0 : return "unknown";
432 : }
433 :
434 1 : const char* DrawingML::GetRelationCompPrefix()
435 : {
436 1 : switch ( meDocumentType )
437 : {
438 1 : case DOCUMENT_DOCX: return "";
439 : case DOCUMENT_PPTX:
440 0 : case DOCUMENT_XLSX: return "../";
441 : }
442 :
443 0 : return "unknown";
444 : }
445 :
446 1 : OUString DrawingML::WriteImage( const Graphic& rGraphic )
447 : {
448 1 : GfxLink aLink = rGraphic.GetLink ();
449 1 : OUString sMediaType;
450 1 : const char* pExtension = "";
451 1 : OUString sRelId;
452 :
453 1 : SvMemoryStream aStream;
454 1 : const void* aData = aLink.GetData();
455 1 : sal_Size nDataSize = aLink.GetDataSize();
456 :
457 1 : switch ( aLink.GetType() ) {
458 : case GFX_LINK_TYPE_NATIVE_GIF:
459 0 : sMediaType = US( "image/gif" );
460 0 : pExtension = ".gif";
461 0 : break;
462 : case GFX_LINK_TYPE_NATIVE_JPG:
463 0 : sMediaType = US( "image/jpeg" );
464 0 : pExtension = ".jpeg";
465 0 : break;
466 : case GFX_LINK_TYPE_NATIVE_PNG:
467 0 : sMediaType = US( "image/png" );
468 0 : pExtension = ".png";
469 0 : break;
470 : case GFX_LINK_TYPE_NATIVE_TIF:
471 0 : sMediaType = US( "image/tiff" );
472 0 : pExtension = ".tiff";
473 0 : break;
474 : case GFX_LINK_TYPE_NATIVE_WMF:
475 0 : sMediaType = US( "image/x-wmf" );
476 0 : pExtension = ".wmf";
477 0 : break;
478 : case GFX_LINK_TYPE_NATIVE_MET:
479 0 : sMediaType = US( "image/x-met" );
480 0 : pExtension = ".met";
481 0 : break;
482 : case GFX_LINK_TYPE_NATIVE_PCT:
483 0 : sMediaType = US( "image/x-pict" );
484 0 : pExtension = ".pct";
485 0 : break;
486 : default: {
487 1 : GraphicType aType = rGraphic.GetType();
488 1 : if ( aType == GRAPHIC_BITMAP ) {
489 0 : GraphicConverter::Export( aStream, rGraphic, CVT_PNG );
490 0 : sMediaType = US( "image/png" );
491 0 : pExtension = ".png";
492 1 : } else if ( aType == GRAPHIC_GDIMETAFILE ) {
493 1 : GraphicConverter::Export( aStream, rGraphic, CVT_EMF );
494 1 : sMediaType = US( "image/x-emf" );
495 1 : pExtension = ".emf";
496 : } else {
497 : OSL_TRACE( "unhandled graphic type" );
498 0 : break;
499 : }
500 :
501 1 : aData = aStream.GetData();
502 1 : nDataSize = aStream.GetEndOfData();
503 1 : break;
504 : }
505 : }
506 :
507 : Reference< XOutputStream > xOutStream = mpFB->openFragmentStream( OUStringBuffer()
508 2 : .appendAscii( GetComponentDir() )
509 1 : .appendAscii( "/media/image" )
510 2 : .append( (sal_Int32) mnImageCounter )
511 1 : .appendAscii( pExtension )
512 : .makeStringAndClear(),
513 1 : sMediaType );
514 1 : xOutStream->writeBytes( Sequence< sal_Int8 >( (const sal_Int8*) aData, nDataSize ) );
515 1 : xOutStream->closeOutput();
516 :
517 : sRelId = mpFB->addRelation( mpFS->getOutputStream(),
518 : US( "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" ),
519 : OUStringBuffer()
520 2 : .appendAscii( GetRelationCompPrefix() )
521 1 : .appendAscii( "media/image" )
522 2 : .append( (sal_Int32) mnImageCounter ++ )
523 1 : .appendAscii( pExtension )
524 1 : .makeStringAndClear() );
525 :
526 1 : return sRelId;
527 : }
528 :
529 0 : OUString DrawingML::WriteBlip( Reference< XPropertySet > rXPropSet, OUString& rURL, Graphic *pGraphic )
530 : {
531 0 : OUString sRelId = pGraphic ? WriteImage( *pGraphic ) : WriteImage( rURL );
532 0 : sal_Int16 nBright = 0;
533 0 : sal_Int32 nContrast = 0;
534 :
535 0 : GET( nBright, AdjustLuminance );
536 0 : GET( nContrast, AdjustContrast );
537 :
538 : mpFS->startElementNS( XML_a, XML_blip,
539 : FSNS( XML_r, XML_embed), OUStringToOString( sRelId, RTL_TEXTENCODING_UTF8 ).getStr(),
540 0 : FSEND );
541 0 : if( nBright || nContrast )
542 : mpFS->singleElementNS( XML_a, XML_lum,
543 0 : XML_bright, nBright ? I32S( nBright*1000 ) : NULL,
544 0 : XML_contrast, nContrast ? I32S( nContrast*1000 ) : NULL,
545 0 : FSEND );
546 :
547 0 : mpFS->endElementNS( XML_a, XML_blip );
548 :
549 0 : return sRelId;
550 : }
551 :
552 0 : void DrawingML::WriteBlipMode( Reference< XPropertySet > rXPropSet )
553 : {
554 0 : BitmapMode eBitmapMode( BitmapMode_NO_REPEAT );
555 0 : if (GetProperty( rXPropSet, S( "FillBitmapMode" ) ) )
556 0 : mAny >>= eBitmapMode;
557 :
558 : DBG(printf("fill bitmap mode: %d\n", eBitmapMode));
559 :
560 0 : switch (eBitmapMode) {
561 : case BitmapMode_REPEAT:
562 0 : mpFS->singleElementNS( XML_a, XML_tile, FSEND );
563 0 : break;
564 : default:
565 : ;
566 : }
567 0 : }
568 :
569 0 : void DrawingML::WriteBlipFill( Reference< XPropertySet > rXPropSet, String sURLPropName )
570 : {
571 0 : WriteBlipFill( rXPropSet, sURLPropName, XML_a );
572 0 : }
573 :
574 0 : void DrawingML::WriteBlipFill( Reference< XPropertySet > rXPropSet, String sURLPropName, sal_Int32 nXmlNamespace )
575 : {
576 0 : if ( GetProperty( rXPropSet, sURLPropName ) ) {
577 0 : OUString aURL;
578 0 : mAny >>= aURL;
579 :
580 : DBG(printf ("URL: %s\n", OUStringToOString( aURL, RTL_TEXTENCODING_UTF8 ).getStr() ));
581 :
582 0 : if( aURL.isEmpty() )
583 0 : return;
584 :
585 0 : mpFS->startElementNS( nXmlNamespace , XML_blipFill, FSEND );
586 :
587 0 : WriteBlip( rXPropSet, aURL );
588 :
589 0 : if( sURLPropName == S( "FillBitmapURL" ) )
590 0 : WriteBlipMode( rXPropSet );
591 0 : else if( GetProperty( rXPropSet, S( "FillBitmapStretch" ) ) ) {
592 0 : bool bStretch = false;
593 0 : mAny >>= bStretch;
594 :
595 0 : if( bStretch )
596 0 : WriteStretch();
597 : }
598 :
599 0 : mpFS->endElementNS( nXmlNamespace, XML_blipFill );
600 : }
601 : }
602 :
603 0 : void DrawingML::WriteStretch()
604 : {
605 0 : mpFS->startElementNS( XML_a, XML_stretch, FSEND );
606 0 : mpFS->singleElementNS( XML_a, XML_fillRect, FSEND );
607 0 : mpFS->endElementNS( XML_a, XML_stretch );
608 0 : }
609 :
610 0 : void DrawingML::WriteTransformation( const Rectangle& rRect,
611 : sal_Int32 nXmlNamespace, sal_Bool bFlipH, sal_Bool bFlipV, sal_Int32 nRotation )
612 : {
613 : mpFS->startElementNS( nXmlNamespace, XML_xfrm,
614 : XML_flipH, bFlipH ? "1" : NULL,
615 : XML_flipV, bFlipV ? "1" : NULL,
616 0 : XML_rot, (nRotation % 21600000) ? I32S( nRotation ) : NULL,
617 0 : FSEND );
618 :
619 0 : mpFS->singleElementNS( XML_a, XML_off, XML_x, IS( MM100toEMU( rRect.Left() ) ), XML_y, IS( MM100toEMU( rRect.Top() ) ), FSEND );
620 0 : mpFS->singleElementNS( XML_a, XML_ext, XML_cx, IS( MM100toEMU( rRect.GetWidth() ) ), XML_cy, IS( MM100toEMU( rRect.GetHeight() ) ), FSEND );
621 :
622 0 : mpFS->endElementNS( nXmlNamespace, XML_xfrm );
623 0 : }
624 :
625 0 : void DrawingML::WriteShapeTransformation( Reference< XShape > rXShape, sal_Int32 nXmlNamespace, sal_Bool bFlipH, sal_Bool bFlipV, sal_Bool bSuppressRotation )
626 : {
627 : DBG(printf( "write shape transformation\n" ));
628 :
629 0 : sal_Int32 nRotation=0;
630 0 : awt::Point aPos = rXShape->getPosition();
631 0 : awt::Size aSize = rXShape->getSize();
632 :
633 0 : if ( aSize.Width < 0 )
634 0 : aSize.Width = 1000;
635 0 : if ( aSize.Height < 0 )
636 0 : aSize.Height = 1000;
637 0 : if (!bSuppressRotation)
638 : {
639 0 : SdrObject* pShape = (SdrObject*) GetSdrObjectFromXShape( rXShape );
640 0 : nRotation=pShape->GetRotateAngle();
641 0 : aPos.X-=(1-cos(nRotation*F_PI18000))*aSize.Width/2-sin(nRotation*F_PI18000)*aSize.Height/2;
642 0 : aPos.Y-=(1-cos(nRotation*F_PI18000))*aSize.Height/2+sin(nRotation*F_PI18000)*aSize.Width/2;
643 : }
644 0 : WriteTransformation( Rectangle( Point( aPos.X, aPos.Y ), Size( aSize.Width, aSize.Height ) ), nXmlNamespace, bFlipH, bFlipV, PPTX_EXPORT_ROTATE_CLOCKWISIFY(nRotation) );
645 0 : }
646 :
647 0 : void DrawingML::WriteRunProperties( Reference< XPropertySet > rRun, sal_Bool bIsField )
648 : {
649 0 : Reference< XPropertySet > rXPropSet( rRun, UNO_QUERY );
650 0 : Reference< XPropertyState > rXPropState( rRun, UNO_QUERY );
651 0 : OUString usLanguage;
652 : PropertyState eState;
653 0 : sal_Int16 nScriptType = SvtLanguageOptions::GetScriptTypeOfLanguage( Application::GetSettings().GetLanguageTag().getLanguageType() );
654 0 : sal_Bool bComplex = ( nScriptType == ScriptType::COMPLEX );
655 0 : const char* bold = NULL;
656 0 : const char* italic = NULL;
657 0 : const char* underline = NULL;
658 0 : sal_Int32 nSize = 1800;
659 :
660 0 : if( GETAD( CharHeight ) )
661 0 : nSize = (sal_Int32) (100*(*((float*) mAny.getValue())));
662 :
663 0 : if ( ( bComplex && GETAD( CharWeightComplex ) ) || GETAD( CharWeight ) )
664 0 : if ( *((float*) mAny.getValue()) >= awt::FontWeight::SEMIBOLD )
665 0 : bold = "1";
666 :
667 0 : if ( ( bComplex && GETAD( CharPostureComplex ) ) || GETAD( CharPosture ) )
668 0 : switch ( *((awt::FontSlant*) mAny.getValue()) )
669 : {
670 : case awt::FontSlant_OBLIQUE :
671 : case awt::FontSlant_ITALIC :
672 0 : italic = "1";
673 0 : break;
674 : default:
675 0 : break;
676 : }
677 :
678 0 : if ( GETAD( CharUnderline ) )
679 0 : switch ( *((sal_Int16*) mAny.getValue()) )
680 : {
681 : case awt::FontUnderline::SINGLE :
682 0 : underline = "sng";
683 0 : break;
684 : case awt::FontUnderline::DOUBLE :
685 0 : underline = "dbl";
686 0 : break;
687 : case awt::FontUnderline::DOTTED :
688 0 : underline = "dotted";
689 0 : break;
690 : case awt::FontUnderline::DASH :
691 0 : underline = "dash";
692 0 : break;
693 : case awt::FontUnderline::LONGDASH :
694 0 : underline = "dashLong";
695 0 : break;
696 : case awt::FontUnderline::DASHDOT :
697 0 : underline = "dotDash";
698 0 : break;
699 : case awt::FontUnderline::DASHDOTDOT :
700 0 : underline = "dotDotDash";
701 0 : break;
702 : case awt::FontUnderline::WAVE :
703 0 : underline = "wavy";
704 0 : break;
705 : case awt::FontUnderline::DOUBLEWAVE :
706 0 : underline = "wavyDbl";
707 0 : break;
708 : case awt::FontUnderline::BOLD :
709 0 : underline = "heavy";
710 0 : break;
711 : case awt::FontUnderline::BOLDDOTTED :
712 0 : underline = "dottedHeavy";
713 0 : break;
714 : case awt::FontUnderline::BOLDDASH :
715 0 : underline = "dashHeavy";
716 0 : break;
717 : case awt::FontUnderline::BOLDLONGDASH :
718 0 : underline = "dashLongHeavy";
719 0 : break;
720 : case awt::FontUnderline::BOLDDASHDOT :
721 0 : underline = "dotDashHeavy";
722 0 : break;
723 : case awt::FontUnderline::BOLDDASHDOTDOT :
724 0 : underline = "dotDotDashHeavy";
725 0 : break;
726 : case awt::FontUnderline::BOLDWAVE :
727 0 : underline = "wavyHeavy";
728 0 : break;
729 : }
730 :
731 0 : if( GETA( CharLocale ) ) {
732 0 : com::sun::star::lang::Locale eLocale;
733 0 : mAny >>= eLocale;
734 :
735 0 : OUStringBuffer usLanguageBuffer = eLocale.Language;
736 0 : if( !eLocale.Country.isEmpty() ) {
737 0 : usLanguageBuffer.appendAscii( "-" );
738 0 : usLanguageBuffer.append( eLocale.Country );
739 : }
740 :
741 0 : if( usLanguageBuffer.getLength() )
742 0 : usLanguage = usLanguageBuffer.makeStringAndClear();
743 : }
744 :
745 : mpFS->startElementNS( XML_a, XML_rPr,
746 : XML_b, bold,
747 : XML_i, italic,
748 0 : XML_lang, usLanguage.isEmpty() ? NULL : USS( usLanguage ),
749 0 : XML_sz, nSize == 1800 ? NULL : IS( nSize ),
750 : XML_u, underline,
751 0 : FSEND );
752 :
753 : // mso doesn't like text color to be placed after typeface
754 0 : if( GETAD( CharColor ) ) {
755 0 : sal_uInt32 color = *((sal_uInt32*) mAny.getValue());
756 : DBG(printf("run color: %x auto: %x\n", static_cast<unsigned int>( color ), static_cast<unsigned int>( COL_AUTO )));
757 :
758 0 : if( color == COL_AUTO ) { // nCharColor depends to the background color
759 0 : sal_Bool bIsDark = sal_False;
760 0 : GET( bIsDark, IsBackgroundDark );
761 0 : color = bIsDark ? 0xffffff : 0x000000;
762 : }
763 0 : color &= 0xffffff;
764 :
765 : // TODO: special handle embossed/engraved
766 :
767 0 : WriteSolidFill( color );
768 : }
769 :
770 0 : if( GETAD( CharFontName ) ) {
771 0 : const char* typeface = NULL;
772 0 : const char* pitch = NULL;
773 0 : const char* charset = NULL;
774 0 : OUString usTypeface;
775 :
776 0 : mAny >>= usTypeface;
777 0 : String aSubstName( GetSubsFontName( usTypeface, SUBSFONT_ONLYONE | SUBSFONT_MS ) );
778 0 : if( aSubstName.Len() )
779 0 : typeface = USS( aSubstName );
780 : else
781 0 : typeface = USS( usTypeface );
782 :
783 : mpFS->singleElementNS( XML_a, XML_latin,
784 : XML_typeface, typeface,
785 : XML_pitchFamily, pitch,
786 : XML_charset, charset,
787 0 : FSEND );
788 : }
789 :
790 0 : if( ( bComplex && GETAD( CharFontNameComplex ) ) || ( !bComplex && GETAD( CharFontNameAsian ) ) ) {
791 0 : const char* typeface = NULL;
792 0 : const char* pitch = NULL;
793 0 : const char* charset = NULL;
794 0 : OUString usTypeface;
795 :
796 0 : mAny >>= usTypeface;
797 0 : String aSubstName( GetSubsFontName( usTypeface, SUBSFONT_ONLYONE | SUBSFONT_MS ) );
798 0 : if( aSubstName.Len() )
799 0 : typeface = USS( aSubstName );
800 : else
801 0 : typeface = USS( usTypeface );
802 :
803 : mpFS->singleElementNS( XML_a, bComplex ? XML_cs : XML_ea,
804 : XML_typeface, typeface,
805 : XML_pitchFamily, pitch,
806 : XML_charset, charset,
807 0 : FSEND );
808 : }
809 :
810 0 : if( bIsField ) {
811 0 : Reference< XTextField > rXTextField;
812 0 : GET( rXTextField, TextField );
813 0 : if( rXTextField.is() )
814 0 : rXPropSet.set( rXTextField, UNO_QUERY );
815 : }
816 :
817 : // field properties starts here
818 0 : if( GETA( URL ) ) {
819 0 : OUString sURL;
820 :
821 0 : mAny >>= sURL;
822 0 : if( !sURL.isEmpty() ) {
823 : OUString sRelId = mpFB->addRelation( mpFS->getOutputStream(),
824 : US( "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink" ),
825 0 : sURL, true );
826 :
827 : mpFS->singleElementNS( XML_a, XML_hlinkClick,
828 : FSNS( XML_r,XML_id ), USS( sRelId ),
829 0 : FSEND );
830 0 : }
831 : }
832 :
833 0 : mpFS->endElementNS( XML_a, XML_rPr );
834 0 : }
835 :
836 0 : const char* DrawingML::GetFieldType( ::com::sun::star::uno::Reference< ::com::sun::star::text::XTextRange > rRun, sal_Bool& bIsField )
837 : {
838 0 : const char* sType = NULL;
839 0 : Reference< XPropertySet > rXPropSet( rRun, UNO_QUERY );
840 0 : OUString aFieldType;
841 :
842 0 : if( GETA( TextPortionType ) ) {
843 0 : aFieldType = OUString( *(OUString*)mAny.getValue() );
844 : DBG(printf ("field type: %s\n", USS(aFieldType) ));
845 : }
846 :
847 0 : if( aFieldType == "TextField" ) {
848 0 : Reference< XTextField > rXTextField;
849 0 : GET( rXTextField, TextField );
850 0 : if( rXTextField.is() ) {
851 0 : bIsField = sal_True;
852 0 : rXPropSet.set( rXTextField, UNO_QUERY );
853 0 : if( rXPropSet.is() ) {
854 0 : String aFieldKind( rXTextField->getPresentation( sal_True ) );
855 : DBG(printf ("field kind: %s\n", USS(aFieldKind) ));
856 0 : if( aFieldKind == S( "Page" ) ) {
857 0 : return "slidenum";
858 0 : }
859 : // else if( aFieldKind == S( "URL" ) ) {
860 : // do not return here
861 : // and make URL field text run with hyperlink property later
862 : // }
863 : }
864 0 : }
865 : }
866 :
867 0 : return sType;
868 : }
869 :
870 0 : void DrawingML::GetUUID( OStringBuffer& rBuffer )
871 : {
872 0 : Sequence< sal_uInt8 > aSeq( 16 );
873 : static char cDigits[17] = "0123456789ABCDEF";
874 0 : rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True );
875 : int i;
876 :
877 0 : rBuffer.append( '{' );
878 0 : for( i = 0; i < 4; i++ ) {
879 0 : rBuffer.append( cDigits[ aSeq[i] >> 4 ] );
880 0 : rBuffer.append( cDigits[ aSeq[i] & 0xf ] );
881 : }
882 0 : rBuffer.append( '-' );
883 0 : for( ; i < 6; i++ ) {
884 0 : rBuffer.append( cDigits[ aSeq[i] >> 4 ] );
885 0 : rBuffer.append( cDigits[ aSeq[i] & 0xf ] );
886 : }
887 0 : rBuffer.append( '-' );
888 0 : for( ; i < 8; i++ ) {
889 0 : rBuffer.append( cDigits[ aSeq[i] >> 4 ] );
890 0 : rBuffer.append( cDigits[ aSeq[i] & 0xf ] );
891 : }
892 0 : rBuffer.append( '-' );
893 0 : for( ; i < 10; i++ ) {
894 0 : rBuffer.append( cDigits[ aSeq[i] >> 4 ] );
895 0 : rBuffer.append( cDigits[ aSeq[i] & 0xf ] );
896 : }
897 0 : rBuffer.append( '-' );
898 0 : for( ; i < 16; i++ ) {
899 0 : rBuffer.append( cDigits[ aSeq[i] >> 4 ] );
900 0 : rBuffer.append( cDigits[ aSeq[i] & 0xf ] );
901 : }
902 0 : rBuffer.append( '}' );
903 0 : }
904 :
905 0 : void DrawingML::WriteRun( Reference< XTextRange > rRun )
906 : {
907 : const char* sFieldType;
908 0 : sal_Bool bIsField = sal_False;
909 0 : OUString sText = rRun->getString();
910 :
911 0 : if( sText.isEmpty()) {
912 0 : Reference< XPropertySet > xPropSet( rRun, UNO_QUERY );
913 :
914 : try {
915 0 : if( !xPropSet.is() || !( xPropSet->getPropertyValue( S( "PlaceholderText" ) ) >>= sText ) )
916 : return;
917 0 : if( sText.isEmpty() )
918 : return;
919 : }
920 0 : catch (const Exception &) {
921 : return;
922 0 : }
923 : }
924 :
925 0 : sFieldType = GetFieldType( rRun, bIsField );
926 0 : if( ( sFieldType != NULL ) ) {
927 0 : OStringBuffer sUUID(39);
928 :
929 0 : GetUUID( sUUID );
930 : mpFS->startElementNS( XML_a, XML_fld,
931 : XML_id, sUUID.getStr(),
932 : XML_type, sFieldType,
933 0 : FSEND );
934 : } else
935 0 : mpFS->startElementNS( XML_a, XML_r, FSEND );
936 :
937 0 : Reference< XPropertySet > xPropSet( rRun, uno::UNO_QUERY );
938 0 : WriteRunProperties( xPropSet, bIsField );
939 :
940 0 : mpFS->startElementNS( XML_a, XML_t, FSEND );
941 0 : mpFS->writeEscaped( sText );
942 0 : mpFS->endElementNS( XML_a, XML_t );
943 :
944 0 : if( sFieldType )
945 0 : mpFS->endElementNS( XML_a, XML_fld );
946 : else
947 0 : mpFS->endElementNS( XML_a, XML_r );
948 : }
949 :
950 : #define AUTONUM(x) \
951 : if( bPBoth ) \
952 : pAutoNumType = #x "ParenBoth"; \
953 : else if( bPBehind ) \
954 : pAutoNumType = #x "ParenR"; \
955 : else if( bSDot ) \
956 : pAutoNumType = #x "Period";
957 :
958 0 : inline static const char* GetAutoNumType( sal_Int16 nNumberingType, bool bSDot, bool bPBehind, bool bPBoth )
959 : {
960 0 : const char* pAutoNumType = NULL;
961 :
962 0 : switch( (SvxExtNumType)nNumberingType )
963 : {
964 : case SVX_NUM_CHARS_UPPER_LETTER_N :
965 : case SVX_NUM_CHARS_UPPER_LETTER :
966 0 : AUTONUM( alphaUc );
967 0 : break;
968 : case SVX_NUM_CHARS_LOWER_LETTER_N :
969 : case SVX_NUM_CHARS_LOWER_LETTER :
970 0 : AUTONUM( alphaLc );
971 0 : break;
972 : case SVX_NUM_ROMAN_UPPER :
973 0 : AUTONUM( romanUc );
974 0 : break;
975 : case SVX_NUM_ROMAN_LOWER :
976 0 : AUTONUM( romanLc );
977 0 : break;
978 : case SVX_NUM_ARABIC :
979 0 : AUTONUM( arabic )
980 : else
981 0 : pAutoNumType = "arabicPlain";
982 0 : break;
983 : default:
984 0 : break;
985 : }
986 :
987 0 : return pAutoNumType;
988 : }
989 :
990 0 : void DrawingML::WriteParagraphNumbering( Reference< XPropertySet > rXPropSet, sal_Int16 nLevel )
991 : {
992 0 : if( nLevel >= 0 && GETA( NumberingRules ) )
993 : {
994 0 : Reference< XIndexAccess > rXIndexAccess;
995 :
996 0 : if ( ( mAny >>= rXIndexAccess ) && nLevel < rXIndexAccess->getCount() )
997 : {
998 : DBG(printf ("numbering rules\n"));
999 :
1000 0 : Sequence< PropertyValue > aPropertySequence;
1001 0 : rXIndexAccess->getByIndex( nLevel ) >>= aPropertySequence;
1002 :
1003 0 : const PropertyValue* pPropValue = aPropertySequence.getArray();
1004 :
1005 0 : sal_Int32 nPropertyCount = aPropertySequence.getLength();
1006 :
1007 0 : if ( nPropertyCount ) {
1008 :
1009 0 : sal_Int16 nNumberingType = -1;
1010 0 : bool bSDot = false;
1011 0 : bool bPBehind = false;
1012 0 : bool bPBoth = false;
1013 0 : sal_Unicode aBulletChar = 0x2022; // a bullet
1014 0 : awt::FontDescriptor aFontDesc;
1015 0 : bool bHasFontDesc = false;
1016 0 : OUString aGraphicURL;
1017 0 : sal_Int16 nBulletRelSize = 0;
1018 :
1019 0 : for ( sal_Int32 i = 0; i < nPropertyCount; i++ ) {
1020 0 : const void* pValue = pPropValue[ i ].Value.getValue();
1021 0 : if ( pValue ) {
1022 0 : OUString aPropName( pPropValue[ i ].Name );
1023 : DBG(printf ("pro name: %s\n", OUStringToOString( aPropName, RTL_TEXTENCODING_UTF8 ).getStr()));
1024 0 : if ( aPropName == "NumberingType" )
1025 0 : nNumberingType = *( (sal_Int16*)pValue );
1026 0 : else if ( aPropName == "Prefix" ) {
1027 0 : if( *(OUString*)pValue == US( ")" ) )
1028 0 : bPBoth = true;
1029 0 : } else if ( aPropName == "Suffix" ) {
1030 0 : if( *(OUString*)pValue == US( "." ) )
1031 0 : bSDot = true;
1032 0 : else if( *(OUString*)pValue == US( ")" ) )
1033 0 : bPBehind = true;
1034 0 : } else if ( aPropName == "BulletChar" )
1035 : {
1036 0 : aBulletChar = String ( *( (String*)pValue ) ).GetChar( 0 );
1037 : //printf ("bullet char: %d\n", aBulletChar.getStr());
1038 : }
1039 0 : else if ( aPropName == "BulletFont" )
1040 : {
1041 0 : aFontDesc = *( (awt::FontDescriptor*)pValue );
1042 0 : bHasFontDesc = true;
1043 :
1044 : // Our numbullet dialog has set the wrong textencoding for our "StarSymbol" font,
1045 : // instead of a Unicode encoding the encoding RTL_TEXTENCODING_SYMBOL was used.
1046 : // Because there might exist a lot of damaged documemts I added this two lines
1047 : // which fixes the bullet problem for the export.
1048 0 : if ( aFontDesc.Name == "StarSymbol" )
1049 0 : aFontDesc.CharSet = RTL_TEXTENCODING_MS_1252;
1050 :
1051 0 : } else if ( aPropName == "BulletRelSize" ) {
1052 0 : nBulletRelSize = *( (sal_Int16*)pValue );
1053 0 : } else if ( aPropName == "GraphicURL" ) {
1054 0 : aGraphicURL = ( *(OUString*)pValue );
1055 : DBG(printf ("graphic url: %s\n", OUStringToOString( aGraphicURL, RTL_TEXTENCODING_UTF8 ).getStr()));
1056 0 : } else if ( aPropName == "GraphicSize" )
1057 : {
1058 0 : if ( pPropValue[ i ].Value.getValueType() == ::getCppuType( (awt::Size*)0) )
1059 : {
1060 : // don't cast awt::Size to Size as on 64-bits they are not the same.
1061 0 : ::com::sun::star::awt::Size aSize;
1062 0 : pPropValue[ i ].Value >>= aSize;
1063 : //aBuGraSize.nA = aSize.Width;
1064 : //aBuGraSize.nB = aSize.Height;
1065 : DBG(printf("graphic size: %dx%d\n", int( aSize.Width ), int( aSize.Height )));
1066 : }
1067 0 : }
1068 : }
1069 : }
1070 :
1071 0 : const char* pAutoNumType = GetAutoNumType( nNumberingType, bSDot, bPBehind, bPBoth );
1072 :
1073 0 : if( nLevel >= 0 ) {
1074 0 : if( !aGraphicURL.isEmpty() ) {
1075 0 : OUString sRelId = WriteImage( aGraphicURL );
1076 :
1077 0 : mpFS->startElementNS( XML_a, XML_buBlip, FSEND );
1078 0 : mpFS->singleElementNS( XML_a, XML_blip, FSNS( XML_r, XML_embed ), USS( sRelId ), FSEND );
1079 0 : mpFS->endElementNS( XML_a, XML_buBlip );
1080 : } else {
1081 0 : if( nBulletRelSize && nBulletRelSize != 100 )
1082 : mpFS->singleElementNS( XML_a, XML_buSzPct,
1083 0 : XML_val, IS( std::min( (sal_Int32)25000, std::max( (sal_Int32)400000, 1000*( (sal_Int32)nBulletRelSize ) ) ) ), FSEND );
1084 0 : if( bHasFontDesc )
1085 : mpFS->singleElementNS( XML_a, XML_buFont,
1086 : XML_typeface, OUStringToOString( aFontDesc.Name, RTL_TEXTENCODING_UTF8 ).getStr(),
1087 : XML_charset, (aFontDesc.CharSet == awt::CharSet::SYMBOL) ? "2" : NULL,
1088 0 : FSEND );
1089 :
1090 0 : if( pAutoNumType )
1091 0 : mpFS->singleElementNS( XML_a, XML_buAutoNum, XML_type, pAutoNumType, FSEND );
1092 : else {
1093 0 : aBulletChar = SubstituteBullet( aBulletChar, aFontDesc );
1094 0 : mpFS->singleElementNS( XML_a, XML_buChar, XML_char, USS( OUString( aBulletChar ) ), FSEND );
1095 : }
1096 : }
1097 0 : }
1098 0 : }
1099 0 : }
1100 : }
1101 0 : }
1102 :
1103 0 : const char* DrawingML::GetAlignment( sal_Int32 nAlignment )
1104 : {
1105 0 : const char* sAlignment = NULL;
1106 :
1107 0 : switch( nAlignment ) {
1108 : case style::ParagraphAdjust_CENTER:
1109 0 : sAlignment = "ctr";
1110 0 : break;
1111 : case style::ParagraphAdjust_RIGHT:
1112 0 : sAlignment = "r";
1113 0 : break;
1114 : case style::ParagraphAdjust_BLOCK:
1115 0 : sAlignment = "just";
1116 0 : break;
1117 : default:
1118 : ;
1119 : }
1120 :
1121 0 : return sAlignment;
1122 : }
1123 :
1124 0 : void DrawingML::WriteLinespacing( LineSpacing& rSpacing )
1125 : {
1126 0 : if( rSpacing.Mode == LineSpacingMode::PROP )
1127 : mpFS->singleElementNS( XML_a, XML_spcPct,
1128 : XML_val, I32S( ((sal_Int32)rSpacing.Height)*1000 ),
1129 0 : FSEND );
1130 : else
1131 : mpFS->singleElementNS( XML_a, XML_spcPts,
1132 : XML_val, I32S( rSpacing.Height ),
1133 0 : FSEND );
1134 0 : }
1135 :
1136 0 : void DrawingML::WriteParagraphProperties( Reference< XTextContent > rParagraph )
1137 : {
1138 0 : Reference< XPropertySet > rXPropSet( rParagraph, UNO_QUERY );
1139 0 : Reference< XPropertyState > rXPropState( rParagraph, UNO_QUERY );
1140 : PropertyState eState;
1141 :
1142 0 : if( !rXPropSet.is() || !rXPropState.is() )
1143 0 : return;
1144 :
1145 0 : sal_Int16 nLevel = -1;
1146 0 : GET( nLevel, NumberingLevel );
1147 :
1148 0 : sal_Int16 nAlignment( style::ParagraphAdjust_LEFT );
1149 0 : GET( nAlignment, ParaAdjust );
1150 :
1151 0 : sal_Bool bHasLinespacing = sal_False;
1152 0 : LineSpacing aLineSpacing;
1153 0 : if( GETAD( ParaLineSpacing ) )
1154 0 : bHasLinespacing = ( mAny >>= aLineSpacing );
1155 :
1156 0 : if( nLevel != -1
1157 : || nAlignment != style::ParagraphAdjust_LEFT
1158 : || bHasLinespacing ) {
1159 : mpFS->startElementNS( XML_a, XML_pPr,
1160 0 : XML_lvl, nLevel > 0 ? I32S( nLevel ) : NULL,
1161 : XML_marL, NULL,
1162 : XML_algn, GetAlignment( nAlignment ),
1163 0 : FSEND );
1164 :
1165 0 : if( bHasLinespacing ) {
1166 0 : mpFS->startElementNS( XML_a, XML_lnSpc, FSEND );
1167 0 : WriteLinespacing( aLineSpacing );
1168 0 : mpFS->endElementNS( XML_a, XML_lnSpc );
1169 : }
1170 :
1171 0 : WriteParagraphNumbering( rXPropSet, nLevel );
1172 :
1173 0 : mpFS->endElementNS( XML_a, XML_pPr );
1174 0 : }
1175 : }
1176 :
1177 0 : void DrawingML::WriteParagraph( Reference< XTextContent > rParagraph )
1178 : {
1179 0 : Reference< XEnumerationAccess > access( rParagraph, UNO_QUERY );
1180 0 : if( !access.is() )
1181 : return;
1182 :
1183 0 : Reference< XEnumeration > enumeration( access->createEnumeration() );
1184 0 : if( !enumeration.is() )
1185 : return;
1186 :
1187 0 : mpFS->startElementNS( XML_a, XML_p, FSEND );
1188 :
1189 0 : sal_Bool bPropertiesWritten = sal_False;
1190 0 : while( enumeration->hasMoreElements() ) {
1191 0 : Reference< XTextRange > run;
1192 0 : Any any ( enumeration->nextElement() );
1193 :
1194 0 : if (any >>= run) {
1195 0 : if( !bPropertiesWritten ) {
1196 0 : WriteParagraphProperties( rParagraph );
1197 0 : bPropertiesWritten = sal_True;
1198 : }
1199 0 : WriteRun( run );
1200 : }
1201 0 : }
1202 0 : mpFS->singleElementNS( XML_a, XML_endParaRPr, FSEND );
1203 :
1204 0 : mpFS->endElementNS( XML_a, XML_p );
1205 : }
1206 :
1207 0 : void DrawingML::WriteText( Reference< XInterface > rXIface )
1208 : {
1209 0 : Reference< XText > xXText( rXIface, UNO_QUERY );
1210 0 : Reference< XPropertySet > rXPropSet( rXIface, UNO_QUERY );
1211 :
1212 0 : if( !xXText.is() )
1213 : return;
1214 :
1215 : #define DEFLRINS 254
1216 : #define DEFTBINS 127
1217 : sal_Int32 nLeft, nRight, nTop, nBottom;
1218 0 : nLeft = nRight = DEFLRINS;
1219 0 : nTop = nBottom = DEFTBINS;
1220 :
1221 : // top inset looks a bit different compared to ppt export
1222 : // check if something related doesn't work as expected
1223 0 : GET( nLeft, TextLeftDistance );
1224 0 : GET( nRight, TextRightDistance );
1225 0 : GET( nTop, TextUpperDistance );
1226 0 : GET( nBottom, TextLowerDistance );
1227 :
1228 0 : TextVerticalAdjust eVerticalAlignment( TextVerticalAdjust_TOP );
1229 0 : const char* sVerticalAlignment = NULL;
1230 0 : GET( eVerticalAlignment, TextVerticalAdjust );
1231 0 : switch( eVerticalAlignment ) {
1232 : case TextVerticalAdjust_BOTTOM:
1233 0 : sVerticalAlignment = "b";
1234 0 : break;
1235 : case TextVerticalAdjust_CENTER:
1236 0 : sVerticalAlignment = "ctr";
1237 0 : break;
1238 : case TextVerticalAdjust_TOP:
1239 : default:
1240 : ;
1241 : }
1242 :
1243 0 : const char* sWritingMode = NULL;
1244 0 : sal_Bool bVertical = sal_False;
1245 0 : if( GETA( TextWritingMode ) ) {
1246 : WritingMode eMode;
1247 :
1248 0 : if( ( mAny >>= eMode ) && eMode == WritingMode_TB_RL ) {
1249 0 : sWritingMode = "vert";
1250 0 : bVertical = sal_True;
1251 : }
1252 : }
1253 :
1254 0 : if ( GETA( CustomShapeGeometry ) )
1255 : {
1256 0 : Sequence< PropertyValue > aProps;
1257 0 : if ( mAny >>= aProps )
1258 : {
1259 0 : for ( sal_Int32 i = 0, nElems = aProps.getLength(); i < nElems; ++i )
1260 : {
1261 0 : sal_Int32 nTextRotateAngle = 0;
1262 0 : if ( aProps[ i ].Name.equals( "TextPreRotateAngle" ) && ( aProps[ i ].Value >>= nTextRotateAngle ) )
1263 : {
1264 0 : if ( nTextRotateAngle == -90 )
1265 : {
1266 0 : sWritingMode = "vert";
1267 0 : bVertical = sal_True;
1268 : }
1269 : break;
1270 : }
1271 : }
1272 0 : }
1273 : }
1274 :
1275 0 : TextHorizontalAdjust eHorizontalAlignment( TextHorizontalAdjust_CENTER );
1276 0 : bool bHorizontalCenter = false;
1277 0 : GET( eHorizontalAlignment, TextHorizontalAdjust );
1278 0 : if( eHorizontalAlignment == TextHorizontalAdjust_CENTER )
1279 0 : bHorizontalCenter = true;
1280 0 : else if( bVertical && eHorizontalAlignment == TextHorizontalAdjust_LEFT )
1281 0 : sVerticalAlignment = "b";
1282 :
1283 0 : sal_Bool bHasWrap = sal_False;
1284 0 : sal_Bool bWrap = sal_False;
1285 0 : if( GETA( TextWordWrap ) ) {
1286 0 : mAny >>= bWrap;
1287 0 : bHasWrap = sal_True;
1288 : }
1289 :
1290 : mpFS->singleElementNS( XML_a, XML_bodyPr,
1291 0 : XML_wrap, bHasWrap && !bWrap ? "none" : NULL,
1292 0 : XML_lIns, (nLeft != DEFLRINS) ? IS( MM100toEMU( nLeft ) ) : NULL,
1293 0 : XML_rIns, (nRight != DEFLRINS) ? IS( MM100toEMU( nRight ) ) : NULL,
1294 0 : XML_tIns, (nTop != DEFTBINS) ? IS( MM100toEMU( nTop ) ) : NULL,
1295 0 : XML_bIns, (nBottom != DEFTBINS) ? IS( MM100toEMU( nBottom ) ) : NULL,
1296 : XML_anchor, sVerticalAlignment,
1297 : XML_anchorCtr, bHorizontalCenter ? "1" : NULL,
1298 : XML_vert, sWritingMode,
1299 0 : FSEND );
1300 :
1301 0 : Reference< XEnumerationAccess > access( xXText, UNO_QUERY );
1302 0 : if( !access.is() )
1303 : return;
1304 :
1305 0 : Reference< XEnumeration > enumeration( access->createEnumeration() );
1306 0 : if( !enumeration.is() )
1307 : return;
1308 :
1309 0 : while( enumeration->hasMoreElements() ) {
1310 0 : Reference< XTextContent > paragraph;
1311 0 : Any any ( enumeration->nextElement() );
1312 :
1313 0 : if( any >>= paragraph)
1314 0 : WriteParagraph( paragraph );
1315 0 : }
1316 :
1317 : }
1318 :
1319 0 : void DrawingML::WritePresetShape( const char* pShape )
1320 : {
1321 : mpFS->startElementNS( XML_a, XML_prstGeom,
1322 : XML_prst, pShape,
1323 0 : FSEND );
1324 0 : mpFS->singleElementNS( XML_a, XML_avLst, FSEND );
1325 0 : mpFS->endElementNS( XML_a, XML_prstGeom );
1326 0 : }
1327 :
1328 0 : void DrawingML::WritePresetShape( const char* pShape, MSO_SPT eShapeType, sal_Bool bPredefinedHandlesUsed, sal_Int32 nAdjustmentsWhichNeedsToBeConverted, const PropertyValue& rProp )
1329 : {
1330 : mpFS->startElementNS( XML_a, XML_prstGeom,
1331 : XML_prst, pShape,
1332 0 : FSEND );
1333 0 : mpFS->startElementNS( XML_a, XML_avLst, FSEND );
1334 :
1335 0 : Sequence< drawing::EnhancedCustomShapeAdjustmentValue > aAdjustmentSeq;
1336 0 : if ( ( rProp.Value >>= aAdjustmentSeq )
1337 : && eShapeType != mso_sptActionButtonForwardNext // we have adjustments values for these type of shape, but MSO doesn't like them
1338 : && eShapeType != mso_sptActionButtonBackPrevious // so they are now disabled
1339 : ) {
1340 : DBG(printf("adj seq len: %d\n", int( aAdjustmentSeq.getLength() )));
1341 0 : if ( bPredefinedHandlesUsed )
1342 0 : EscherPropertyContainer::LookForPolarHandles( eShapeType, nAdjustmentsWhichNeedsToBeConverted );
1343 :
1344 0 : sal_Int32 nValue, nLength = aAdjustmentSeq.getLength();
1345 0 : for( sal_Int32 i=0; i < nLength; i++ )
1346 0 : if( EscherPropertyContainer::GetAdjustmentValue( aAdjustmentSeq[ i ], i, nAdjustmentsWhichNeedsToBeConverted, nValue ) )
1347 : mpFS->singleElementNS( XML_a, XML_gd,
1348 0 : XML_name, aAdjustmentSeq[ i ].Name.getLength() > 0 ? USS(aAdjustmentSeq[ i ].Name) : (nLength > 1 ? OString( "adj" + OString::valueOf( i + 1 ) ).getStr() : "adj"),
1349 0 : XML_fmla, OString("val " + OString::valueOf( nValue )).getStr(),
1350 0 : FSEND );
1351 : }
1352 :
1353 0 : mpFS->endElementNS( XML_a, XML_avLst );
1354 0 : mpFS->endElementNS( XML_a, XML_prstGeom );
1355 0 : }
1356 :
1357 0 : void DrawingML::WritePolyPolygon( const PolyPolygon& rPolyPolygon )
1358 : {
1359 0 : if( rPolyPolygon.Count() < 1 )
1360 0 : return;
1361 :
1362 0 : mpFS->startElementNS( XML_a, XML_custGeom, FSEND );
1363 0 : mpFS->singleElementNS( XML_a, XML_avLst, FSEND );
1364 0 : mpFS->singleElementNS( XML_a, XML_gdLst, FSEND );
1365 0 : mpFS->singleElementNS( XML_a, XML_ahLst, FSEND );
1366 : mpFS->singleElementNS( XML_a, XML_rect,
1367 : XML_l, "0",
1368 : XML_t, "0",
1369 : XML_r, "r",
1370 : XML_b, "b",
1371 0 : FSEND );
1372 :
1373 0 : mpFS->startElementNS( XML_a, XML_pathLst, FSEND );
1374 :
1375 0 : for( sal_uInt16 i = 0; i < rPolyPolygon.Count(); i ++ ) {
1376 :
1377 0 : const Polygon& rPoly = rPolyPolygon[ i ];
1378 0 : Rectangle aRect( rPoly.GetBoundRect() );
1379 0 : sal_Bool bBezier = sal_False;
1380 :
1381 : mpFS->startElementNS( XML_a, XML_path,
1382 0 : XML_w, I64S( aRect.GetWidth() ),
1383 0 : XML_h, I64S( aRect.GetHeight() ),
1384 0 : FSEND );
1385 :
1386 0 : if( rPoly.GetSize() > 0 )
1387 : {
1388 0 : mpFS->startElementNS( XML_a, XML_moveTo, FSEND );
1389 :
1390 : mpFS->singleElementNS( XML_a, XML_pt,
1391 0 : XML_x, I64S( rPoly[ 0 ].X() - aRect.Left() ),
1392 0 : XML_y, I64S( rPoly[ 0 ].Y() - aRect.Top() ),
1393 0 : FSEND );
1394 :
1395 0 : mpFS->endElementNS( XML_a, XML_moveTo );
1396 : }
1397 :
1398 0 : for( sal_uInt16 j = 1; j < rPoly.GetSize(); j ++ )
1399 : {
1400 0 : enum PolyFlags flags = rPoly.GetFlags(j);
1401 0 : if( flags == POLY_CONTROL && !bBezier )
1402 : {
1403 0 : mpFS->startElementNS( XML_a, XML_cubicBezTo, FSEND );
1404 0 : bBezier = sal_True;
1405 : }
1406 0 : else if( flags == POLY_NORMAL && !bBezier )
1407 0 : mpFS->startElementNS( XML_a, XML_lnTo, FSEND );
1408 :
1409 : mpFS->singleElementNS( XML_a, XML_pt,
1410 0 : XML_x, I64S( rPoly[j].X() - aRect.Left() ),
1411 0 : XML_y, I64S( rPoly[j].Y() - aRect.Top() ),
1412 0 : FSEND );
1413 :
1414 0 : if( ( flags == POLY_NORMAL || flags == POLY_SYMMTR ) && bBezier )
1415 : {
1416 0 : mpFS->endElementNS( XML_a, XML_cubicBezTo );
1417 0 : bBezier = sal_False;
1418 : }
1419 0 : else if( flags == POLY_NORMAL && !bBezier )
1420 0 : mpFS->endElementNS( XML_a, XML_lnTo );
1421 0 : else if( bBezier && ( j % 3 ) == 0 )
1422 : {
1423 : // //a:cubicBezTo can only contain 3 //a:pt elements, so we
1424 : // need to break things up...
1425 0 : mpFS->endElementNS( XML_a, XML_cubicBezTo );
1426 0 : mpFS->startElementNS( XML_a, XML_cubicBezTo, FSEND );
1427 : }
1428 : }
1429 :
1430 0 : mpFS->endElementNS( XML_a, XML_path );
1431 : }
1432 :
1433 0 : mpFS->endElementNS( XML_a, XML_pathLst );
1434 :
1435 0 : mpFS->endElementNS( XML_a, XML_custGeom );
1436 : }
1437 :
1438 0 : void DrawingML::WriteConnectorConnections( EscherConnectorListEntry& rConnectorEntry, sal_Int32 nStartID, sal_Int32 nEndID )
1439 : {
1440 0 : if( nStartID != -1 )
1441 : mpFS->singleElementNS( XML_a, XML_stCxn,
1442 : XML_id, I32S( nStartID ),
1443 0 : XML_idx, I64S( rConnectorEntry.GetConnectorRule( sal_True ) ),
1444 0 : FSEND );
1445 0 : if( nEndID != -1 )
1446 : mpFS->singleElementNS( XML_a, XML_endCxn,
1447 : XML_id, I32S( nEndID ),
1448 0 : XML_idx, I64S( rConnectorEntry.GetConnectorRule( sal_False ) ),
1449 0 : FSEND );
1450 0 : }
1451 :
1452 0 : sal_Unicode DrawingML::SubstituteBullet( sal_Unicode cBulletId, ::com::sun::star::awt::FontDescriptor& rFontDesc )
1453 : {
1454 0 : if ( rFontDesc.Name.equalsIgnoreAsciiCase("starsymbol") || rFontDesc.Name.equalsIgnoreAsciiCase("opensymbol") )
1455 : {
1456 0 : rtl_TextEncoding eCharSet = rFontDesc.CharSet;
1457 0 : cBulletId = msfilter::util::bestFitOpenSymbolToMSFont(cBulletId, eCharSet, rFontDesc.Name);
1458 0 : rFontDesc.CharSet = eCharSet;
1459 : }
1460 :
1461 0 : return cBulletId;
1462 : }
1463 :
1464 0 : sax_fastparser::FSHelperPtr DrawingML::CreateOutputStream (
1465 : const OUString& sFullStream,
1466 : const OUString& sRelativeStream,
1467 : const Reference< XOutputStream >& xParentRelation,
1468 : const char* sContentType,
1469 : const char* sRelationshipType,
1470 : OUString* pRelationshipId )
1471 : {
1472 0 : OUString sRelationshipId;
1473 0 : if (xParentRelation.is())
1474 0 : sRelationshipId = GetFB()->addRelation( xParentRelation, OUString::createFromAscii( sRelationshipType), sRelativeStream );
1475 : else
1476 0 : sRelationshipId = GetFB()->addRelation( OUString::createFromAscii( sRelationshipType ), sRelativeStream );
1477 :
1478 0 : if( pRelationshipId )
1479 0 : *pRelationshipId = sRelationshipId;
1480 :
1481 0 : sax_fastparser::FSHelperPtr p = GetFB()->openFragmentStreamWithSerializer( sFullStream, OUString::createFromAscii( sContentType ) );
1482 :
1483 0 : return p;
1484 : }
1485 :
1486 0 : void DrawingML::WriteFill( Reference< XPropertySet > xPropSet )
1487 : {
1488 0 : if ( !GetProperty( xPropSet, S( "FillStyle" ) ) )
1489 : return;
1490 0 : FillStyle aFillStyle( FillStyle_NONE );
1491 0 : xPropSet->getPropertyValue( S( "FillStyle" ) ) >>= aFillStyle;
1492 :
1493 0 : if( aFillStyle == FillStyle_NONE ||
1494 : aFillStyle == FillStyle_HATCH )
1495 : return;
1496 :
1497 0 : switch( aFillStyle )
1498 : {
1499 : case ::com::sun::star::drawing::FillStyle_SOLID :
1500 0 : WriteSolidFill( xPropSet );
1501 0 : break;
1502 : case ::com::sun::star::drawing::FillStyle_GRADIENT :
1503 0 : WriteGradientFill( xPropSet );
1504 0 : break;
1505 : case ::com::sun::star::drawing::FillStyle_BITMAP :
1506 0 : WriteBlipFill( xPropSet, S( "FillBitmapURL" ) );
1507 0 : break;
1508 : default:
1509 : ;
1510 : }
1511 :
1512 : return;
1513 : }
1514 :
1515 : }
1516 51 : }
1517 :
1518 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|