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