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 case GFX_LINK_TYPE_NATIVE_JPG: 430 sMediaType = US( "image/jpeg" ); 431 sExtension = ".jpeg"; 432 break; 433 case GFX_LINK_TYPE_NATIVE_PNG: 434 sMediaType = US( "image/png" ); 435 sExtension = ".png"; 436 break; 437 case GFX_LINK_TYPE_NATIVE_TIF: 438 sMediaType = US( "image/tiff" ); 439 sExtension = ".tiff"; 440 break; 441 case GFX_LINK_TYPE_NATIVE_WMF: 442 sMediaType = US( "image/x-wmf" ); 443 sExtension = ".wmf"; 444 break; 445 case GFX_LINK_TYPE_NATIVE_MET: 446 sMediaType = US( "image/x-met" ); 447 sExtension = ".met"; 448 break; 449 case GFX_LINK_TYPE_NATIVE_PCT: 450 sMediaType = US( "image/x-pict" ); 451 sExtension = ".pct"; 452 break; 453 default: { 454 GraphicType aType = rGraphic.GetType(); 455 if ( aType == GRAPHIC_BITMAP ) { 456 GraphicConverter::Export( aStream, rGraphic, CVT_PNG ); 457 sMediaType = US( "image/png" ); 458 sExtension = ".png"; 459 } else if ( aType == GRAPHIC_GDIMETAFILE ) { 460 GraphicConverter::Export( aStream, rGraphic, CVT_EMF ); 461 sMediaType = US( "image/x-emf" ); 462 sExtension = ".emf"; 463 } else { 464 OSL_TRACE( "unhandled graphic type" ); 465 break; 466 } 467 468 aData = aStream.GetData(); 469 nDataSize = aStream.GetSize(); 470 break; 471 } 472 } 473 474 const char *pComponent = NULL; 475 switch ( meDocumentType ) 476 { 477 case DOCUMENT_DOCX: pComponent = "word"; break; 478 case DOCUMENT_PPTX: pComponent = "ppt"; break; 479 case DOCUMENT_XLSX: pComponent = "xl"; break; 480 } 481 482 Reference< XOutputStream > xOutStream = mpFB->openOutputStream( OUStringBuffer() 483 .appendAscii( pComponent ) 484 .appendAscii( "/media/image" ) 485 .append( (sal_Int32) mnImageCounter ) 486 .appendAscii( sExtension ) 487 .makeStringAndClear(), 488 sMediaType ); 489 xOutStream->writeBytes( Sequence< sal_Int8 >( (const sal_Int8*) aData, nDataSize ) ); 490 xOutStream->closeOutput(); 491 492 const char *pImagePrefix = NULL; 493 switch ( meDocumentType ) 494 { 495 case DOCUMENT_DOCX: 496 pImagePrefix = "media/image"; 497 break; 498 case DOCUMENT_PPTX: 499 case DOCUMENT_XLSX: 500 pImagePrefix = "../media/image"; 501 break; 502 } 503 504 sRelId = mpFB->addRelation( mpFS->getOutputStream(), 505 US( "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" ), 506 OUStringBuffer() 507 .appendAscii( pImagePrefix ) 508 .append( (sal_Int32) mnImageCounter ++ ) 509 .appendAscii( sExtension ) 510 .makeStringAndClear() ); 511 512 return sRelId; 513 } 514 515 OUString DrawingML::WriteBlip( OUString& rURL ) 516 { 517 OUString sRelId = WriteImage( rURL ); 518 519 mpFS->singleElementNS( XML_a, XML_blip, 520 FSNS( XML_r, XML_embed), OUStringToOString( sRelId, RTL_TEXTENCODING_UTF8 ).getStr(), 521 FSEND ); 522 523 return sRelId; 524 } 525 526 void DrawingML::WriteBlipMode( Reference< XPropertySet > rXPropSet ) 527 { 528 BitmapMode eBitmapMode( BitmapMode_NO_REPEAT ); 529 if (GetProperty( rXPropSet, S( "FillBitmapMode" ) ) ) 530 mAny >>= eBitmapMode; 531 532 DBG(printf("fill bitmap mode: %d\n", eBitmapMode)); 533 534 switch (eBitmapMode) { 535 case BitmapMode_REPEAT: 536 mpFS->singleElementNS( XML_a, XML_tile, FSEND ); 537 break; 538 default: 539 ; 540 } 541 } 542 543 void DrawingML::WriteBlipFill( Reference< XPropertySet > rXPropSet, String sURLPropName ) 544 { 545 WriteBlipFill( rXPropSet, sURLPropName, XML_a ); 546 } 547 548 void DrawingML::WriteBlipFill( Reference< XPropertySet > rXPropSet, String sURLPropName, sal_Int32 nXmlNamespace ) 549 { 550 if ( GetProperty( rXPropSet, sURLPropName ) ) { 551 OUString aURL; 552 mAny >>= aURL; 553 554 DBG(printf ("URL: %s\n", OUStringToOString( aURL, RTL_TEXTENCODING_UTF8 ).getStr() )); 555 556 if( !aURL.getLength() ) 557 return; 558 559 mpFS->startElementNS( nXmlNamespace , XML_blipFill, FSEND ); 560 561 WriteBlip( aURL ); 562 563 if( sURLPropName == S( "FillBitmapURL" ) ) 564 WriteBlipMode( rXPropSet ); 565 else if( GetProperty( rXPropSet, S( "FillBitmapStretch" ) ) ) { 566 bool bStretch = false; 567 mAny >>= bStretch; 568 569 if( bStretch ) 570 WriteStretch(); 571 } 572 573 mpFS->endElementNS( nXmlNamespace, XML_blipFill ); 574 } 575 } 576 577 void DrawingML::WriteStretch() 578 { 579 mpFS->startElementNS( XML_a, XML_stretch, FSEND ); 580 mpFS->singleElementNS( XML_a, XML_fillRect, FSEND ); 581 mpFS->endElementNS( XML_a, XML_stretch ); 582 } 583 584 void DrawingML::WriteTransformation( const Rectangle& rRect, 585 sal_Bool bFlipH, sal_Bool bFlipV, sal_Int32 nRotation ) 586 { 587 mpFS->startElementNS( XML_a, XML_xfrm, 588 XML_flipH, bFlipH ? "1" : NULL, 589 XML_flipV, bFlipV ? "1" : NULL, 590 XML_rot, nRotation ? I32S( nRotation ) : NULL, 591 FSEND ); 592 593 mpFS->singleElementNS( XML_a, XML_off, XML_x, IS( MM100toEMU( rRect.Left() ) ), XML_y, IS( MM100toEMU( rRect.Top() ) ), FSEND ); 594 mpFS->singleElementNS( XML_a, XML_ext, XML_cx, IS( MM100toEMU( rRect.GetWidth() ) ), XML_cy, IS( MM100toEMU( rRect.GetHeight() ) ), FSEND ); 595 596 mpFS->endElementNS( XML_a, XML_xfrm ); 597 } 598 599 void DrawingML::WriteShapeTransformation( Reference< XShape > rXShape, sal_Bool bFlipH, sal_Bool bFlipV, sal_Int32 nRotation ) 600 { 601 DBG(printf( "write shape transformation\n" )); 602 603 awt::Point aPos = rXShape->getPosition(); 604 awt::Size aSize = rXShape->getSize(); 605 606 WriteTransformation( Rectangle( Point( aPos.X, aPos.Y ), Size( aSize.Width, aSize.Height ) ), bFlipH, bFlipV, nRotation ); 607 } 608 609 void DrawingML::WriteRunProperties( Reference< XTextRange > rRun ) 610 { 611 Reference< XPropertySet > rXPropSet( rRun, UNO_QUERY ); 612 Reference< XPropertyState > rXPropState( rRun, UNO_QUERY ); 613 OUString usLanguage; 614 PropertyState eState; 615 sal_Int16 nScriptType = SvtLanguageOptions::GetScriptTypeOfLanguage( Application::GetSettings().GetLanguage() ); 616 sal_Bool bComplex = ( nScriptType == ScriptType::COMPLEX ); 617 const char* bold = NULL; 618 const char* italic = NULL; 619 const char* underline = NULL; 620 sal_Int32 nSize = 1800; 621 622 if( GETAD( CharHeight ) ) 623 nSize = (sal_Int32) (100*(*((float*) mAny.getValue()))); 624 625 if ( ( bComplex && GETAD( CharWeightComplex ) ) || GETAD( CharWeight ) ) 626 if ( *((float*) mAny.getValue()) >= awt::FontWeight::SEMIBOLD ) 627 bold = "1"; 628 629 if ( ( bComplex && GETAD( CharPostureComplex ) ) || GETAD( CharPosture ) ) 630 switch ( *((awt::FontSlant*) mAny.getValue()) ) 631 { 632 case awt::FontSlant_OBLIQUE : 633 case awt::FontSlant_ITALIC : 634 italic = "1"; 635 break; 636 default: 637 break; 638 } 639 640 if ( GETAD( CharUnderline ) ) 641 switch ( *((sal_Int16*) mAny.getValue()) ) 642 { 643 case awt::FontUnderline::SINGLE : 644 underline = "sng"; 645 break; 646 case awt::FontUnderline::DOUBLE : 647 underline = "dbl"; 648 break; 649 case awt::FontUnderline::DOTTED : 650 underline = "dotted"; 651 break; 652 case awt::FontUnderline::DASH : 653 underline = "dash"; 654 break; 655 case awt::FontUnderline::LONGDASH : 656 underline = "dashLong"; 657 break; 658 case awt::FontUnderline::DASHDOT : 659 underline = "dotDash"; 660 break; 661 case awt::FontUnderline::DASHDOTDOT : 662 underline = "dotDotDash"; 663 break; 664 case awt::FontUnderline::WAVE : 665 underline = "wavy"; 666 break; 667 case awt::FontUnderline::DOUBLEWAVE : 668 underline = "wavyDbl"; 669 break; 670 case awt::FontUnderline::BOLD : 671 underline = "heavy"; 672 break; 673 case awt::FontUnderline::BOLDDOTTED : 674 underline = "dottedHeavy"; 675 break; 676 case awt::FontUnderline::BOLDDASH : 677 underline = "dashHeavy"; 678 break; 679 case awt::FontUnderline::BOLDLONGDASH : 680 underline = "dashLongHeavy"; 681 break; 682 case awt::FontUnderline::BOLDDASHDOT : 683 underline = "dotDashHeavy"; 684 break; 685 case awt::FontUnderline::BOLDDASHDOTDOT : 686 underline = "dotDotDashHeavy"; 687 break; 688 case awt::FontUnderline::BOLDWAVE : 689 underline = "wavyHeavy"; 690 break; 691 } 692 693 if( GETA( CharLocale ) ) { 694 com::sun::star::lang::Locale eLocale; 695 mAny >>= eLocale; 696 697 OUStringBuffer usLanguageBuffer = eLocale.Language; 698 if( eLocale.Country.getLength() ) { 699 usLanguageBuffer.appendAscii( "-" ); 700 usLanguageBuffer.append( eLocale.Country ); 701 } 702 703 if( usLanguageBuffer.getLength() ) 704 usLanguage = usLanguageBuffer.makeStringAndClear(); 705 } 706 707 mpFS->startElementNS( XML_a, XML_rPr, 708 XML_b, bold, 709 XML_i, italic, 710 XML_lang, usLanguage.getLength() ? USS( usLanguage ) : NULL, 711 XML_sz, nSize == 1800 ? NULL : IS( nSize ), 712 XML_u, underline, 713 FSEND ); 714 715 // mso doesn't like text color to be placed after typeface 716 if( GETAD( CharColor ) ) { 717 sal_uInt32 color = *((sal_uInt32*) mAny.getValue()); 718 DBG(printf("run color: %x auto: %x\n", static_cast<unsigned int>( color ), static_cast<unsigned int>( COL_AUTO ))); 719 720 if( color == COL_AUTO ) { // nCharColor depends to the background color 721 sal_Bool bIsDark = sal_False; 722 GET( bIsDark, IsBackgroundDark ); 723 color = bIsDark ? 0xffffff : 0x000000; 724 } 725 color &= 0xffffff; 726 727 // TODO: special handle embossed/engraved 728 729 WriteSolidFill( color ); 730 } 731 732 if( GETAD( CharFontName ) ) { 733 const char* typeface = NULL; 734 const char* pitch = NULL; 735 const char* charset = NULL; 736 OUString usTypeface, usPitch, usCharset; 737 738 mAny >>= usTypeface; 739 String aSubstName( GetSubsFontName( usTypeface, SUBSFONT_ONLYONE | SUBSFONT_MS ) ); 740 if( aSubstName.Len() ) 741 typeface = ST( aSubstName ); 742 else 743 typeface = USS( usTypeface ); 744 745 746 747 mpFS->singleElementNS( XML_a, XML_latin, 748 XML_typeface, typeface, 749 XML_pitchFamily, pitch, 750 XML_charset, charset, 751 FSEND ); 752 } 753 754 if( ( bComplex && GETAD( CharFontNameComplex ) ) || ( !bComplex && GETAD( CharFontNameAsian ) ) ) { 755 const char* typeface = NULL; 756 const char* pitch = NULL; 757 const char* charset = NULL; 758 OUString usTypeface, usPitch, usCharset; 759 760 mAny >>= usTypeface; 761 String aSubstName( GetSubsFontName( usTypeface, SUBSFONT_ONLYONE | SUBSFONT_MS ) ); 762 if( aSubstName.Len() ) 763 typeface = ST( aSubstName ); 764 else 765 typeface = USS( usTypeface ); 766 767 mpFS->singleElementNS( XML_a, bComplex ? XML_cs : XML_ea, 768 XML_typeface, typeface, 769 XML_pitchFamily, pitch, 770 XML_charset, charset, 771 FSEND ); 772 } 773 774 mpFS->endElementNS( XML_a, XML_rPr ); 775 } 776 777 const char* DrawingML::GetFieldType( ::com::sun::star::uno::Reference< ::com::sun::star::text::XTextRange > rRun ) 778 { 779 const char* sType = NULL; 780 Reference< XPropertySet > rXPropSet( rRun, UNO_QUERY ); 781 String aFieldType; 782 783 if( GETA( TextPortionType ) ) { 784 aFieldType = String( *(::rtl::OUString*)mAny.getValue() ); 785 DBG(printf ("field type: %s\n", ST(aFieldType) )); 786 } 787 788 if( aFieldType == S( "TextField" ) ) { 789 Reference< XTextField > rXTextField; 790 GET( rXTextField, TextField ); 791 if( rXTextField.is() ) { 792 rXPropSet.set( rXTextField, UNO_QUERY ); 793 if( rXPropSet.is() ) { 794 String aFieldKind( rXTextField->getPresentation( TRUE ) ); 795 DBG(printf ("field kind: %s\n", ST(aFieldKind) )); 796 if( aFieldKind == S( "Page" ) ) { 797 return "slidenum"; 798 } 799 } 800 } 801 } 802 803 return sType; 804 } 805 806 void DrawingML::GetUUID( OStringBuffer& rBuffer ) 807 { 808 Sequence< sal_uInt8 > aSeq( 16 ); 809 static char cDigits[17] = "0123456789ABCDEF"; 810 rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True ); 811 int i; 812 813 rBuffer.append( '{' ); 814 for( i = 0; i < 4; i++ ) { 815 rBuffer.append( cDigits[ aSeq[i] >> 4 ] ); 816 rBuffer.append( cDigits[ aSeq[i] && 0xf ] ); 817 } 818 rBuffer.append( '-' ); 819 for( ; i < 6; i++ ) { 820 rBuffer.append( cDigits[ aSeq[i] >> 4 ] ); 821 rBuffer.append( cDigits[ aSeq[i] && 0xf ] ); 822 } 823 rBuffer.append( '-' ); 824 for( ; i < 8; i++ ) { 825 rBuffer.append( cDigits[ aSeq[i] >> 4 ] ); 826 rBuffer.append( cDigits[ aSeq[i] && 0xf ] ); 827 } 828 rBuffer.append( '-' ); 829 for( ; i < 10; i++ ) { 830 rBuffer.append( cDigits[ aSeq[i] >> 4 ] ); 831 rBuffer.append( cDigits[ aSeq[i] && 0xf ] ); 832 } 833 rBuffer.append( '-' ); 834 for( ; i < 16; i++ ) { 835 rBuffer.append( cDigits[ aSeq[i] >> 4 ] ); 836 rBuffer.append( cDigits[ aSeq[i] && 0xf ] ); 837 } 838 rBuffer.append( '}' ); 839 } 840 841 void DrawingML::WriteRun( Reference< XTextRange > rRun ) 842 { 843 const char* sFieldType; 844 bool bIsField = false; 845 OUString sText = rRun->getString(); 846 847 if( sText.getLength() < 1) 848 return; 849 850 if( ( sFieldType = GetFieldType( rRun ) ) ) { 851 OStringBuffer sUUID(39); 852 853 GetUUID( sUUID ); 854 mpFS->startElementNS( XML_a, XML_fld, 855 XML_id, sUUID.getStr(), 856 XML_type, sFieldType, 857 FSEND ); 858 bIsField = true; 859 } else 860 mpFS->startElementNS( XML_a, XML_r, FSEND ); 861 862 WriteRunProperties( rRun ); 863 864 mpFS->startElementNS( XML_a, XML_t, FSEND ); 865 mpFS->writeEscaped( sText ); 866 mpFS->endElementNS( XML_a, XML_t ); 867 868 if( bIsField ) 869 mpFS->endElementNS( XML_a, XML_fld ); 870 else 871 mpFS->endElementNS( XML_a, XML_r ); 872 } 873 874 #define AUTONUM(x) \ 875 if( bPBoth ) \ 876 pAutoNumType = #x "ParenBoth"; \ 877 else if( bPBehind ) \ 878 pAutoNumType = #x "ParenR"; \ 879 else if( bSDot ) \ 880 pAutoNumType = #x "Period"; 881 882 883 inline static const char* GetAutoNumType( sal_Int16 nNumberingType, bool bSDot, bool bPBehind, bool bPBoth ) 884 { 885 const char* pAutoNumType = NULL; 886 887 switch( (SvxExtNumType)nNumberingType ) 888 { 889 case SVX_NUM_CHARS_UPPER_LETTER_N : 890 case SVX_NUM_CHARS_UPPER_LETTER : 891 AUTONUM( alphaUc ); 892 break; 893 case SVX_NUM_CHARS_LOWER_LETTER_N : 894 case SVX_NUM_CHARS_LOWER_LETTER : 895 AUTONUM( alphaLc ); 896 break; 897 case SVX_NUM_ROMAN_UPPER : 898 AUTONUM( romanUc ); 899 break; 900 case SVX_NUM_ROMAN_LOWER : 901 AUTONUM( romanLc ); 902 break; 903 case SVX_NUM_ARABIC : 904 AUTONUM( arabic ) 905 else 906 pAutoNumType = "arabicPlain"; 907 break; 908 default: 909 break; 910 } 911 912 return pAutoNumType; 913 } 914 915 void DrawingML::WriteParagraphNumbering( Reference< XPropertySet > rXPropSet, sal_Int16 nLevel ) 916 { 917 if( nLevel >= 0 && GETA( NumberingRules ) ) 918 { 919 Reference< XIndexAccess > rXIndexAccess; 920 921 if ( ( mAny >>= rXIndexAccess ) && nLevel < rXIndexAccess->getCount() ) 922 { 923 DBG(printf ("numbering rules\n")); 924 925 Sequence< PropertyValue > aPropertySequence; 926 rXIndexAccess->getByIndex( nLevel ) >>= aPropertySequence; 927 928 929 const PropertyValue* pPropValue = aPropertySequence.getArray(); 930 931 sal_Int32 nPropertyCount = aPropertySequence.getLength(); 932 933 if ( nPropertyCount ) { 934 935 sal_Int16 nNumberingType = -1; 936 bool bSDot = false; 937 bool bPBehind = false; 938 bool bPBoth = false; 939 sal_Unicode aBulletChar = 0x2022; // a bullet 940 awt::FontDescriptor aFontDesc; 941 bool bHasFontDesc = false; 942 OUString aGraphicURL; 943 sal_Int16 nBulletRelSize = 0; 944 945 for ( sal_Int32 i = 0; i < nPropertyCount; i++ ) { 946 const void* pValue = pPropValue[ i ].Value.getValue(); 947 if ( pValue ) { 948 OUString aPropName( pPropValue[ i ].Name ); 949 DBG(printf ("pro name: %s\n", OUStringToOString( aPropName, RTL_TEXTENCODING_UTF8 ).getStr())); 950 if ( aPropName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "NumberingType" ) ) ) 951 nNumberingType = *( (sal_Int16*)pValue ); 952 else if ( aPropName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Prefix" ) ) ) { 953 if( *(OUString*)pValue == US( ")" ) ) 954 bPBoth = true; 955 } else if ( aPropName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Suffix" ) ) ) { 956 if( *(OUString*)pValue == US( "." ) ) 957 bSDot = true; 958 else if( *(OUString*)pValue == US( ")" ) ) 959 bPBehind = true; 960 } else if ( aPropName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "BulletChar" ) ) ) 961 { 962 aBulletChar = String ( *( (String*)pValue ) ).GetChar( 0 ); 963 //printf ("bullet char: %d\n", aBulletChar.getStr()); 964 } 965 else if ( aPropName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "BulletFont" ) ) ) 966 { 967 aFontDesc = *( (awt::FontDescriptor*)pValue ); 968 bHasFontDesc = true; 969 970 // Our numbullet dialog has set the wrong textencoding for our "StarSymbol" font, 971 // instead of a Unicode encoding the encoding RTL_TEXTENCODING_SYMBOL was used. 972 // Because there might exist a lot of damaged documemts I added this two lines 973 // which fixes the bullet problem for the export. 974 if ( aFontDesc.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "StarSymbol" ) ) ) 975 aFontDesc.CharSet = RTL_TEXTENCODING_MS_1252; 976 977 } else if ( aPropName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "BulletRelSize" ) ) ) { 978 nBulletRelSize = *( (sal_Int16*)pValue ); 979 } else if ( aPropName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "GraphicURL" ) ) ) { 980 aGraphicURL = ( *(OUString*)pValue ); 981 DBG(printf ("graphic url: %s\n", OUStringToOString( aGraphicURL, RTL_TEXTENCODING_UTF8 ).getStr())); 982 } else if ( aPropName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "GraphicSize" ) ) ) 983 { 984 if ( pPropValue[ i ].Value.getValueType() == ::getCppuType( (awt::Size*)0) ) 985 { 986 // don't cast awt::Size to Size as on 64-bits they are not the same. 987 ::com::sun::star::awt::Size aSize; 988 pPropValue[ i ].Value >>= aSize; 989 //aBuGraSize.nA = aSize.Width; 990 //aBuGraSize.nB = aSize.Height; 991 DBG(printf("graphic size: %dx%d\n", int( aSize.Width ), int( aSize.Height ))); 992 } 993 } 994 } 995 } 996 997 const char* pAutoNumType = GetAutoNumType( nNumberingType, bSDot, bPBehind, bPBoth ); 998 999 if( nLevel >= 0 ) { 1000 if( aGraphicURL.getLength() > 0 ) { 1001 OUString sRelId = WriteImage( aGraphicURL ); 1002 1003 mpFS->startElementNS( XML_a, XML_buBlip, FSEND ); 1004 mpFS->singleElementNS( XML_a, XML_blip, FSNS( XML_r, XML_embed ), USS( sRelId ), FSEND ); 1005 mpFS->endElementNS( XML_a, XML_buBlip ); 1006 } else { 1007 if( nBulletRelSize && nBulletRelSize != 100 ) 1008 mpFS->singleElementNS( XML_a, XML_buSzPct, 1009 XML_val, IS( 1000*( (sal_Int32)nBulletRelSize ) ), FSEND ); 1010 if( bHasFontDesc ) 1011 mpFS->singleElementNS( XML_a, XML_buFont, 1012 XML_typeface, OUStringToOString( aFontDesc.Name, RTL_TEXTENCODING_UTF8 ).getStr(), 1013 XML_charset, (aFontDesc.CharSet == awt::CharSet::SYMBOL) ? "2" : NULL, 1014 FSEND ); 1015 1016 if( pAutoNumType ) 1017 mpFS->singleElementNS( XML_a, XML_buAutoNum, XML_type, pAutoNumType, FSEND ); 1018 else { 1019 aBulletChar = SubstituteBullet( aBulletChar, aFontDesc ); 1020 mpFS->singleElementNS( XML_a, XML_buChar, XML_char, USS( OUString( aBulletChar ) ), FSEND ); 1021 } 1022 } 1023 } 1024 } 1025 } 1026 } 1027 } 1028 1029 const char* DrawingML::GetAlignment( sal_Int32 nAlignment ) 1030 { 1031 const char* sAlignment = NULL; 1032 1033 switch( nAlignment ) { 1034 case style::ParagraphAdjust_CENTER: 1035 sAlignment = "ctr"; 1036 break; 1037 case style::ParagraphAdjust_RIGHT: 1038 sAlignment = "r"; 1039 break; 1040 case style::ParagraphAdjust_BLOCK: 1041 sAlignment = "just"; 1042 break; 1043 default: 1044 ; 1045 } 1046 1047 return sAlignment; 1048 } 1049 1050 void DrawingML::WriteParagraphProperties( Reference< XTextContent > rParagraph ) 1051 { 1052 Reference< XPropertySet > rXPropSet( rParagraph, UNO_QUERY ); 1053 Reference< XPropertyState > rXPropState( rParagraph, UNO_QUERY ); 1054 1055 if( !rXPropSet.is() || !rXPropState.is() ) 1056 return; 1057 1058 sal_Int16 nLevel = -1; 1059 GET( nLevel, NumberingLevel ); 1060 1061 sal_Int32 nLeftMargin = 0; 1062 // fix coordinates 1063 //GET( nLeftMargin, ParaLeftMargin ); 1064 1065 sal_Int16 nAlignment( style::ParagraphAdjust_LEFT ); 1066 GET( nAlignment, ParaAdjust ); 1067 1068 if( nLevel != -1 1069 || nLeftMargin > 0 1070 || nAlignment != style::ParagraphAdjust_LEFT ) { 1071 mpFS->startElementNS( XML_a, XML_pPr, 1072 XML_lvl, nLevel > 0 ? I32S( nLevel ) : NULL, 1073 XML_marL, nLeftMargin > 0 ? IS( nLeftMargin ) : NULL, 1074 XML_algn, GetAlignment( nAlignment ), 1075 FSEND ); 1076 1077 WriteParagraphNumbering( rXPropSet, nLevel ); 1078 1079 mpFS->endElementNS( XML_a, XML_pPr ); 1080 } 1081 } 1082 1083 void DrawingML::WriteParagraph( Reference< XTextContent > rParagraph ) 1084 { 1085 Reference< XEnumerationAccess > access( rParagraph, UNO_QUERY ); 1086 if( !access.is() ) 1087 return; 1088 1089 Reference< XEnumeration > enumeration( access->createEnumeration() ); 1090 if( !enumeration.is() ) 1091 return; 1092 1093 mpFS->startElementNS( XML_a, XML_p, FSEND ); 1094 1095 sal_Bool bPropertiesWritten = FALSE; 1096 while( enumeration->hasMoreElements() ) { 1097 Reference< XTextRange > run; 1098 Any any ( enumeration->nextElement() ); 1099 1100 if (any >>= run) { 1101 if( !bPropertiesWritten && run->getString().getLength() ) { 1102 WriteParagraphProperties( rParagraph ); 1103 bPropertiesWritten = TRUE; 1104 } 1105 WriteRun( run ); 1106 } 1107 } 1108 mpFS->singleElementNS( XML_a, XML_endParaRPr, FSEND ); 1109 1110 mpFS->endElementNS( XML_a, XML_p ); 1111 } 1112 1113 void DrawingML::WriteText( Reference< XShape > rXShape ) 1114 { 1115 Reference< XText > xXText( rXShape, UNO_QUERY ); 1116 Reference< XPropertySet > rXPropSet( rXShape, UNO_QUERY ); 1117 1118 if( !xXText.is() ) 1119 return; 1120 1121 #define DEFLRINS 254 1122 #define DEFTBINS 127 1123 sal_Int32 nLeft, nRight, nTop, nBottom; 1124 nLeft = nRight = DEFLRINS; 1125 nTop = nBottom = DEFTBINS; 1126 1127 // top inset looks a bit different compared to ppt export 1128 // check if something related doesn't work as expected 1129 GET( nLeft, TextLeftDistance ); 1130 GET( nRight, TextRightDistance ); 1131 GET( nTop, TextUpperDistance ); 1132 GET( nBottom, TextLowerDistance ); 1133 1134 TextVerticalAdjust eVerticalAlignment( TextVerticalAdjust_TOP ); 1135 const char* sVerticalAlignment = NULL; 1136 GET( eVerticalAlignment, TextVerticalAdjust ); 1137 switch( eVerticalAlignment ) { 1138 case TextVerticalAdjust_BOTTOM: 1139 sVerticalAlignment = "b"; 1140 break; 1141 case TextVerticalAdjust_CENTER: 1142 sVerticalAlignment = "ctr"; 1143 break; 1144 case TextVerticalAdjust_TOP: 1145 default: 1146 ; 1147 } 1148 1149 TextHorizontalAdjust eHorizontalAlignment( TextHorizontalAdjust_CENTER ); 1150 bool bHorizontalCenter = false; 1151 GET( eHorizontalAlignment, TextHorizontalAdjust ); 1152 if( eHorizontalAlignment == TextHorizontalAdjust_CENTER ) 1153 bHorizontalCenter = true; 1154 1155 sal_Bool bHasWrap = FALSE; 1156 sal_Bool bWrap = FALSE; 1157 if( GETA( TextWordWrap ) ) { 1158 mAny >>= bWrap; 1159 bHasWrap = TRUE; 1160 //DBG(printf("wrap: %d\n", bWrap)); 1161 } 1162 1163 mpFS->singleElementNS( XML_a, XML_bodyPr, 1164 XML_wrap, bHasWrap && !bWrap ? "none" : NULL, 1165 XML_lIns, (nLeft != DEFLRINS) ? IS( MM100toEMU( nLeft ) ) : NULL, 1166 XML_rIns, (nRight != DEFLRINS) ? IS( MM100toEMU( nRight ) ) : NULL, 1167 XML_tIns, (nTop != DEFTBINS) ? IS( MM100toEMU( nTop ) ) : NULL, 1168 XML_bIns, (nBottom != DEFTBINS) ? IS( MM100toEMU( nBottom ) ) : NULL, 1169 XML_anchor, sVerticalAlignment, 1170 XML_anchorCtr, bHorizontalCenter ? "1" : NULL, 1171 FSEND ); 1172 1173 Reference< XEnumerationAccess > access( xXText, UNO_QUERY ); 1174 if( !access.is() ) 1175 return; 1176 1177 Reference< XEnumeration > enumeration( access->createEnumeration() ); 1178 if( !enumeration.is() ) 1179 return; 1180 1181 while( enumeration->hasMoreElements() ) { 1182 Reference< XTextContent > paragraph; 1183 Any any ( enumeration->nextElement() ); 1184 1185 if( any >>= paragraph) 1186 WriteParagraph( paragraph ); 1187 } 1188 1189 } 1190 1191 void DrawingML::WritePresetShape( const char* pShape ) 1192 { 1193 mpFS->startElementNS( XML_a, XML_prstGeom, 1194 XML_prst, pShape, 1195 FSEND ); 1196 mpFS->singleElementNS( XML_a, XML_avLst, FSEND ); 1197 mpFS->endElementNS( XML_a, XML_prstGeom ); 1198 } 1199 1200 void DrawingML::WritePresetShape( const char* pShape, MSO_SPT eShapeType, sal_Bool bPredefinedHandlesUsed, sal_Int32 nAdjustmentsWhichNeedsToBeConverted, const PropertyValue& rProp ) 1201 { 1202 mpFS->startElementNS( XML_a, XML_prstGeom, 1203 XML_prst, pShape, 1204 FSEND ); 1205 mpFS->startElementNS( XML_a, XML_avLst, FSEND ); 1206 1207 Sequence< drawing::EnhancedCustomShapeAdjustmentValue > aAdjustmentSeq; 1208 if ( rProp.Value >>= aAdjustmentSeq ) { 1209 DBG(printf("adj seq len: %d\n", int( aAdjustmentSeq.getLength() ))); 1210 if ( bPredefinedHandlesUsed ) 1211 EscherPropertyContainer::LookForPolarHandles( eShapeType, nAdjustmentsWhichNeedsToBeConverted ); 1212 1213 sal_Int32 nValue, nLength = aAdjustmentSeq.getLength(); 1214 for( sal_Int32 i=0; i < nLength; i++ ) 1215 if( EscherPropertyContainer::GetAdjustmentValue( aAdjustmentSeq[ i ], i, nAdjustmentsWhichNeedsToBeConverted, nValue ) ) 1216 mpFS->singleElementNS( XML_a, XML_gd, 1217 XML_name, nLength > 1 ? ( OString( "adj" ) + OString::valueOf( i + 1 ) ).getStr() : "adj", 1218 XML_fmla, (OString("val ") + OString::valueOf( nValue )).getStr(), 1219 FSEND ); 1220 } 1221 1222 mpFS->endElementNS( XML_a, XML_avLst ); 1223 mpFS->endElementNS( XML_a, XML_prstGeom ); 1224 } 1225 1226 void DrawingML::WritePolyPolygon( const PolyPolygon& rPolyPolygon ) 1227 { 1228 if( rPolyPolygon.Count() < 1 ) 1229 return; 1230 1231 mpFS->startElementNS( XML_a, XML_custGeom, FSEND ); 1232 mpFS->singleElementNS( XML_a, XML_avLst, FSEND ); 1233 mpFS->singleElementNS( XML_a, XML_gdLst, FSEND ); 1234 mpFS->singleElementNS( XML_a, XML_ahLst, FSEND ); 1235 mpFS->singleElementNS( XML_a, XML_rect, 1236 XML_l, "0", 1237 XML_t, "0", 1238 XML_r, "r", 1239 XML_b, "b", 1240 FSEND ); 1241 1242 mpFS->startElementNS( XML_a, XML_pathLst, FSEND ); 1243 1244 for( USHORT i = 0; i < rPolyPolygon.Count(); i ++ ) { 1245 1246 const Polygon& rPoly = rPolyPolygon[ i ]; 1247 Rectangle aRect( rPoly.GetBoundRect() ); 1248 sal_Bool bBezier = FALSE; 1249 1250 mpFS->startElementNS( XML_a, XML_path, 1251 XML_w, I64S( aRect.GetWidth() ), 1252 XML_h, I64S( aRect.GetHeight() ), 1253 FSEND ); 1254 1255 if( rPoly.GetSize() > 0 ) 1256 { 1257 mpFS->startElementNS( XML_a, XML_moveTo, FSEND ); 1258 1259 mpFS->singleElementNS( XML_a, XML_pt, 1260 XML_x, I64S( rPoly[ 0 ].X() - aRect.Left() ), 1261 XML_y, I64S( rPoly[ 0 ].Y() - aRect.Top() ), 1262 FSEND ); 1263 1264 mpFS->endElementNS( XML_a, XML_moveTo ); 1265 } 1266 1267 for( USHORT j = 1; j < rPoly.GetSize(); j ++ ) 1268 { 1269 enum PolyFlags flags = rPoly.GetFlags(j); 1270 if( flags == POLY_CONTROL && !bBezier ) 1271 { 1272 mpFS->startElementNS( XML_a, XML_cubicBezTo, FSEND ); 1273 bBezier = TRUE; 1274 } 1275 else if( flags == POLY_NORMAL && !bBezier ) 1276 mpFS->startElementNS( XML_a, XML_lnTo, FSEND ); 1277 1278 mpFS->singleElementNS( XML_a, XML_pt, 1279 XML_x, I64S( rPoly[j].X() - aRect.Left() ), 1280 XML_y, I64S( rPoly[j].Y() - aRect.Top() ), 1281 FSEND ); 1282 1283 if( ( flags == POLY_NORMAL || flags == POLY_SYMMTR ) && bBezier ) 1284 { 1285 mpFS->endElementNS( XML_a, XML_cubicBezTo ); 1286 bBezier = FALSE; 1287 } 1288 else if( flags == POLY_NORMAL && !bBezier ) 1289 mpFS->endElementNS( XML_a, XML_lnTo ); 1290 else if( bBezier && ( j % 3 ) == 0 ) 1291 { 1292 // //a:cubicBezTo can only contain 3 //a:pt elements, so we 1293 // need to break things up... 1294 mpFS->endElementNS( XML_a, XML_cubicBezTo ); 1295 mpFS->startElementNS( XML_a, XML_cubicBezTo, FSEND ); 1296 } 1297 // switch( rPoly.GetFlags(j) ) { 1298 // case POLY_NORMAL: 1299 // DBG(printf("normal\n")); 1300 // break; 1301 // case POLY_SMOOTH: 1302 // DBG(printf("smooth\n")); 1303 // break; 1304 // case POLY_CONTROL: 1305 // DBG(printf("control\n")); 1306 // break; 1307 // case POLY_SYMMTR: 1308 // DBG(printf("symmtr\n")); 1309 // break; 1310 // } 1311 // DBG(printf("point %ld %ld\n", rPoly[j].X() - aRect.Left(), rPoly[j].Y() - aRect.Top())); 1312 } 1313 1314 mpFS->endElementNS( XML_a, XML_path ); 1315 } 1316 1317 mpFS->endElementNS( XML_a, XML_pathLst ); 1318 1319 mpFS->endElementNS( XML_a, XML_custGeom ); 1320 } 1321 1322 void DrawingML::WriteConnectorConnections( EscherConnectorListEntry& rConnectorEntry, sal_Int32 nStartID, sal_Int32 nEndID ) 1323 { 1324 mpFS->singleElementNS( XML_a, XML_stCxn, 1325 XML_id, I32S( nStartID ), 1326 XML_idx, I64S( rConnectorEntry.GetConnectorRule( TRUE ) ), 1327 FSEND ); 1328 mpFS->singleElementNS( XML_a, XML_endCxn, 1329 XML_id, I32S( nEndID ), 1330 XML_idx, I64S( rConnectorEntry.GetConnectorRule( FALSE ) ), 1331 FSEND ); 1332 } 1333 1334 // from sw/source/filter/ww8/wrtw8num.cxx for default bullets to export to MS intact 1335 static void lcl_SubstituteBullet(String& rNumStr, rtl_TextEncoding& rChrSet, String& rFontName) 1336 { 1337 sal_Unicode cChar = rNumStr.GetChar(0); 1338 StarSymbolToMSMultiFont *pConvert = CreateStarSymbolToMSMultiFont(); 1339 String sFont = pConvert->ConvertChar(cChar); 1340 delete pConvert; 1341 if (sFont.Len()) 1342 { 1343 rNumStr = static_cast< sal_Unicode >(cChar | 0xF000); 1344 rFontName = sFont; 1345 rChrSet = RTL_TEXTENCODING_SYMBOL; 1346 } 1347 else if ( (rNumStr.GetChar(0) < 0xE000 || rNumStr.GetChar(0) > 0xF8FF) ) 1348 { 1349 /* 1350 Ok we can't fit into a known windows unicode font, but 1351 we are not in the private area, so we are a 1352 standardized symbol, so turn off the symbol bit and 1353 let words own font substitution kick in 1354 */ 1355 rChrSet = RTL_TEXTENCODING_UNICODE; 1356 rFontName = ::GetFontToken(rFontName, 0); 1357 } 1358 else 1359 { 1360 /* 1361 Well we don't have an available substition, and we're 1362 in our private area, so give up and show a standard 1363 bullet symbol 1364 */ 1365 rFontName.AssignAscii(RTL_CONSTASCII_STRINGPARAM("Wingdings")); 1366 rNumStr = static_cast< sal_Unicode >(0x6C); 1367 } 1368 } 1369 1370 sal_Unicode DrawingML::SubstituteBullet( sal_Unicode cBulletId, ::com::sun::star::awt::FontDescriptor& rFontDesc ) 1371 { 1372 String sNumStr = cBulletId; 1373 1374 if ( rFontDesc.Name.equalsIgnoreAsciiCaseAscii("starsymbol") || 1375 rFontDesc.Name.equalsIgnoreAsciiCaseAscii("opensymbol") ) { 1376 String sFontName = rFontDesc.Name; 1377 rtl_TextEncoding aCharSet = rFontDesc.CharSet; 1378 1379 lcl_SubstituteBullet( sNumStr, aCharSet, sFontName ); 1380 1381 rFontDesc.Name = sFontName; 1382 rFontDesc.CharSet = aCharSet; 1383 } 1384 1385 return sNumStr.GetChar( 0 ); 1386 } 1387 1388 } 1389 } 1390