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/shapes.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/FillStyle.hpp> 43 #include <com/sun/star/drawing/BitmapMode.hpp> 44 #include <com/sun/star/drawing/ConnectorType.hpp> 45 #include <com/sun/star/drawing/LineDash.hpp> 46 #include <com/sun/star/drawing/LineJoint.hpp> 47 #include <com/sun/star/drawing/LineStyle.hpp> 48 #include <com/sun/star/drawing/TextHorizontalAdjust.hpp> 49 #include <com/sun/star/drawing/TextVerticalAdjust.hpp> 50 #include <com/sun/star/i18n/ScriptType.hpp> 51 #include <com/sun/star/io/XOutputStream.hpp> 52 #include <com/sun/star/style/ParagraphAdjust.hpp> 53 #include <com/sun/star/text/XSimpleText.hpp> 54 #include <com/sun/star/text/XText.hpp> 55 #include <com/sun/star/text/XTextContent.hpp> 56 #include <com/sun/star/text/XTextField.hpp> 57 #include <com/sun/star/text/XTextRange.hpp> 58 #include <tools/stream.hxx> 59 #include <tools/string.hxx> 60 #include <vcl/cvtgrf.hxx> 61 #include <unotools/fontcvt.hxx> 62 #include <vcl/graph.hxx> 63 #include <vcl/outdev.hxx> 64 #include <svtools/grfmgr.hxx> 65 #include <rtl/strbuf.hxx> 66 #include <sfx2/app.hxx> 67 #include <svl/languageoptions.hxx> 68 #include <svx/escherex.hxx> 69 #include <svx/svdoashp.hxx> 70 #include <svx/svxenum.hxx> 71 #include <svx/unoapi.hxx> 72 73 using namespace ::com::sun::star; 74 using namespace ::com::sun::star::uno; 75 using namespace ::com::sun::star::drawing; 76 using namespace ::com::sun::star::i18n; 77 using ::com::sun::star::beans::PropertyState; 78 using ::com::sun::star::beans::PropertyValue; 79 using ::com::sun::star::beans::XPropertySet; 80 using ::com::sun::star::beans::XPropertyState; 81 using ::com::sun::star::container::XEnumeration; 82 using ::com::sun::star::container::XEnumerationAccess; 83 using ::com::sun::star::container::XIndexAccess; 84 using ::com::sun::star::drawing::FillStyle; 85 using ::com::sun::star::io::XOutputStream; 86 using ::com::sun::star::text::XSimpleText; 87 using ::com::sun::star::text::XText; 88 using ::com::sun::star::text::XTextContent; 89 using ::com::sun::star::text::XTextField; 90 using ::com::sun::star::text::XTextRange; 91 using ::rtl::OString; 92 using ::rtl::OStringBuffer; 93 using ::rtl::OUString; 94 using ::rtl::OUStringBuffer; 95 using ::sax_fastparser::FSHelperPtr; 96 97 DBG(extern void dump_pset(Reference< XPropertySet > rXPropSet)); 98 99 #define IDS(x) (OString(#x " ") + OString::valueOf( mnShapeIdMax++ )).getStr() 100 101 struct CustomShapeTypeTranslationTable 102 { 103 const char* sOOo; 104 const char* sMSO; 105 }; 106 107 static const CustomShapeTypeTranslationTable pCustomShapeTypeTranslationTable[] = 108 { 109 // { "non-primitive", mso_sptMin }, 110 { "rectangle", "rect" }, 111 { "round-rectangle", "roundRect" }, 112 { "ellipse", "ellipse" }, 113 { "diamond", "diamond" }, 114 { "isosceles-triangle", "triangle" }, 115 { "right-triangle", "rtTriangle" }, 116 { "parallelogram", "parallelogram" }, 117 { "trapezoid", "trapezoid" }, 118 { "hexagon", "hexagon" }, 119 { "octagon", "octagon" }, 120 { "cross", "plus" }, 121 { "star5", "star5" }, 122 { "right-arrow", "rightArrow" }, 123 // { "mso-spt14", mso_sptThickArrow }, 124 { "pentagon-right", "homePlate" }, 125 { "cube", "cube" }, 126 // { "mso-spt17", mso_sptBalloon }, 127 // { "mso-spt18", mso_sptSeal }, 128 { "mso-spt19", "arc" }, 129 { "mso-spt20", "line" }, 130 { "mso-spt21", "plaque" }, 131 { "can", "can" }, 132 { "ring", "donut" }, 133 { "mso-spt24", "textSimple" }, 134 { "mso-spt25", "textOctagon" }, 135 { "mso-spt26", "textHexagon" }, 136 { "mso-spt27", "textCurve" }, 137 { "mso-spt28", "textWave" }, 138 { "mso-spt29", "textRing" }, 139 { "mso-spt30", "textOnCurve" }, 140 { "mso-spt31", "textOnRing" }, 141 { "mso-spt32", "straightConnector1" }, 142 { "mso-spt33", "bentConnector2" }, 143 { "mso-spt34", "bentConnector3" }, 144 { "mso-spt35", "bentConnector4" }, 145 { "mso-spt36", "bentConnector5" }, 146 { "mso-spt37", "curvedConnector2" }, 147 { "mso-spt38", "curvedConnector3" }, 148 { "mso-spt39", "curvedConnector4" }, 149 { "mso-spt40", "curvedConnector5" }, 150 { "mso-spt41", "callout1" }, 151 { "mso-spt42", "callout2" }, 152 { "mso-spt43", "callout3" }, 153 { "mso-spt44", "accentCallout1" }, 154 { "mso-spt45", "accentCallout2" }, 155 { "mso-spt46", "accentCallout3" }, 156 { "line-callout-1", "borderCallout1" }, 157 { "line-callout-2", "borderCallout2" }, 158 { "line-callout-3", "borderCallout3" }, 159 { "mso-spt49", "accentBorderCallout90" }, 160 { "mso-spt50", "accentBorderCallout1" }, 161 { "mso-spt51", "accentBorderCallout2" }, 162 { "mso-spt52", "accentBorderCallout3" }, 163 { "mso-spt53", "ribbon" }, 164 { "mso-spt54", "ribbon2" }, 165 { "chevron", "chevron" }, 166 { "pentagon", "pentagon" }, 167 { "forbidden", "noSmoking" }, 168 { "star8", "seal8" }, 169 { "mso-spt59", "seal16" }, 170 { "mso-spt60", "seal32" }, 171 { "rectangular-callout", "wedgeRectCallout" }, 172 { "round-rectangular-callout", "wedgeRoundRectCallout" }, 173 { "round-callout", "wedgeEllipseCallout" }, 174 { "mso-spt64", "wave" }, 175 { "paper", "foldedCorner" }, 176 { "left-arrow", "leftArrow" }, 177 { "down-arrow", "downArrow" }, 178 { "up-arrow", "upArrow" }, 179 { "left-right-arrow", "leftRightArrow" }, 180 { "up-down-arrow", "upDownArrow" }, 181 { "mso-spt71", "irregularSeal1" }, 182 { "bang", "irregularSeal2" }, 183 { "lightning", "lightningBolt" }, 184 { "heart", "heart" }, 185 { "mso-spt75", "pictureFrame" }, 186 { "quad-arrow", "quadArrow" }, 187 { "left-arrow-callout", "leftArrowCallout" }, 188 { "right-arrow-callout", "rightArrowCallout" }, 189 { "up-arrow-callout", "upArrowCallout" }, 190 { "down-arrow-callout", "downArrowCallout" }, 191 { "left-right-arrow-callout", "leftRightArrowCallout" }, 192 { "up-down-arrow-callout", "upDownArrowCallout" }, 193 { "quad-arrow-callout", "quadArrowCallout" }, 194 { "quad-bevel", "bevel" }, 195 { "left-bracket", "leftBracket" }, 196 { "right-bracket", "rightBracket" }, 197 { "left-brace", "leftBrace" }, 198 { "right-brace", "rightBrace" }, 199 { "mso-spt89", "leftUpArrow" }, 200 { "mso-spt90", "bentUpArrow" }, 201 { "mso-spt91", "bentArrow" }, 202 { "star24", "seal24" }, 203 { "striped-right-arrow", "stripedRightArrow" }, 204 { "notched-right-arrow", "notchedRightArrow" }, 205 { "block-arc", "blockArc" }, 206 { "smiley", "smileyFace" }, 207 { "vertical-scroll", "verticalScroll" }, 208 { "horizontal-scroll", "horizontalScroll" }, 209 { "circular-arrow", "circularArrow" }, 210 { "mso-spt100", "pie" }, // looks like MSO_SPT is wrong here 211 { "mso-spt101", "uturnArrow" }, 212 { "mso-spt102", "curvedRightArrow" }, 213 { "mso-spt103", "curvedLeftArrow" }, 214 { "mso-spt104", "curvedUpArrow" }, 215 { "mso-spt105", "curvedDownArrow" }, 216 { "cloud-callout", "cloudCallout" }, 217 { "mso-spt107", "ellipseRibbon" }, 218 { "mso-spt108", "ellipseRibbon2" }, 219 { "flowchart-process", "flowChartProcess" }, 220 { "flowchart-decision", "flowChartDecision" }, 221 { "flowchart-data", "flowChartInputOutput" }, 222 { "flowchart-predefined-process", "flowChartPredefinedProcess" }, 223 { "flowchart-internal-storage", "flowChartInternalStorage" }, 224 { "flowchart-document", "flowChartDocument" }, 225 { "flowchart-multidocument", "flowChartMultidocument" }, 226 { "flowchart-terminator", "flowChartTerminator" }, 227 { "flowchart-preparation", "flowChartPreparation" }, 228 { "flowchart-manual-input", "flowChartManualInput" }, 229 { "flowchart-manual-operation", "flowChartManualOperation" }, 230 { "flowchart-connector", "flowChartConnector" }, 231 { "flowchart-card", "flowChartPunchedCard" }, 232 { "flowchart-punched-tape", "flowChartPunchedTape" }, 233 { "flowchart-summing-junction", "flowChartSummingJunction" }, 234 { "flowchart-or", "flowChartOr" }, 235 { "flowchart-collate", "flowChartCollate" }, 236 { "flowchart-sort", "flowChartSort" }, 237 { "flowchart-extract", "flowChartExtract" }, 238 { "flowchart-merge", "flowChartMerge" }, 239 { "mso-spt129", "flowChartOfflineStorage" }, 240 { "flowchart-stored-data", "flowChartOnlineStorage" }, 241 { "flowchart-sequential-access", "flowChartMagneticTape" }, 242 { "flowchart-magnetic-disk", "flowChartMagneticDisk" }, 243 { "flowchart-direct-access-storage", "flowChartMagneticDrum" }, 244 { "flowchart-display", "flowChartDisplay" }, 245 { "flowchart-delay", "flowChartDelay" }, 246 { "fontwork-plain-text", "textPlainText" }, 247 { "fontwork-stop", "textStop" }, 248 { "fontwork-triangle-up", "textTriangle" }, 249 { "fontwork-triangle-down", "textTriangleInverted" }, 250 { "fontwork-chevron-up", "textChevron" }, 251 { "fontwork-chevron-down", "textChevronInverted" }, 252 { "mso-spt142", "textRingInside" }, 253 { "mso-spt143", "textRingOutside" }, 254 { "fontwork-arch-up-curve", "textArchUpCurve" }, 255 { "fontwork-arch-down-curve", "textArchDownCurve" }, 256 { "fontwork-circle-curve", "textCircleCurve" }, 257 { "fontwork-open-circle-curve", "textButtonCurve" }, 258 { "fontwork-arch-up-pour", "textArchUpPour" }, 259 { "fontwork-arch-down-pour", "textArchDownPour" }, 260 { "fontwork-circle-pour", "textCirclePour" }, 261 { "fontwork-open-circle-pour", "textButtonPour" }, 262 { "fontwork-curve-up", "textCurveUp" }, 263 { "fontwork-curve-down", "textCurveDown" }, 264 { "fontwork-fade-up-and-right", "textCascadeUp" }, 265 { "fontwork-fade-up-and-left", "textCascadeDown" }, 266 { "fontwork-wave", "textWave1" }, 267 { "mso-spt157", "textWave2" }, 268 { "mso-spt158", "textWave3" }, 269 { "mso-spt159", "textWave4" }, 270 { "fontwork-inflate", "textInflate" }, 271 { "mso-spt161", "textDeflate" }, 272 { "mso-spt162", "textInflateBottom" }, 273 { "mso-spt163", "textDeflateBottom" }, 274 { "mso-spt164", "textInflateTop" }, 275 { "mso-spt165", "textDeflateTop" }, 276 { "mso-spt166", "textDeflateInflate" }, 277 { "mso-spt167", "textDeflateInflateDeflate" }, 278 { "fontwork-fade-right", "textFadeRight" }, 279 { "fontwork-fade-left", "textFadeLeft" }, 280 { "fontwork-fade-up", "textFadeUp" }, 281 { "fontwork-fade-down", "textFadeDown" }, 282 { "fontwork-slant-up", "textSlantUp" }, 283 { "fontwork-slant-down", "textSlantDown" }, 284 { "mso-spt174", "textCanUp" }, 285 { "mso-spt175", "textCanDown" }, 286 { "flowchart-alternate-process", "flowChartAlternateProcess" }, 287 { "flowchart-off-page-connector", "flowChartOffpageConnector" }, 288 { "mso-spt178", "callout90" }, 289 { "mso-spt179", "accentCallout90" }, 290 { "mso-spt180", "borderCallout90" }, 291 { "mso-spt182", "leftRightUpArrow" }, 292 { "sun", "sun" }, 293 { "moon", "moon" }, 294 { "bracket-pair", "bracketPair" }, 295 { "brace-pair", "bracePair" }, 296 { "star4", "seal4" }, 297 { "mso-spt188", "doubleWave" }, 298 { "mso-spt189", "actionButtonBlank" }, 299 { "mso-spt190", "actionButtonHome" }, 300 { "mso-spt191", "actionButtonHelp" }, 301 { "mso-spt192", "actionButtonInformation" }, 302 { "mso-spt193", "actionButtonForwardNext" }, 303 { "mso-spt194", "actionButtonBackPrevious" }, 304 { "mso-spt195", "actionButtonEnd" }, 305 { "mso-spt196", "actionButtonBeginning" }, 306 { "mso-spt197", "actionButtonReturn" }, 307 { "mso-spt198", "actionButtonDocument" }, 308 { "mso-spt199", "actionButtonSound" }, 309 { "mso-spt200", "actionButtonMovie" }, 310 { "mso-spt201", "hostControl" }, 311 { "mso-spt202", "rect" } 312 }; 313 314 struct StringCheck 315 { 316 bool operator()( const char* s1, const char* s2 ) const 317 { 318 return strcmp( s1, s2 ) == 0; 319 } 320 }; 321 322 typedef std::hash_map< const char*, const char*, std::hash<const char*>, StringCheck> CustomShapeTypeTranslationHashMap; 323 static CustomShapeTypeTranslationHashMap* pCustomShapeTypeTranslationHashMap = NULL; 324 325 static const char* lcl_GetPresetGeometry( const char* sShapeType ) 326 { 327 const char* sPresetGeo; 328 329 if( pCustomShapeTypeTranslationHashMap == NULL ) 330 { 331 pCustomShapeTypeTranslationHashMap = new CustomShapeTypeTranslationHashMap (); 332 for( unsigned int i = 0; i < sizeof( pCustomShapeTypeTranslationTable )/sizeof( CustomShapeTypeTranslationTable ); i ++ ) 333 { 334 (*pCustomShapeTypeTranslationHashMap)[ pCustomShapeTypeTranslationTable[ i ].sOOo ] = pCustomShapeTypeTranslationTable[ i ].sMSO; 335 //DBG(printf("type OOo: %s MSO: %s\n", pCustomShapeTypeTranslationTable[ i ].sOOo, pCustomShapeTypeTranslationTable[ i ].sMSO)); 336 } 337 } 338 339 sPresetGeo = (*pCustomShapeTypeTranslationHashMap)[ sShapeType ]; 340 341 if( sPresetGeo == NULL ) 342 sPresetGeo = "rect"; 343 344 return sPresetGeo; 345 } 346 347 namespace oox { namespace drawingml { 348 349 #define GETA(propName) \ 350 GetProperty( rXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( #propName ) ) ) 351 352 #define GETAD(propName) \ 353 ( GetPropertyAndState( rXPropSet, rXPropState, String( RTL_CONSTASCII_USTRINGPARAM( #propName ) ), eState ) && eState == beans::PropertyState_DIRECT_VALUE ) 354 355 #define GET(variable, propName) \ 356 if ( GETA(propName) ) \ 357 mAny >>= variable; 358 359 ShapeExport::ShapeExport( sal_Int32 nXmlNamespace, FSHelperPtr pFS, ::oox::core::XmlFilterBase* pFB, DocumentType eDocumentType ) 360 : DrawingML( pFS, pFB, eDocumentType ) 361 , mnXmlNamespace( nXmlNamespace ) 362 , mnShapeIdMax( 1 ) 363 , mnPictureIdMax( 1 ) 364 , maFraction( 1, 576 ) 365 , maMapModeSrc( MAP_100TH_MM ) 366 , maMapModeDest( MAP_INCH, Point(), maFraction, maFraction ) 367 { 368 } 369 370 sal_Int32 ShapeExport::GetXmlNamespace() const 371 { 372 return mnXmlNamespace; 373 } 374 375 ShapeExport& ShapeExport::SetXmlNamespace( sal_Int32 nXmlNamespace ) 376 { 377 mnXmlNamespace = nXmlNamespace; 378 return *this; 379 } 380 381 awt::Size ShapeExport::MapSize( const awt::Size& rSize ) const 382 { 383 Size aRetSize( OutputDevice::LogicToLogic( Size( rSize.Width, rSize.Height ), maMapModeSrc, maMapModeDest ) ); 384 385 if ( !aRetSize.Width() ) 386 aRetSize.Width()++; 387 if ( !aRetSize.Height() ) 388 aRetSize.Height()++; 389 return awt::Size( aRetSize.Width(), aRetSize.Height() ); 390 } 391 392 sal_Bool ShapeExport::NonEmptyText( Reference< XShape > xShape ) 393 { 394 Reference< XSimpleText > xText( xShape, UNO_QUERY ); 395 396 return ( xText.is() && xText->getString().getLength() ); 397 } 398 399 ShapeExport& ShapeExport::WriteBezierShape( Reference< XShape > xShape, sal_Bool bClosed ) 400 { 401 DBG(printf("write open bezier shape\n")); 402 403 FSHelperPtr pFS = GetFS(); 404 pFS->startElementNS( mnXmlNamespace, XML_sp, FSEND ); 405 406 PolyPolygon aPolyPolygon = EscherPropertyContainer::GetPolyPolygon( xShape ); 407 Rectangle aRect( aPolyPolygon.GetBoundRect() ); 408 awt::Size size = MapSize( awt::Size( aRect.GetWidth(), aRect.GetHeight() ) ); 409 410 DBG(printf("poly count %d\nsize: %d x %d", aPolyPolygon.Count(), int( size.Width ), int( size.Height ))); 411 412 // non visual shape properties 413 pFS->startElementNS( mnXmlNamespace, XML_nvSpPr, FSEND ); 414 pFS->singleElementNS( mnXmlNamespace, XML_cNvPr, 415 XML_id, I32S( GetNewShapeID( xShape ) ), 416 XML_name, IDS( Freeform ), 417 FSEND ); 418 pFS->singleElementNS( mnXmlNamespace, XML_cNvSpPr, FSEND ); 419 WriteNonVisualProperties( xShape ); 420 pFS->endElementNS( mnXmlNamespace, XML_nvSpPr ); 421 422 // visual shape properties 423 pFS->startElementNS( mnXmlNamespace, XML_spPr, FSEND ); 424 WriteTransformation( aRect ); 425 WritePolyPolygon( aPolyPolygon ); 426 Reference< XPropertySet > xProps( xShape, UNO_QUERY ); 427 if( xProps.is() ) { 428 if( bClosed ) 429 WriteFill( xProps ); 430 WriteOutline( xProps ); 431 } 432 433 pFS->endElementNS( mnXmlNamespace, XML_spPr ); 434 435 // write text 436 WriteTextBox( xShape ); 437 438 pFS->endElementNS( mnXmlNamespace, XML_sp ); 439 440 return *this; 441 } 442 443 ShapeExport& ShapeExport::WriteClosedBezierShape( Reference< XShape > xShape ) 444 { 445 return WriteBezierShape( xShape, TRUE ); 446 } 447 448 ShapeExport& ShapeExport::WriteOpenBezierShape( Reference< XShape > xShape ) 449 { 450 return WriteBezierShape( xShape, FALSE ); 451 } 452 453 ShapeExport& ShapeExport::WriteCustomShape( Reference< XShape > xShape ) 454 { 455 DBG(printf("write custom shape\n")); 456 457 Reference< XPropertySet > rXPropSet( xShape, UNO_QUERY ); 458 SdrObjCustomShape* pShape = (SdrObjCustomShape*) GetSdrObjectFromXShape( xShape ); 459 sal_Bool bIsDefaultObject = EscherPropertyContainer::IsDefaultObject( pShape ); 460 sal_Bool bPredefinedHandlesUsed = TRUE; 461 OUString sShapeType; 462 sal_uInt32 nMirrorFlags = 0; 463 MSO_SPT eShapeType = EscherPropertyContainer::GetCustomShapeType( xShape, nMirrorFlags, sShapeType ); 464 const char* sPresetShape = lcl_GetPresetGeometry( USS( sShapeType ) ); 465 DBG(printf("custom shape type: %s ==> %s\n", USS( sShapeType ), sPresetShape)); 466 Sequence< PropertyValue > aGeometrySeq; 467 sal_Int32 nAdjustmentValuesIndex = -1; 468 sal_Int32 nAdjustmentsWhichNeedsToBeConverted = 0; 469 470 if( GETA( CustomShapeGeometry ) ) { 471 DBG(printf("got custom shape geometry\n")); 472 if( mAny >>= aGeometrySeq ) { 473 474 DBG(printf("got custom shape geometry sequence\n")); 475 for( int i = 0; i < aGeometrySeq.getLength(); i++ ) { 476 const PropertyValue& rProp = aGeometrySeq[ i ]; 477 DBG(printf("geometry property: %s\n", USS( rProp.Name ))); 478 479 if( rProp.Name.equalsAscii( "AdjustmentValues" )) 480 nAdjustmentValuesIndex = i; 481 else if( rProp.Name.equalsAscii( "Handles" )) { 482 if( !bIsDefaultObject ) 483 bPredefinedHandlesUsed = FALSE; 484 // TODO: update nAdjustmentsWhichNeedsToBeConverted here 485 } 486 } 487 } 488 } 489 490 FSHelperPtr pFS = GetFS(); 491 pFS->startElementNS( mnXmlNamespace, XML_sp, FSEND ); 492 493 // non visual shape properties 494 pFS->startElementNS( mnXmlNamespace, XML_nvSpPr, FSEND ); 495 pFS->singleElementNS( mnXmlNamespace, XML_cNvPr, 496 XML_id, I32S( GetNewShapeID( xShape ) ), 497 XML_name, IDS( CustomShape ), 498 FSEND ); 499 pFS->singleElementNS( mnXmlNamespace, XML_cNvSpPr, FSEND ); 500 WriteNonVisualProperties( xShape ); 501 pFS->endElementNS( mnXmlNamespace, XML_nvSpPr ); 502 503 // visual shape properties 504 pFS->startElementNS( mnXmlNamespace, XML_spPr, FSEND ); 505 WriteShapeTransformation( xShape ); 506 if( nAdjustmentValuesIndex != -1 ) 507 WritePresetShape( sPresetShape, eShapeType, bPredefinedHandlesUsed, nAdjustmentsWhichNeedsToBeConverted, aGeometrySeq[ nAdjustmentValuesIndex ] ); 508 else 509 WritePresetShape( sPresetShape ); 510 if( rXPropSet.is() ) 511 { 512 WriteFill( rXPropSet ); 513 WriteOutline( rXPropSet ); 514 } 515 516 pFS->endElementNS( mnXmlNamespace, XML_spPr ); 517 518 // write text 519 WriteTextBox( xShape ); 520 521 pFS->endElementNS( mnXmlNamespace, XML_sp ); 522 523 return *this; 524 } 525 526 ShapeExport& ShapeExport::WriteEllipseShape( Reference< XShape > xShape ) 527 { 528 DBG(printf("write ellipse shape\n")); 529 530 FSHelperPtr pFS = GetFS(); 531 532 pFS->startElementNS( mnXmlNamespace, XML_sp, FSEND ); 533 534 // TODO: arc, section, cut, connector 535 536 // non visual shape properties 537 pFS->startElementNS( mnXmlNamespace, XML_nvSpPr, FSEND ); 538 pFS->singleElementNS( mnXmlNamespace, XML_cNvPr, 539 XML_id, I32S( GetNewShapeID( xShape ) ), 540 XML_name, IDS( Ellipse ), 541 FSEND ); 542 pFS->singleElementNS( mnXmlNamespace, XML_cNvSpPr, FSEND ); 543 WriteNonVisualProperties( xShape ); 544 pFS->endElementNS( mnXmlNamespace, XML_nvSpPr ); 545 546 // visual shape properties 547 pFS->startElementNS( mnXmlNamespace, XML_spPr, FSEND ); 548 WriteShapeTransformation( xShape ); 549 WritePresetShape( "ellipse" ); 550 Reference< XPropertySet > xProps( xShape, UNO_QUERY ); 551 if( xProps.is() ) 552 { 553 WriteFill( xProps ); 554 WriteOutline( xProps ); 555 } 556 pFS->endElementNS( mnXmlNamespace, XML_spPr ); 557 558 // write text 559 WriteTextBox( xShape ); 560 561 pFS->endElementNS( mnXmlNamespace, XML_sp ); 562 563 return *this; 564 } 565 566 ShapeExport& ShapeExport::WriteFill( Reference< XPropertySet > xPropSet ) 567 { 568 FillStyle aFillStyle( FillStyle_NONE ); 569 xPropSet->getPropertyValue( S( "FillStyle" ) ) >>= aFillStyle; 570 571 if( aFillStyle == FillStyle_BITMAP ) 572 { 573 //DBG(printf ("FillStyle_BITMAP properties\n")); 574 //DBG(dump_pset(rXPropSet)); 575 } 576 577 if( aFillStyle == FillStyle_NONE || 578 aFillStyle == FillStyle_HATCH ) 579 return *this; 580 581 switch( aFillStyle ) 582 { 583 case ::com::sun::star::drawing::FillStyle_SOLID : 584 WriteSolidFill( xPropSet ); 585 break; 586 case ::com::sun::star::drawing::FillStyle_GRADIENT : 587 WriteGradientFill( xPropSet ); 588 break; 589 case ::com::sun::star::drawing::FillStyle_BITMAP : 590 WriteBlipFill( xPropSet, S( "FillBitmapURL" ) ); 591 break; 592 default: 593 ; 594 } 595 596 return *this; 597 } 598 599 ShapeExport& ShapeExport::WriteGraphicObjectShape( Reference< XShape > xShape ) 600 { 601 DBG(printf("write graphic object shape\n")); 602 603 if( NonEmptyText( xShape ) ) 604 { 605 WriteTextShape( xShape ); 606 607 //DBG(dump_pset(mXPropSet)); 608 609 return *this; 610 } 611 612 DBG(printf("graphicObject without text\n")); 613 614 OUString sGraphicURL; 615 Reference< XPropertySet > xShapeProps( xShape, UNO_QUERY ); 616 if( !xShapeProps.is() || !( xShapeProps->getPropertyValue( S( "GraphicURL" ) ) >>= sGraphicURL ) ) 617 { 618 DBG(printf("no graphic URL found\n")); 619 return *this; 620 } 621 622 FSHelperPtr pFS = GetFS(); 623 624 pFS->startElementNS( mnXmlNamespace, XML_pic, FSEND ); 625 626 pFS->startElementNS( mnXmlNamespace, XML_nvPicPr, FSEND ); 627 628 OUString sName, sDescr; 629 bool bHaveName = xShapeProps->getPropertyValue( S( "Name" ) ) >>= sName; 630 bool bHaveDesc = xShapeProps->getPropertyValue( S( "Description" ) ) >>= sDescr; 631 632 pFS->singleElementNS( mnXmlNamespace, XML_cNvPr, 633 XML_id, I32S( GetNewShapeID( xShape ) ), 634 XML_name, bHaveName ? USS( sName ) : (OString("Picture ") + OString::valueOf( mnPictureIdMax++ )).getStr(), 635 XML_descr, bHaveDesc ? USS( sDescr ) : NULL, 636 FSEND ); 637 // OOXTODO: //cNvPr children: XML_extLst, XML_hlinkClick, XML_hlinkHover 638 639 pFS->singleElementNS( mnXmlNamespace, XML_cNvPicPr, 640 // OOXTODO: XML_preferRelativeSize 641 FSEND ); 642 643 WriteNonVisualProperties( xShape ); 644 645 pFS->endElementNS( mnXmlNamespace, XML_nvPicPr ); 646 647 pFS->startElementNS( mnXmlNamespace, XML_blipFill, FSEND ); 648 649 WriteBlip( sGraphicURL ); 650 651 bool bStretch = false; 652 if( ( xShapeProps->getPropertyValue( S( "FillBitmapStretch" ) ) >>= bStretch ) && bStretch ) 653 { 654 WriteStretch(); 655 } 656 657 pFS->endElementNS( mnXmlNamespace, XML_blipFill ); 658 659 // visual shape properties 660 pFS->startElementNS( mnXmlNamespace, XML_spPr, FSEND ); 661 WriteShapeTransformation( xShape ); 662 WritePresetShape( "rect" ); 663 pFS->endElementNS( mnXmlNamespace, XML_spPr ); 664 665 pFS->endElementNS( mnXmlNamespace, XML_pic ); 666 667 return *this; 668 } 669 670 ShapeExport& ShapeExport::WriteConnectorShape( Reference< XShape > xShape ) 671 { 672 sal_Bool bFlipH = false; 673 sal_Bool bFlipV = false; 674 675 DBG(printf("write connector shape\n")); 676 677 FSHelperPtr pFS = GetFS(); 678 679 const char* sGeometry = "line"; 680 Reference< XPropertySet > rXPropSet( xShape, UNO_QUERY ); 681 Reference< XPropertyState > rXPropState( xShape, UNO_QUERY ); 682 awt::Point aStartPoint, aEndPoint; 683 Reference< XShape > rXShapeA; 684 Reference< XShape > rXShapeB; 685 PropertyState eState; 686 ConnectorType eConnectorType; 687 if( GETAD( EdgeKind ) ) { 688 mAny >>= eConnectorType; 689 690 switch( eConnectorType ) { 691 case ConnectorType_CURVE: 692 sGeometry = "curvedConnector3"; 693 break; 694 case ConnectorType_STANDARD: 695 sGeometry = "bentConnector3"; 696 break; 697 default: 698 case ConnectorType_LINE: 699 case ConnectorType_LINES: 700 sGeometry = "straightConnector1"; 701 break; 702 } 703 704 if( GETAD( EdgeStartPoint ) ) { 705 mAny >>= aStartPoint; 706 if( GETAD( EdgeEndPoint ) ) { 707 mAny >>= aEndPoint; 708 } 709 } 710 GET( rXShapeA, EdgeStartConnection ); 711 GET( rXShapeB, EdgeEndConnection ); 712 } 713 EscherConnectorListEntry aConnectorEntry( xShape, aStartPoint, rXShapeA, aEndPoint, rXShapeB ); 714 715 Rectangle aRect( Point( aStartPoint.X, aStartPoint.Y ), Point( aEndPoint.X, aEndPoint.Y ) ); 716 if( aRect.getWidth() < 0 ) { 717 bFlipH = TRUE; 718 aRect.setX( aEndPoint.X ); 719 aRect.setWidth( aStartPoint.X - aEndPoint.X ); 720 } 721 722 if( aRect.getHeight() < 0 ) { 723 bFlipV = TRUE; 724 aRect.setY( aEndPoint.Y ); 725 aRect.setHeight( aStartPoint.Y - aEndPoint.Y ); 726 } 727 728 pFS->startElementNS( mnXmlNamespace, XML_cxnSp, FSEND ); 729 730 // non visual shape properties 731 pFS->startElementNS( mnXmlNamespace, XML_nvCxnSpPr, FSEND ); 732 pFS->singleElementNS( mnXmlNamespace, XML_cNvPr, 733 XML_id, I32S( GetNewShapeID( xShape ) ), 734 XML_name, IDS( Line ), 735 FSEND ); 736 // non visual connector shape drawing properties 737 pFS->startElementNS( mnXmlNamespace, XML_cNvCxnSpPr, FSEND ); 738 WriteConnectorConnections( aConnectorEntry, GetShapeID( rXShapeA ), GetShapeID( rXShapeB ) ); 739 pFS->endElementNS( mnXmlNamespace, XML_cNvCxnSpPr ); 740 pFS->singleElementNS( mnXmlNamespace, XML_nvPr, FSEND ); 741 pFS->endElementNS( mnXmlNamespace, XML_nvCxnSpPr ); 742 743 // visual shape properties 744 pFS->startElementNS( mnXmlNamespace, XML_spPr, FSEND ); 745 WriteTransformation( aRect, bFlipH, bFlipV ); 746 // TODO: write adjustments (ppt export doesn't work well there either) 747 WritePresetShape( sGeometry ); 748 Reference< XPropertySet > xShapeProps( xShape, UNO_QUERY ); 749 if( xShapeProps.is() ) 750 WriteOutline( xShapeProps ); 751 pFS->endElementNS( mnXmlNamespace, XML_spPr ); 752 753 // write text 754 WriteTextBox( xShape ); 755 756 pFS->endElementNS( mnXmlNamespace, XML_cxnSp ); 757 758 return *this; 759 } 760 761 ShapeExport& ShapeExport::WriteLineShape( Reference< XShape > xShape ) 762 { 763 sal_Bool bFlipH = false; 764 sal_Bool bFlipV = false; 765 766 DBG(printf("write line shape\n")); 767 768 FSHelperPtr pFS = GetFS(); 769 770 pFS->startElementNS( mnXmlNamespace, XML_sp, FSEND ); 771 772 PolyPolygon aPolyPolygon = EscherPropertyContainer::GetPolyPolygon( xShape ); 773 if( aPolyPolygon.Count() == 1 && aPolyPolygon[ 0 ].GetSize() == 2) 774 { 775 const Polygon& rPoly = aPolyPolygon[ 0 ]; 776 777 bFlipH = ( rPoly[ 0 ].X() > rPoly[ 1 ].X() ); 778 bFlipV = ( rPoly[ 0 ].Y() > rPoly[ 1 ].Y() ); 779 } 780 781 // non visual shape properties 782 pFS->startElementNS( mnXmlNamespace, XML_nvSpPr, FSEND ); 783 pFS->singleElementNS( mnXmlNamespace, XML_cNvPr, 784 XML_id, I32S( GetNewShapeID( xShape ) ), 785 XML_name, IDS( Line ), 786 FSEND ); 787 pFS->singleElementNS( mnXmlNamespace, XML_cNvSpPr, FSEND ); 788 WriteNonVisualProperties( xShape ); 789 pFS->endElementNS( mnXmlNamespace, XML_nvSpPr ); 790 791 // visual shape properties 792 pFS->startElementNS( mnXmlNamespace, XML_spPr, FSEND ); 793 WriteShapeTransformation( xShape, bFlipH, bFlipV ); 794 WritePresetShape( "line" ); 795 Reference< XPropertySet > xShapeProps( xShape, UNO_QUERY ); 796 if( xShapeProps.is() ) 797 WriteOutline( xShapeProps ); 798 pFS->endElementNS( mnXmlNamespace, XML_spPr ); 799 800 // write text 801 WriteTextBox( xShape ); 802 803 pFS->endElementNS( mnXmlNamespace, XML_sp ); 804 805 return *this; 806 } 807 808 ShapeExport& ShapeExport::WriteNonVisualDrawingProperties( Reference< XShape > xShape, const char* pName ) 809 { 810 GetFS()->singleElementNS( mnXmlNamespace, XML_cNvPr, 811 XML_id, I32S( GetNewShapeID( xShape ) ), 812 XML_name, pName, 813 FSEND ); 814 815 return *this; 816 } 817 818 ShapeExport& ShapeExport::WriteNonVisualProperties( Reference< XShape > ) 819 { 820 // Override to generate //nvPr elements. 821 return *this; 822 } 823 824 ShapeExport& ShapeExport::WriteRectangleShape( Reference< XShape > xShape ) 825 { 826 DBG(printf("write rectangle shape\n")); 827 828 FSHelperPtr pFS = GetFS(); 829 830 pFS->startElementNS( mnXmlNamespace, XML_sp, FSEND ); 831 832 sal_Int32 nRadius = 0; 833 834 Reference< XPropertySet > xShapeProps( xShape, UNO_QUERY ); 835 if( xShapeProps.is() ) 836 { 837 xShapeProps->getPropertyValue( S( "CornerRadius" ) ) >>= nRadius; 838 } 839 840 if( nRadius ) 841 { 842 nRadius = MapSize( awt::Size( nRadius, 0 ) ).Width; 843 } 844 845 // non visual shape properties 846 pFS->startElementNS( mnXmlNamespace, XML_nvSpPr, FSEND ); 847 pFS->singleElementNS( mnXmlNamespace, XML_cNvPr, 848 XML_id, I32S( GetNewShapeID( xShape ) ), 849 XML_name, IDS( Rectangle ), 850 FSEND ); 851 pFS->singleElementNS( mnXmlNamespace, XML_cNvSpPr, FSEND ); 852 WriteNonVisualProperties( xShape ); 853 pFS->endElementNS( mnXmlNamespace, XML_nvSpPr ); 854 855 // visual shape properties 856 pFS->startElementNS( mnXmlNamespace, XML_spPr, FSEND ); 857 WriteShapeTransformation( xShape ); 858 WritePresetShape( "rect" ); 859 Reference< XPropertySet > xProps( xShape, UNO_QUERY ); 860 if( xProps.is() ) 861 { 862 WriteFill( xProps ); 863 WriteOutline( xProps ); 864 } 865 pFS->endElementNS( mnXmlNamespace, XML_spPr ); 866 867 // write text 868 WriteTextBox( xShape ); 869 870 pFS->endElementNS( mnXmlNamespace, XML_sp ); 871 872 return *this; 873 } 874 875 typedef ShapeExport& (ShapeExport::*ShapeConverter)( Reference< XShape > ); 876 typedef std::hash_map< const char*, ShapeConverter, std::hash<const char*>, StringCheck> NameToConvertMapType; 877 878 static const NameToConvertMapType& lcl_GetConverters() 879 { 880 static bool shape_map_inited = false; 881 static NameToConvertMapType shape_converters; 882 if( shape_map_inited ) 883 { 884 return shape_converters; 885 } 886 887 shape_converters[ "com.sun.star.drawing.ClosedBezierShape" ] = &ShapeExport::WriteClosedBezierShape; 888 shape_converters[ "com.sun.star.drawing.ConnectorShape" ] = &ShapeExport::WriteConnectorShape; 889 shape_converters[ "com.sun.star.drawing.CustomShape" ] = &ShapeExport::WriteCustomShape; 890 shape_converters[ "com.sun.star.drawing.EllipseShape" ] = &ShapeExport::WriteEllipseShape; 891 shape_converters[ "com.sun.star.drawing.GraphicObjectShape" ] = &ShapeExport::WriteGraphicObjectShape; 892 shape_converters[ "com.sun.star.drawing.LineShape" ] = &ShapeExport::WriteLineShape; 893 shape_converters[ "com.sun.star.drawing.OpenBezierShape" ] = &ShapeExport::WriteOpenBezierShape; 894 shape_converters[ "com.sun.star.drawing.RectangleShape" ] = &ShapeExport::WriteRectangleShape; 895 shape_converters[ "com.sun.star.drawing.TextShape" ] = &ShapeExport::WriteTextShape; 896 shape_converters[ "com.sun.star.presentation.DateTimeShape" ] = &ShapeExport::WriteTextShape; 897 shape_converters[ "com.sun.star.presentation.FooterShape" ] = &ShapeExport::WriteTextShape; 898 shape_converters[ "com.sun.star.presentation.HeaderShape" ] = &ShapeExport::WriteTextShape; 899 shape_converters[ "com.sun.star.presentation.NotesShape" ] = &ShapeExport::WriteTextShape; 900 shape_converters[ "com.sun.star.presentation.OutlinerShape" ] = &ShapeExport::WriteTextShape; 901 shape_converters[ "com.sun.star.presentation.SlideNumberShape" ] = &ShapeExport::WriteTextShape; 902 shape_converters[ "com.sun.star.presentation.TitleTextShape" ] = &ShapeExport::WriteTextShape; 903 shape_map_inited = true; 904 905 return shape_converters; 906 } 907 908 ShapeExport& ShapeExport::WriteShape( Reference< XShape > xShape ) 909 { 910 OUString sShapeType = xShape->getShapeType(); 911 DBG( printf( "write shape: %s\n", USS( sShapeType ) ) ); 912 NameToConvertMapType::const_iterator aConverter = lcl_GetConverters().find( USS( sShapeType ) ); 913 if( aConverter == lcl_GetConverters().end() ) 914 { 915 DBG( printf( "unknown shape\n" ) ); 916 return WriteUnknownShape( xShape ); 917 } 918 (this->*(aConverter->second))( xShape ); 919 920 return *this; 921 } 922 923 ShapeExport& ShapeExport::WriteTextBox( Reference< XShape > xShape ) 924 { 925 if( NonEmptyText( xShape ) ) 926 { 927 FSHelperPtr pFS = GetFS(); 928 929 pFS->startElementNS( mnXmlNamespace, XML_txBody, FSEND ); 930 WriteText( xShape ); 931 pFS->endElementNS( mnXmlNamespace, XML_txBody ); 932 } 933 934 return *this; 935 } 936 937 ShapeExport& ShapeExport::WriteTextShape( Reference< XShape > xShape ) 938 { 939 FSHelperPtr pFS = GetFS(); 940 941 pFS->startElementNS( mnXmlNamespace, XML_sp, FSEND ); 942 943 // non visual shape properties 944 pFS->startElementNS( mnXmlNamespace, XML_nvSpPr, FSEND ); 945 WriteNonVisualDrawingProperties( xShape, IDS( TextShape ) ); 946 pFS->singleElementNS( mnXmlNamespace, XML_cNvSpPr, XML_txBox, "1", FSEND ); 947 WriteNonVisualProperties( xShape ); 948 pFS->endElementNS( mnXmlNamespace, XML_nvSpPr ); 949 950 // visual shape properties 951 pFS->startElementNS( mnXmlNamespace, XML_spPr, FSEND ); 952 WriteShapeTransformation( xShape ); 953 WritePresetShape( "rect" ); 954 WriteBlipFill( Reference< XPropertySet >(xShape, UNO_QUERY ), S( "GraphicURL" ) ); 955 pFS->endElementNS( mnXmlNamespace, XML_spPr ); 956 957 WriteTextBox( xShape ); 958 959 pFS->endElementNS( mnXmlNamespace, XML_sp ); 960 961 return *this; 962 } 963 964 ShapeExport& ShapeExport::WriteUnknownShape( Reference< XShape > ) 965 { 966 // Override this method to do something useful. 967 return *this; 968 } 969 970 size_t ShapeExport::ShapeHash::operator()( const ::com::sun::star::uno::Reference < ::com::sun::star::drawing::XShape > rXShape ) const 971 { 972 return maHashFunction( USS( rXShape->getShapeType() ) ); 973 } 974 975 sal_Int32 ShapeExport::GetNewShapeID( const Reference< XShape > rXShape ) 976 { 977 sal_Int32 nID = GetFB()->GetUniqueId(); 978 979 maShapeMap[ rXShape ] = nID; 980 981 return nID; 982 } 983 984 sal_Int32 ShapeExport::GetShapeID( const Reference< XShape > rXShape ) 985 { 986 ShapeHashMap::const_iterator aIter = maShapeMap.find( rXShape ); 987 988 if( aIter == maShapeMap.end() ) 989 return -1; 990 991 return aIter->second; 992 } 993 994 } } 995