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