LCOV - code coverage report
Current view: top level - filter/source/msfilter - eschesdo.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 411 657 62.6 %
Date: 2015-06-13 12:38:46 Functions: 35 40 87.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include "eschesdo.hxx"
      21             : #include <svx/svdobj.hxx>
      22             : #include <svx/unoapi.hxx>
      23             : #include <svx/svdoashp.hxx>
      24             : #include <svx/unoshape.hxx>
      25             : #include <vcl/outdev.hxx>
      26             : #include <tools/poly.hxx>
      27             : #include <vcl/bitmapex.hxx>
      28             : #include <vcl/graph.hxx>
      29             : #include <tools/debug.hxx>
      30             : #include <svx/fmdpage.hxx>
      31             : #include <toolkit/helper/vclunohelper.hxx>
      32             : #include <com/sun/star/style/VerticalAlignment.hpp>
      33             : #include <com/sun/star/awt/Gradient.hpp>
      34             : #include <com/sun/star/drawing/PointSequence.hpp>
      35             : #include <com/sun/star/drawing/PointSequenceSequence.hpp>
      36             : #include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp>
      37             : #include <com/sun/star/drawing/FlagSequence.hpp>
      38             : #include <com/sun/star/drawing/TextAdjust.hpp>
      39             : #include <com/sun/star/drawing/LineDash.hpp>
      40             : #include <com/sun/star/text/XText.hpp>
      41             : #include <com/sun/star/drawing/CircleKind.hpp>
      42             : #include <com/sun/star/drawing/FillStyle.hpp>
      43             : #include <com/sun/star/task/XStatusIndicator.hpp>
      44             : #include <comphelper/extract.hxx>
      45             : #include <vcl/fltcall.hxx>
      46             : #include <vcl/cvtgrf.hxx>
      47             : #include <com/sun/star/drawing/HomogenMatrix3.hpp>
      48             : #include <basegfx/matrix/b2dhommatrix.hxx>
      49             : #include <basegfx/polygon/b2dpolygontools.hxx>
      50             : #include <basegfx/polygon/b2dpolygon.hxx>
      51             : 
      52             : using namespace ::com::sun::star;
      53             : using namespace ::com::sun::star::beans;
      54             : using namespace ::com::sun::star::container;
      55             : using namespace ::com::sun::star::uno;
      56             : using namespace ::com::sun::star::drawing;
      57             : using namespace ::com::sun::star::text;
      58             : using namespace ::com::sun::star::task;
      59             : using namespace ::com::sun::star::style;
      60             : 
      61             : #define EES_MAP_FRACTION 1440   // 1440 dpi
      62             : 
      63         661 : ImplEESdrWriter::ImplEESdrWriter( EscherEx& rEx )
      64             :     : mpEscherEx(&rEx)
      65             :     , maMapModeSrc(MAP_100TH_MM)
      66             :     // PowerPoint: 576 dpi, WinWord: 1440 dpi, Excel: 1440 dpi
      67             :     , maMapModeDest( MAP_INCH, Point(), Fraction( 1, EES_MAP_FRACTION ), Fraction( 1, EES_MAP_FRACTION ) )
      68             :     , mpPicStrm(NULL)
      69             :     , mpHostAppData(NULL)
      70             :     , mnPagesWritten(0)
      71             :     , mnShapeMasterTitle(0)
      72             :     , mnShapeMasterBody(0)
      73             :     , mnIndices(0)
      74             :     , mnOutlinerCount(0)
      75             :     , mnPrevTextStyle(0)
      76             :     , mnStatMaxValue(0)
      77             :     , mnEffectCount(0)
      78             :     , mbIsTitlePossible(false)
      79             :     , mbStatusIndicator(false)
      80         661 :     , mbStatus(false)
      81             : {
      82         661 : }
      83             : 
      84        1051 : Point ImplEESdrWriter::ImplMapPoint( const Point& rPoint )
      85             : {
      86        1051 :     return OutputDevice::LogicToLogic( rPoint, maMapModeSrc, maMapModeDest );
      87             : }
      88             : 
      89        1052 : Size ImplEESdrWriter::ImplMapSize( const Size& rSize )
      90             : {
      91        1052 :     Size aRetSize( OutputDevice::LogicToLogic( rSize, maMapModeSrc, maMapModeDest ) );
      92             : 
      93        1052 :     if ( !aRetSize.Width() )
      94          31 :         aRetSize.Width()++;
      95        1052 :     if ( !aRetSize.Height() )
      96          38 :         aRetSize.Height()++;
      97        1052 :     return aRetSize;
      98             : }
      99             : 
     100          36 : void ImplEESdrWriter::ImplFlipBoundingBox( ImplEESdrObject& rObj, EscherPropertyContainer& rPropOpt )
     101             : {
     102          36 :     sal_Int32 nAngle = rObj.GetAngle();
     103          36 :     Rectangle aRect( rObj.GetRect() );
     104             : 
     105             :     // for position calculations, we normalize the angle between 0 and 90 degrees
     106          36 :     if ( nAngle < 0 )
     107           0 :         nAngle = ( 36000 + nAngle ) % 36000;
     108          36 :     if ( nAngle % 18000 == 0 )
     109           5 :         nAngle = 0;
     110          99 :     while ( nAngle > 9000 )
     111          27 :         nAngle = ( 18000 - ( nAngle % 18000 ) );
     112             : 
     113          36 :     double fVal = (double)nAngle * F_PI18000;
     114          36 :     double  fCos = cos( fVal );
     115          36 :     double  fSin = sin( fVal );
     116             : 
     117          36 :     double  nWidthHalf = (double) aRect.GetWidth() / 2;
     118          36 :     double  nHeightHalf = (double) aRect.GetHeight() / 2;
     119             : 
     120             :     // fdo#70838:
     121             :     // when you rotate an object, the top-left corner of its bounding box is moved
     122             :     // nXDiff and nYDiff pixels. To get their values we use these equations:
     123             :     //
     124             :     //   fSin * nHeightHalf + fCos * nWidthHalf  == nXDiff + nWidthHalf
     125             :     //   fSin * nWidthHalf  + fCos * nHeightHalf == nYDiff + nHeightHalf
     126             : 
     127          36 :     double nXDiff = fSin * nHeightHalf + fCos * nWidthHalf  - nWidthHalf;
     128          36 :     double nYDiff = fSin * nWidthHalf  + fCos * nHeightHalf - nHeightHalf;
     129             : 
     130          36 :     aRect.Move( (sal_Int32) nXDiff, (sal_Int32) nYDiff );
     131             : 
     132             :     // calculate the proper angle value to be saved
     133          36 :     nAngle = rObj.GetAngle();
     134          36 :     if ( nAngle < 0 )
     135           0 :         nAngle = ( 36000 + nAngle ) % 36000;
     136             :     else
     137          36 :         nAngle = ( 36000 - ( nAngle % 36000 ) );
     138             : 
     139          36 :     nAngle *= 655;
     140          36 :     nAngle += 0x8000;
     141          36 :     nAngle &=~0xffff;                                   // nAngle round to full degrees
     142          36 :     rPropOpt.AddOpt( ESCHER_Prop_Rotation, nAngle );
     143             : 
     144          36 :     rObj.SetAngle( nAngle );
     145          36 :     rObj.SetRect( aRect );
     146          36 : }
     147             : 
     148             : 
     149             : 
     150             : #define ADD_SHAPE( nType, nFlags )                              \
     151             : {                                                               \
     152             :     nShapeType = nType;                                         \
     153             :     nShapeID = mpEscherEx->GenerateShapeId();                   \
     154             :     rObj.SetShapeId( nShapeID );                                \
     155             :     mpEscherEx->AddShape( (sal_uInt32)nType, (sal_uInt32)nFlags, nShapeID );    \
     156             :     rSolverContainer.AddShape( rObj.GetShapeRef(), nShapeID );  \
     157             : }
     158             : 
     159             : #define SHAPE_TEXT( bFill )                                         \
     160             : {                                                                   \
     161             :     mpEscherEx->OpenContainer( ESCHER_SpContainer );                \
     162             :     ADD_SHAPE( ESCHER_ShpInst_TextBox, 0xa00 );                     \
     163             :     if ( bFill )                                                    \
     164             :         aPropOpt.CreateFillProperties( rObj.mXPropSet, true );  \
     165             :     if( rObj.ImplGetText() )                                        \
     166             :         aPropOpt.CreateTextProperties( rObj.mXPropSet,              \
     167             :             mpEscherEx->QueryTextID( rObj.GetShapeRef(),            \
     168             :                 rObj.GetShapeId() ) );                              \
     169             : }
     170             : 
     171        1024 : sal_uInt32 ImplEESdrWriter::ImplWriteShape( ImplEESdrObject& rObj,
     172             :                                 EscherSolverContainer& rSolverContainer,
     173             :                                 ImplEESdrPageType ePageType, const bool bOOxmlExport )
     174             : {
     175        1024 :     sal_uInt32 nShapeID = 0;
     176        1024 :     sal_uInt16 nShapeType = 0;
     177        1024 :     bool bDontWriteText = false;        // if a metafile is written as shape replacement, then the text is already part of the metafile
     178        1024 :     bool bAdditionalText = false;
     179        1024 :     sal_uInt32 nGrpShapeID = 0;
     180             : 
     181             :     do {
     182        1024 :         mpHostAppData = mpEscherEx->StartShape( rObj.GetShapeRef(), (mpEscherEx->GetGroupLevel() > 1) ? &rObj.GetRect() : 0 );
     183        1024 :         if ( mpHostAppData && mpHostAppData->DontWriteShape() )
     184         111 :             break;
     185             : 
     186             :         // #i51348# get shape name
     187         995 :         OUString aShapeName;
     188         995 :         if( const SdrObject* pSdrObj = rObj.GetSdrObject() )
     189         995 :             if (!pSdrObj->GetName().isEmpty())
     190         556 :                 aShapeName = pSdrObj->GetName();
     191        1937 :         uno::Reference< drawing::XShape> mXShape(rObj.GetShapeRef(), uno::UNO_QUERY);
     192         995 :         if (mXShape.is())
     193             :         {
     194         995 :             uno::Reference<beans::XPropertySet> xPropertySet(mXShape, uno::UNO_QUERY);
     195         995 :             if (xPropertySet.is())
     196             :             {
     197         995 :                 uno::Sequence<beans::PropertyValue> aGrabBag;
     198        1990 :                 uno::Reference< XPropertySetInfo > xPropInfo = xPropertySet->getPropertySetInfo();
     199         995 :                 if ( xPropInfo.is() && xPropInfo->hasPropertyByName( "InteropGrabBag" ) )
     200             :                 {
     201         882 :                     xPropertySet->getPropertyValue( "InteropGrabBag" ) >>= aGrabBag;
     202        2820 :                     for (int i=0; i< aGrabBag.getLength();  i++)
     203             :                     {
     204        1942 :                         if (aGrabBag[i].Name == "mso-edit-as")
     205             :                         {
     206           4 :                             OUString rEditAs;
     207           4 :                             aGrabBag[i].Value >>= rEditAs;
     208           4 :                             mpEscherEx->SetEditAs(rEditAs);
     209           4 :                             break;
     210             :                         }
     211             :                     }
     212         995 :                 }
     213         995 :             }
     214             :         }
     215             : 
     216         995 :         Point aTextRefPoint;
     217             : 
     218         995 :         if( rObj.GetType() == "drawing.Group" )
     219             :         {
     220          53 :             Reference< XIndexAccess > xXIndexAccess( rObj.GetShapeRef(), UNO_QUERY );
     221             : 
     222          53 :             if( xXIndexAccess.is() && 0 != xXIndexAccess->getCount() )
     223             :             {
     224          53 :                 nShapeID = mpEscherEx->EnterGroup( aShapeName, &rObj.GetRect() );
     225          53 :                 nShapeType = ESCHER_ShpInst_Min;
     226             : 
     227         647 :                 for( sal_uInt32 n = 0, nCnt = xXIndexAccess->getCount();
     228             :                         n < nCnt; ++n )
     229             :                 {
     230             :                     ImplEESdrObject aObj( *this, *static_cast<Reference< XShape > const *>(
     231         594 :                                     xXIndexAccess->getByIndex( n ).getValue()) );
     232         594 :                     if( aObj.IsValid() )
     233             :                     {
     234         594 :                         aObj.SetOOXML(bOOxmlExport);
     235         594 :                         ImplWriteShape( aObj, rSolverContainer, ePageType, bOOxmlExport );
     236             :                     }
     237         594 :                 }
     238          53 :                 mpEscherEx->LeaveGroup();
     239             :             }
     240          53 :             break;
     241             :         }
     242         942 :         rObj.SetAngle( rObj.ImplGetInt32PropertyValue( OUString( "RotateAngle" ) ));
     243             : 
     244        3768 :         if( ( rObj.ImplGetPropertyValue( OUString( "IsFontwork" ) ) &&
     245        3768 :             ::cppu::any2bool( rObj.GetUsrAny() ) ) ||
     246         942 :             rObj.GetType() == "drawing.Measure" )
     247             :         {
     248           6 :             rObj.SetType("drawing.dontknow");
     249             :         }
     250             : 
     251         942 :         const ::com::sun::star::awt::Size   aSize100thmm( rObj.GetShapeRef()->getSize() );
     252         942 :         const ::com::sun::star::awt::Point  aPoint100thmm( rObj.GetShapeRef()->getPosition() );
     253         942 :         Rectangle   aRect100thmm( Point( aPoint100thmm.X, aPoint100thmm.Y ), Size( aSize100thmm.Width, aSize100thmm.Height ) );
     254         942 :         if ( !mpPicStrm )
     255         929 :             mpPicStrm = mpEscherEx->QueryPictureStream();
     256        1884 :         EscherPropertyContainer aPropOpt( mpEscherEx->GetGraphicProvider(), mpPicStrm, aRect100thmm );
     257             : 
     258             :         // #i51348# shape name
     259         942 :         if (!aShapeName.isEmpty())
     260         537 :             aPropOpt.AddOpt( ESCHER_Prop_wzName, aShapeName );
     261         942 :         if ( InteractionInfo* pInteraction = mpHostAppData ? mpHostAppData->GetInteractionInfo():NULL )
     262             :         {
     263           3 :             const std::unique_ptr< SvMemoryStream >& pMemStrm = pInteraction->getHyperlinkRecord();
     264           3 :             if ( pMemStrm.get() )
     265             :             {
     266           3 :                 pMemStrm->ObjectOwnsMemory( false );
     267           3 :                 sal_uInt8 const * pBuf = static_cast<sal_uInt8 const *>(pMemStrm->GetData());
     268           3 :                 sal_uInt32 nSize = pMemStrm->Seek( STREAM_SEEK_TO_END );
     269           3 :                 aPropOpt.AddOpt( ESCHER_Prop_pihlShape, false, nSize, const_cast<sal_uInt8 *>(pBuf), nSize );
     270             :             }
     271           3 :             if ( pInteraction->hasInteraction() )
     272           3 :                 aPropOpt.AddOpt( ESCHER_Prop_fPrint, 0x00080008 );
     273             :         }
     274             : 
     275         942 :         if ( rObj.GetType() == "drawing.Custom" )
     276             :         {
     277         413 :             mpEscherEx->OpenContainer( ESCHER_SpContainer );
     278             :             sal_uInt32 nMirrorFlags;
     279             : 
     280         413 :             OUString sCustomShapeType;
     281         413 :             MSO_SPT eShapeType = EscherPropertyContainer::GetCustomShapeType( rObj.GetShapeRef(), nMirrorFlags, sCustomShapeType, rObj.GetOOXML() );
     282         413 :             if ( sCustomShapeType == "col-502ad400" || sCustomShapeType == "col-60da8460" )
     283             :             {
     284           0 :                 ADD_SHAPE( ESCHER_ShpInst_PictureFrame, 0xa00 );
     285           0 :                 if ( aPropOpt.CreateGraphicProperties( rObj.mXPropSet, "MetaFile", false ) )
     286             :                 {
     287           0 :                     aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x800080 );
     288           0 :                     aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x100000 );        // no fill
     289           0 :                     aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x90000 );        // no linestyle
     290           0 :                         SdrObject* pObj = GetSdrObjectFromXShape( rObj.GetShapeRef() );
     291           0 :                     if ( pObj )
     292             :                     {
     293           0 :                         Rectangle aBound = pObj->GetCurrentBoundRect();
     294           0 :                         Point aPosition( ImplMapPoint( aBound.TopLeft() ) );
     295           0 :                         Size aSize( ImplMapSize( aBound.GetSize() ) );
     296           0 :                         rObj.SetRect( Rectangle( aPosition, aSize ) );
     297           0 :                         rObj.SetAngle( 0 );
     298           0 :                         bDontWriteText = true;
     299             :                     }
     300             :                 }
     301             :             }
     302             :             else
     303             :             {
     304         413 :                 ADD_SHAPE(
     305             :                     sal::static_int_cast< sal_uInt16 >(eShapeType),
     306             :                     nMirrorFlags | 0xa00 );
     307         413 :                 aPropOpt.CreateCustomShapeProperties( eShapeType, rObj.GetShapeRef() );
     308         413 :                 aPropOpt.CreateFillProperties( rObj.mXPropSet, true );
     309         413 :                 if ( rObj.ImplGetText() )
     310             :                 {
     311         163 :                     if ( !aPropOpt.IsFontWork() )
     312             :                         aPropOpt.CreateTextProperties( rObj.mXPropSet, mpEscherEx->QueryTextID(
     313         146 :                             rObj.GetShapeRef(), rObj.GetShapeId() ), true, false );
     314             :                 }
     315         413 :             }
     316             :         }
     317         529 :         else if ( rObj.GetType() == "drawing.Rectangle" )
     318             :         {
     319          57 :             mpEscherEx->OpenContainer( ESCHER_SpContainer );
     320             :             sal_Int32 nRadius = (sal_Int32)rObj.ImplGetInt32PropertyValue(
     321          57 :                                             OUString( "CornerRadius" ));
     322          57 :             if( nRadius )
     323             :             {
     324           1 :                 nRadius = ImplMapSize( Size( nRadius, 0 )).Width();
     325           1 :                 ADD_SHAPE( ESCHER_ShpInst_RoundRectangle, 0xa00 );  // Flags: Connector | HasSpt
     326           1 :                 sal_Int32 nLength = rObj.GetRect().GetWidth();
     327           1 :                 if ( nLength > rObj.GetRect().GetHeight() )
     328           1 :                     nLength = rObj.GetRect().GetHeight();
     329           1 :                 nLength >>= 1;
     330           1 :                 if ( nRadius >= nLength || nLength == 0 )
     331           0 :                     nRadius = 0x2a30;                           // 0x2a30 is PPTs maximum radius
     332             :                 else
     333           1 :                     nRadius = ( 0x2a30 * nRadius ) / nLength;
     334           1 :                 aPropOpt.AddOpt( ESCHER_Prop_adjustValue, nRadius );
     335             :             }
     336             :             else
     337             :             {
     338          56 :                 ADD_SHAPE( ESCHER_ShpInst_Rectangle, 0xa00 );           // Flags: Connector | HasSpt
     339             :             }
     340          57 :             aPropOpt.CreateFillProperties( rObj.mXPropSet, true );
     341          57 :             if( rObj.ImplGetText() )
     342             :                 aPropOpt.CreateTextProperties( rObj.mXPropSet,
     343           1 :                     mpEscherEx->QueryTextID( rObj.GetShapeRef(),
     344           2 :                         rObj.GetShapeId() ), false, false );
     345             :         }
     346         472 :         else if ( rObj.GetType() == "drawing.Ellipse" )
     347             :         {
     348           0 :             CircleKind  eCircleKind = CircleKind_FULL;
     349           0 :             PolyStyle   ePolyKind = PolyStyle();
     350           0 :             if ( rObj.ImplGetPropertyValue( OUString( "CircleKind" ) ) )
     351             :             {
     352           0 :                 eCircleKind = *( static_cast<CircleKind const *>(rObj.GetUsrAny().getValue()) );
     353           0 :                 switch ( eCircleKind )
     354             :                 {
     355             :                     case CircleKind_SECTION :
     356             :                     {
     357           0 :                         ePolyKind = POLY_PIE;
     358             :                     }
     359           0 :                     break;
     360             :                     case CircleKind_ARC :
     361             :                     {
     362           0 :                         ePolyKind = POLY_ARC;
     363             :                     }
     364           0 :                     break;
     365             : 
     366             :                     case CircleKind_CUT :
     367             :                     {
     368           0 :                         ePolyKind = POLY_CHORD;
     369             :                     }
     370           0 :                     break;
     371             : 
     372             :                     default:
     373           0 :                         eCircleKind = CircleKind_FULL;
     374             :                 }
     375             :             }
     376           0 :             if ( eCircleKind == CircleKind_FULL )
     377             :             {
     378           0 :                 mpEscherEx->OpenContainer( ESCHER_SpContainer );
     379           0 :                 ADD_SHAPE( ESCHER_ShpInst_Ellipse, 0xa00 );         // Flags: Connector | HasSpt
     380           0 :                 aPropOpt.CreateFillProperties( rObj.mXPropSet, true );
     381             :             }
     382             :             else
     383             :             {
     384             :                 sal_Int32 nStartAngle, nEndAngle;
     385           0 :                 if ( !rObj.ImplGetPropertyValue( OUString( "CircleStartAngle" ) ) )
     386           0 :                     break;
     387           0 :                 nStartAngle = *( static_cast<sal_Int32 const *>(rObj.GetUsrAny().getValue()) );
     388           0 :                 if( !rObj.ImplGetPropertyValue( OUString( "CircleEndAngle" ) ) )
     389           0 :                     break;
     390           0 :                 nEndAngle = *( static_cast<sal_Int32 const *>(rObj.GetUsrAny().getValue()) );
     391             : 
     392           0 :                 Point aStart, aEnd, aCenter;
     393           0 :                 aStart.X() = (sal_Int32)( ( cos( (double)( nStartAngle *
     394           0 :                                                 F_PI18000 ) ) * 100.0 ) );
     395           0 :                 aStart.Y() = - (sal_Int32)( ( sin( (double)( nStartAngle *
     396           0 :                                                 F_PI18000 ) ) * 100.0 ) );
     397           0 :                 aEnd.X() = (sal_Int32)( ( cos( (double)( nEndAngle *
     398           0 :                                                 F_PI18000 ) ) * 100.0 ) );
     399           0 :                 aEnd.Y() = - (sal_Int32)( ( sin( (double)( nEndAngle *
     400           0 :                                                 F_PI18000 ) ) * 100.0 ) );
     401           0 :                 const Rectangle& rRect = aRect100thmm;
     402           0 :                 aCenter.X() = rRect.Left() + ( rRect.GetWidth() / 2 );
     403           0 :                 aCenter.Y() = rRect.Top() + ( rRect.GetHeight() / 2 );
     404           0 :                 aStart.X() += aCenter.X();
     405           0 :                 aStart.Y() += aCenter.Y();
     406           0 :                 aEnd.X() += aCenter.X();
     407           0 :                 aEnd.Y() += aCenter.Y();
     408           0 :                 Polygon aPolygon( rRect, aStart, aEnd, ePolyKind );
     409           0 :                 if( rObj.GetAngle() )
     410             :                 {
     411           0 :                     aPolygon.Rotate( rRect.TopLeft(), (sal_uInt16)( rObj.GetAngle() / 10 ) );
     412           0 :                     rObj.SetAngle( 0 );
     413             :                 }
     414           0 :                 mpEscherEx->OpenContainer( ESCHER_SpContainer );
     415           0 :                 ADD_SHAPE( ESCHER_ShpInst_NotPrimitive, 0xa00 );        // Flags: Connector | HasSpt
     416           0 :                 ::com::sun::star::awt::Rectangle aNewRect;
     417           0 :                 switch ( ePolyKind )
     418             :                 {
     419             :                     case POLY_PIE :
     420             :                     case POLY_CHORD :
     421             :                     {
     422           0 :                         aPropOpt.CreatePolygonProperties( rObj.mXPropSet, ESCHER_CREATEPOLYGON_POLYPOLYGON, false, aNewRect, &aPolygon );
     423           0 :                         aPropOpt.CreateFillProperties( rObj.mXPropSet, true  );
     424             :                     }
     425           0 :                     break;
     426             : 
     427             :                     case POLY_ARC :
     428             :                     {
     429           0 :                         aPropOpt.CreatePolygonProperties( rObj.mXPropSet, ESCHER_CREATEPOLYGON_POLYLINE, false, aNewRect, &aPolygon );
     430           0 :                         aPropOpt.CreateLineProperties( rObj.mXPropSet, false );
     431             :                     }
     432           0 :                     break;
     433             :                 }
     434           0 :                 rObj.SetRect( Rectangle( ImplMapPoint( Point( aNewRect.X, aNewRect.Y ) ),
     435           0 :                                             ImplMapSize( Size( aNewRect.Width, aNewRect.Height ) ) ) );
     436             :             }
     437           0 :             if ( rObj.ImplGetText() )
     438             :                 aPropOpt.CreateTextProperties( rObj.mXPropSet,
     439           0 :                     mpEscherEx->QueryTextID( rObj.GetShapeRef(),
     440           0 :                         rObj.GetShapeId() ), false, false );
     441             : 
     442             :         }
     443         472 :         else if ( rObj.GetType() == "drawing.Control" )
     444             :         {
     445           0 :             break;
     446             :         }
     447         472 :         else if ( rObj.GetType() == "drawing.Connector" )
     448             :         {
     449             :             sal_uInt16 nSpType, nSpFlags;
     450          27 :             ::com::sun::star::awt::Rectangle aNewRect;
     451          54 :             if ( ! aPropOpt.CreateConnectorProperties( rObj.GetShapeRef(),
     452          27 :                             rSolverContainer, aNewRect, nSpType, nSpFlags ) )
     453           0 :                 break;
     454          54 :             rObj.SetRect( Rectangle( ImplMapPoint( Point( aNewRect.X, aNewRect.Y ) ),
     455          81 :                                         ImplMapSize( Size( aNewRect.Width, aNewRect.Height ) ) ) );
     456             : 
     457          27 :             mpEscherEx->OpenContainer( ESCHER_SpContainer );
     458          27 :             ADD_SHAPE( nSpType, nSpFlags );
     459             :         }
     460         445 :         else if ( rObj.GetType() == "drawing.Measure" )
     461             :         {
     462           0 :             break;
     463             :         }
     464         445 :         else if ( rObj.GetType() == "drawing.Line" )
     465             :         {
     466          21 :             ::com::sun::star::awt::Rectangle aNewRect;
     467          21 :             aPropOpt.CreatePolygonProperties( rObj.mXPropSet, ESCHER_CREATEPOLYGON_LINE, false, aNewRect, NULL );
     468             :             //i27942: Poly/Lines/Bezier do not support text.
     469             : 
     470          21 :             mpEscherEx->OpenContainer( ESCHER_SpContainer );
     471          21 :             sal_uInt32 nFlags = 0xa00;      // Flags: Connector | HasSpt
     472          21 :             if( aNewRect.Height < 0 )
     473           5 :                 nFlags |= 0x80;             // Flags: VertMirror
     474          21 :             if( aNewRect.Width < 0 )
     475           0 :                 nFlags |= 0x40;             // Flags: HorzMirror
     476             : 
     477          21 :             ADD_SHAPE( ESCHER_ShpInst_Line, nFlags );
     478          21 :             aPropOpt.AddOpt( ESCHER_Prop_shapePath, ESCHER_ShapeComplex );
     479          21 :             aPropOpt.CreateLineProperties( rObj.mXPropSet, false );
     480          21 :             rObj.SetAngle( 0 );
     481             :         }
     482         424 :         else if ( rObj.GetType() == "drawing.PolyPolygon" )
     483             :         {
     484         129 :             if( rObj.ImplHasText() )
     485             :             {
     486           0 :                 nGrpShapeID = ImplEnterAdditionalTextGroup( rObj.GetShapeRef(), &rObj.GetRect() );
     487           0 :                 bAdditionalText = true;
     488             :             }
     489         129 :             mpEscherEx->OpenContainer( ESCHER_SpContainer );
     490         129 :             ADD_SHAPE( ESCHER_ShpInst_NotPrimitive, 0xa00 );        // Flags: Connector | HasSpt
     491         129 :             ::com::sun::star::awt::Rectangle aNewRect;
     492         129 :             aPropOpt.CreatePolygonProperties( rObj.mXPropSet, ESCHER_CREATEPOLYGON_POLYPOLYGON, false, aNewRect, NULL );
     493         129 :             aPropOpt.CreateFillProperties( rObj.mXPropSet, true );
     494         129 :             rObj.SetAngle( 0 );
     495             :         }
     496         295 :         else if ( rObj.GetType() == "drawing.PolyLine" )
     497             :         {
     498             :             //i27942: Poly/Lines/Bezier do not support text.
     499             : 
     500           6 :             mpEscherEx->OpenContainer( ESCHER_SpContainer );
     501           6 :             ADD_SHAPE( ESCHER_ShpInst_NotPrimitive, 0xa00 );        // Flags: Connector | HasSpt
     502           6 :             ::com::sun::star::awt::Rectangle aNewRect;
     503           6 :             aPropOpt.CreatePolygonProperties( rObj.mXPropSet, ESCHER_CREATEPOLYGON_POLYLINE, false, aNewRect, NULL );
     504           6 :             aPropOpt.CreateLineProperties( rObj.mXPropSet, false );
     505           6 :             rObj.SetAngle( 0 );
     506             :         }
     507         289 :         else if ( rObj.GetType() == "drawing.OpenBezier" )
     508             :         {
     509             :             //i27942: Poly/Lines/Bezier do not support text.
     510             : 
     511           1 :             mpEscherEx->OpenContainer( ESCHER_SpContainer );
     512           1 :             ADD_SHAPE( ESCHER_ShpInst_NotPrimitive, 0xa00 );        // Flags: Connector | HasSpt
     513           1 :             ::com::sun::star::awt::Rectangle aNewRect;
     514           1 :             aPropOpt.CreatePolygonProperties( rObj.mXPropSet, ESCHER_CREATEPOLYGON_POLYLINE, true, aNewRect, NULL );
     515           1 :             aPropOpt.CreateLineProperties( rObj.mXPropSet, false );
     516           1 :             rObj.SetAngle( 0 );
     517             :         }
     518         288 :         else if ( rObj.GetType() == "drawing.ClosedBezier" )
     519             :         {
     520          94 :             if ( rObj.ImplHasText() )
     521             :             {
     522           0 :                 nGrpShapeID = ImplEnterAdditionalTextGroup( rObj.GetShapeRef(), &rObj.GetRect() );
     523           0 :                 bAdditionalText = true;
     524             :             }
     525          94 :             mpEscherEx->OpenContainer( ESCHER_SpContainer );
     526          94 :             ADD_SHAPE( ESCHER_ShpInst_NotPrimitive, 0xa00 );        // Flags: Connector | HasSpt
     527          94 :             ::com::sun::star::awt::Rectangle aNewRect;
     528          94 :             aPropOpt.CreatePolygonProperties( rObj.mXPropSet, ESCHER_CREATEPOLYGON_POLYPOLYGON, true, aNewRect, NULL );
     529          94 :             aPropOpt.CreateFillProperties( rObj.mXPropSet, true );
     530          94 :             rObj.SetAngle( 0 );
     531             :         }
     532         194 :         else if ( rObj.GetType() == "drawing.GraphicObject" )
     533             :         {
     534          75 :             mpEscherEx->OpenContainer( ESCHER_SpContainer );
     535             : 
     536             :             // a GraphicObject can also be a ClickMe element
     537          75 :             if( rObj.IsEmptyPresObj() && ( ePageType == NORMAL ) )
     538             :             {
     539           0 :                 ADD_SHAPE( ESCHER_ShpInst_Rectangle, 0x220 );               // Flags: HaveAnchor | HaveMaster
     540           0 :                 sal_uInt32 nTxtBxId = mpEscherEx->QueryTextID( rObj.GetShapeRef(),
     541           0 :                                                         rObj.GetShapeId() );
     542           0 :                 aPropOpt.AddOpt( ESCHER_Prop_lTxid, nTxtBxId );
     543           0 :                 aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x10001 );
     544           0 :                 aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x10001 );
     545           0 :                 aPropOpt.AddOpt( ESCHER_Prop_hspMaster, mnShapeMasterBody );
     546             :             }
     547             :             else
     548             :             {
     549          75 :                 if( rObj.ImplGetText() )
     550             :                 {
     551             :                     /* SJ #i34951#: because M. documents are not allowing GraphicObjects containing text, we
     552             :                        have to create a simple Rectangle with fill bitmap instead (while not allowing BitmapMode_Repeat).
     553             :                     */
     554           0 :                     ADD_SHAPE( ESCHER_ShpInst_Rectangle, 0xa00 );           // Flags: Connector | HasSpt
     555           0 :                     if ( aPropOpt.CreateGraphicProperties( rObj.mXPropSet, "GraphicURL", true, true, false ) )
     556             :                     {
     557           0 :                         aPropOpt.AddOpt( ESCHER_Prop_WrapText, ESCHER_WrapNone );
     558           0 :                         aPropOpt.AddOpt( ESCHER_Prop_AnchorText, ESCHER_AnchorMiddle );
     559           0 :                         aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x140014 );
     560           0 :                         aPropOpt.AddOpt( ESCHER_Prop_fillBackColor, 0x8000000 );
     561           0 :                         aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x80000 );
     562           0 :                         if ( rObj.ImplGetText() )
     563             :                             aPropOpt.CreateTextProperties( rObj.mXPropSet,
     564           0 :                                 mpEscherEx->QueryTextID( rObj.GetShapeRef(),
     565           0 :                                     rObj.GetShapeId() ), false, false );
     566             :                     }
     567             :                 }
     568             :                 else
     569             :                 {
     570          75 :                     ADD_SHAPE( ESCHER_ShpInst_PictureFrame, 0xa00 );
     571          75 :                     if ( aPropOpt.CreateGraphicProperties( rObj.mXPropSet, "GraphicURL", false, true, true, bOOxmlExport ) )
     572          69 :                         aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x800080 );
     573             :                 }
     574             :             }
     575             :         }
     576         119 :         else if ( rObj.GetType() == "drawing.Text" )
     577             :         {
     578         113 :             SHAPE_TEXT( true );
     579             :         }
     580           6 :         else if ( rObj.GetType() == "drawing.Page" )
     581             :         {
     582           0 :             mpEscherEx->OpenContainer( ESCHER_SpContainer );
     583           0 :             ADD_SHAPE( ESCHER_ShpInst_Rectangle, 0xa00 );
     584           0 :             aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x40004 );
     585           0 :             aPropOpt.AddOpt( ESCHER_Prop_fFillOK, 0x100001 );
     586           0 :             aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x110011 );
     587           0 :             aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x90008 );
     588           0 :             aPropOpt.AddOpt( ESCHER_Prop_fshadowObscured, 0x10001 );
     589             :         }
     590           6 :         else if ( rObj.GetType() == "drawing.Frame" )
     591             :         {
     592           0 :             break;
     593             :         }
     594           6 :         else if ( rObj.GetType() == "drawing.OLE2" )
     595             :         {
     596           0 :             mpEscherEx->OpenContainer( ESCHER_SpContainer );
     597           0 :             if( rObj.IsEmptyPresObj() && ( ePageType == NORMAL ) )
     598             :             {
     599           0 :                 ADD_SHAPE( ESCHER_ShpInst_Rectangle, 0x220 );               // Flags: HaveAnchor | HaveMaster
     600           0 :                 sal_uInt32 nTxtBxId = mpEscherEx->QueryTextID( rObj.GetShapeRef(),
     601           0 :                                                         rObj.GetShapeId() );
     602           0 :                 aPropOpt.AddOpt( ESCHER_Prop_lTxid, nTxtBxId );
     603           0 :                 aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x10001 );
     604           0 :                 aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x10001 );
     605           0 :                 aPropOpt.AddOpt( ESCHER_Prop_hspMaster, mnShapeMasterBody );
     606             :             }
     607             :             else
     608             :             {
     609             :                 //2do: could be made an option in HostAppData whether OLE object should be written or not
     610           0 :                 bool bAppOLE = true;
     611           0 :                 ADD_SHAPE( ESCHER_ShpInst_PictureFrame,
     612             :                     0xa00 | (bAppOLE ? SHAPEFLAG_OLESHAPE : 0) );
     613           0 :                 if ( aPropOpt.CreateOLEGraphicProperties( rObj.GetShapeRef() ) )
     614             :                 {
     615           0 :                     if ( bAppOLE )
     616             :                     {   // snooped from Xcl hex dump, nobody knows the trouble I have seen
     617           0 :                         aPropOpt.AddOpt( ESCHER_Prop_FitTextToShape,    0x00080008 );
     618           0 :                         aPropOpt.AddOpt( ESCHER_Prop_pictureId,     0x00000001 );
     619           0 :                         aPropOpt.AddOpt( ESCHER_Prop_fillColor,     0x08000041 );
     620           0 :                         aPropOpt.AddOpt( ESCHER_Prop_fillBackColor, 0x08000041 );
     621           0 :                         aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest,    0x00110010 );
     622           0 :                         aPropOpt.AddOpt( ESCHER_Prop_lineColor,     0x08000040 );
     623           0 :                         aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash,0x00080008 );
     624           0 :                         aPropOpt.AddOpt( ESCHER_Prop_fPrint,            0x00080000 );
     625             :                     }
     626           0 :                     aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x800080 );
     627             :                 }
     628             :             }
     629             :         }
     630           6 :         else if( '3' == rObj.GetType()[8] &&
     631           0 :                  'D' == rObj.GetType()[9] )   // drawing.3D
     632             :         {
     633             :             // SceneObject, CubeObject, SphereObject, LatheObject, ExtrudeObject, PolygonObject
     634           0 :             if ( !rObj.ImplGetPropertyValue( OUString( "Bitmap" ) ) )
     635           0 :                 break;
     636             : 
     637           0 :             mpEscherEx->OpenContainer( ESCHER_SpContainer );
     638           0 :             ADD_SHAPE( ESCHER_ShpInst_PictureFrame, 0xa00 );
     639             : 
     640           0 :                 if ( aPropOpt.CreateGraphicProperties( rObj.mXPropSet, "Bitmap", false ) )
     641           0 :                 aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x800080 );
     642             :         }
     643           6 :         else if ( rObj.GetType() == "drawing.Caption" )
     644             :         {
     645           0 :             rObj.SetAngle( 0 );
     646           0 :             mpEscherEx->OpenContainer( ESCHER_SpContainer );
     647           0 :             ADD_SHAPE( ESCHER_ShpInst_TextBox, 0xa00 );
     648           0 :             if ( aPropOpt.CreateGraphicProperties( rObj.mXPropSet, "MetaFile", false ) )
     649           0 :                 aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x800080 );
     650             :         }
     651           6 :         else if ( rObj.GetType() == "drawing.dontknow" )
     652             :         {
     653           6 :             rObj.SetAngle( 0 );
     654           6 :             mpEscherEx->OpenContainer( ESCHER_SpContainer );
     655           6 :             ADD_SHAPE( ESCHER_ShpInst_PictureFrame, 0xa00 );
     656           6 :             if ( aPropOpt.CreateGraphicProperties( rObj.mXPropSet, "MetaFile", false ) )
     657           6 :                 aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x800080 );
     658             :         }
     659             :         else
     660             :         {
     661           0 :             break;
     662             :         }
     663         942 :         aPropOpt.CreateShadowProperties( rObj.mXPropSet );
     664             : 
     665        3774 :         if( USHRT_MAX != mpEscherEx->GetHellLayerId() &&
     666        2844 :             rObj.ImplGetPropertyValue( OUString( "LayerID" ) ) &&
     667           6 :             (*static_cast<sal_uInt16 const *>(rObj.GetUsrAny().getValue()) ) == mpEscherEx->GetHellLayerId() )
     668             :         {
     669           0 :             aPropOpt.AddOpt( ESCHER_Prop_fPrint, 0x200020 );
     670             :         }
     671             : 
     672             :         {
     673         942 :             Rectangle aRect( rObj.GetRect() );
     674         942 :             aRect.Justify();
     675         942 :             rObj.SetRect( aRect );
     676             :         }
     677             : 
     678         942 :         if( rObj.GetAngle() )
     679          36 :             ImplFlipBoundingBox( rObj, aPropOpt );
     680             : 
     681         942 :         aPropOpt.CreateShapeProperties( rObj.GetShapeRef() );
     682         942 :         const SdrObject* sdrObj = rObj.GetSdrObject();
     683         942 :         mpEscherEx->AddSdrObjectVMLObject(*sdrObj );
     684         942 :         mpEscherEx->Commit( aPropOpt, rObj.GetRect());
     685         942 :         if( mpEscherEx->GetGroupLevel() > 1 )
     686         467 :             mpEscherEx->AddChildAnchor( rObj.GetRect() );
     687             : 
     688         942 :         if ( mpHostAppData )
     689             :         {   //! with AdditionalText the App has to control whether these are written or not
     690          35 :             mpHostAppData->WriteClientAnchor( *mpEscherEx, rObj.GetRect() );
     691          35 :             mpHostAppData->WriteClientData( *mpEscherEx );
     692          35 :             if ( !bDontWriteText )
     693          35 :                 mpHostAppData->WriteClientTextbox( *mpEscherEx );
     694             :         }
     695         942 :         mpEscherEx->CloseContainer();       // ESCHER_SpContainer
     696             : 
     697         942 :         if( bAdditionalText )
     698             :         {
     699           0 :             mpEscherEx->EndShape( nShapeType, nShapeID );
     700           0 :             ImplWriteAdditionalText( rObj, aTextRefPoint );
     701         942 :         }
     702             : 
     703             :     } while ( false );
     704             : 
     705        1024 :     if ( bAdditionalText )
     706           0 :         mpEscherEx->EndShape( ESCHER_ShpInst_Min, nGrpShapeID );
     707             :     else
     708        1024 :         mpEscherEx->EndShape( nShapeType, nShapeID );
     709        1024 :     return nShapeID;
     710             : }
     711             : 
     712           0 : void ImplEESdrWriter::ImplWriteAdditionalText( ImplEESdrObject& rObj,
     713             :                                                 const Point& rTextRefPoint )
     714             : {
     715           0 :     sal_uInt32 nShapeID = 0;
     716           0 :     sal_uInt16 nShapeType = 0;
     717             :     do
     718             :     {
     719           0 :         mpHostAppData = mpEscherEx->StartShape( rObj.GetShapeRef(), (mpEscherEx->GetGroupLevel() > 1) ? &rObj.GetRect() : 0 );
     720           0 :         if ( mpHostAppData && mpHostAppData->DontWriteShape() )
     721           0 :             break;
     722             : 
     723           0 :         const ::com::sun::star::awt::Size   aSize100thmm( rObj.GetShapeRef()->getSize() );
     724           0 :         const ::com::sun::star::awt::Point  aPoint100thmm( rObj.GetShapeRef()->getPosition() );
     725           0 :         Rectangle   aRect100thmm( Point( aPoint100thmm.X, aPoint100thmm.Y ), Size( aSize100thmm.Width, aSize100thmm.Height ) );
     726           0 :         if ( !mpPicStrm )
     727           0 :             mpPicStrm = mpEscherEx->QueryPictureStream();
     728           0 :         EscherPropertyContainer aPropOpt( mpEscherEx->GetGraphicProvider(), mpPicStrm, aRect100thmm );
     729           0 :         rObj.SetAngle( rObj.ImplGetInt32PropertyValue( OUString( "RotateAngle" )));
     730           0 :         sal_Int32 nAngle = rObj.GetAngle();
     731           0 :         if( rObj.GetType() == "drawing.Line" )
     732             :         {
     733             : //2do: this does not work right
     734           0 :             double fDist = hypot( rObj.GetRect().GetWidth(),
     735           0 :                                     rObj.GetRect().GetHeight() );
     736             :             rObj.SetRect( Rectangle( rTextRefPoint,
     737           0 :                             Point( (sal_Int32)( rTextRefPoint.X() + fDist ), rTextRefPoint.Y() - 1 ) ) );
     738             : 
     739           0 :             mpEscherEx->OpenContainer( ESCHER_SpContainer );
     740           0 :             mpEscherEx->AddShape( ESCHER_ShpInst_TextBox, 0xa00 );
     741           0 :             if ( rObj.ImplGetText() )
     742             :                 aPropOpt.CreateTextProperties( rObj.mXPropSet,
     743           0 :                     mpEscherEx->QueryTextID( rObj.GetShapeRef(),
     744           0 :                         rObj.GetShapeId() ) );
     745             : 
     746           0 :             aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x90000 );
     747           0 :             aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x100000 );
     748           0 :             aPropOpt.AddOpt( ESCHER_Prop_FitTextToShape, 0x60006 );     // Size Shape To Fit Text
     749           0 :             if ( nAngle < 0 )
     750           0 :                 nAngle = ( 36000 + nAngle ) % 36000;
     751           0 :             if ( nAngle )
     752           0 :                 ImplFlipBoundingBox( rObj, aPropOpt );
     753             :         }
     754             :         else
     755             :         {
     756           0 :             mpEscherEx->OpenContainer( ESCHER_SpContainer );
     757           0 :             nShapeID = mpEscherEx->GenerateShapeId();
     758           0 :             mpEscherEx->AddShape( nShapeType = ESCHER_ShpInst_TextBox, 0xa00, nShapeID );
     759           0 :             if ( rObj.ImplGetText() )
     760             :                 aPropOpt.CreateTextProperties( rObj.mXPropSet,
     761           0 :                     mpEscherEx->QueryTextID( rObj.GetShapeRef(),
     762           0 :                         rObj.GetShapeId() ) );
     763           0 :             aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x90000 );
     764           0 :             aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x100000 );
     765             : 
     766           0 :             if( nAngle < 0 )
     767           0 :                 nAngle = ( 36000 + nAngle ) % 36000;
     768             :             else
     769           0 :                 nAngle = ( 36000 - ( nAngle % 36000 ) );
     770             : 
     771           0 :             nAngle *= 655;
     772           0 :             nAngle += 0x8000;
     773           0 :             nAngle &=~0xffff;   // nAngle round to full degrees
     774           0 :             aPropOpt.AddOpt( ESCHER_Prop_Rotation, nAngle );
     775             :             mpEscherEx->SetGroupSnapRect( mpEscherEx->GetGroupLevel(),
     776           0 :                                             rObj.GetRect() );
     777             :             mpEscherEx->SetGroupLogicRect( mpEscherEx->GetGroupLevel(),
     778           0 :                                             rObj.GetRect() );
     779             :         }
     780           0 :         rObj.SetAngle( nAngle );
     781           0 :         aPropOpt.CreateShapeProperties( rObj.GetShapeRef() );
     782           0 :         const SdrObject* sdrObj = rObj.GetSdrObject();
     783           0 :         mpEscherEx->AddSdrObjectVMLObject(*sdrObj );
     784           0 :         mpEscherEx->Commit( aPropOpt, rObj.GetRect());
     785             : 
     786             :         // write the childanchor
     787           0 :         mpEscherEx->AddChildAnchor( rObj.GetRect() );
     788             : 
     789             : #if defined EES_WRITE_EPP
     790             :         // ClientAnchor
     791             :         mpEscherEx->AddClientAnchor( maRect );
     792             :         // ClientTextbox
     793             :         mpEscherEx->OpenContainer( ESCHER_ClientTextbox );
     794             :         mpEscherEx->AddAtom( 4, EPP_TextHeaderAtom );
     795             :         *mpStrm << (sal_uInt32)EPP_TEXTTYPE_Other;                              // Text in a Shape
     796             :         ImplWriteTextStyleAtom();
     797             :         mpEscherEx->CloseContainer();   // ESCHER_ClientTextBox
     798             : #else // !EES_WRITE_EPP
     799           0 :         if ( mpHostAppData )
     800             :         {   //! the App has to control whether these are written or not
     801           0 :             mpHostAppData->WriteClientAnchor( *mpEscherEx, rObj.GetRect() );
     802           0 :             mpHostAppData->WriteClientData( *mpEscherEx );
     803           0 :             mpHostAppData->WriteClientTextbox( *mpEscherEx );
     804             :         }
     805             : #endif // EES_WRITE_EPP
     806           0 :         mpEscherEx->CloseContainer();   // ESCHER_SpContainer
     807             :     } while ( false );
     808           0 :     mpEscherEx->LeaveGroup();
     809           0 :     mpEscherEx->EndShape( nShapeType, nShapeID );
     810           0 : }
     811             : 
     812             : 
     813           0 : sal_uInt32 ImplEESdrWriter::ImplEnterAdditionalTextGroup( const Reference< XShape >& rShape,
     814             :             const Rectangle* pBoundRect )
     815             : {
     816           0 :     mpHostAppData = mpEscherEx->EnterAdditionalTextGroup();
     817           0 :     sal_uInt32 nGrpId = mpEscherEx->EnterGroup( pBoundRect );
     818           0 :     mpHostAppData = mpEscherEx->StartShape( rShape, pBoundRect );
     819           0 :     return nGrpId;
     820             : }
     821             : 
     822             : 
     823         397 : bool ImplEESdrWriter::ImplInitPageValues()
     824             : {
     825         397 :     mnIndices = 0;
     826         397 :     mnOutlinerCount = 0;                // die outline objects must be in accordance with the layout.
     827         397 :     mnEffectCount = 0;
     828         397 :     mbIsTitlePossible = true;       // With more than one title PowerPoint will fail.
     829             : 
     830         397 :     return true;
     831             : }
     832             : 
     833         127 : void ImplEESdrWriter::ImplWritePage(
     834             :             EscherSolverContainer& rSolverContainer,
     835             :             ImplEESdrPageType ePageType, bool /* bBackGround */ )
     836             : {
     837         127 :     ImplInitPageValues();
     838             : 
     839         127 :     sal_uInt32 nLastPer = 0, nShapes = mXShapes->getCount();
     840         185 :     for( sal_uInt32 n = 0; n < nShapes; ++n )
     841             :     {
     842          58 :         sal_uInt32 nPer = ( 5 * n ) / nShapes;
     843          58 :         if( nPer != nLastPer )
     844             :         {
     845           6 :             nLastPer = nPer;
     846           6 :             sal_uInt32 nValue = mnPagesWritten * 5 + nPer;
     847           6 :             if( nValue > mnStatMaxValue )
     848           6 :                 nValue = mnStatMaxValue;
     849           6 :             if( mbStatusIndicator )
     850           0 :                 mXStatusIndicator->setValue( nValue );
     851             :         }
     852             : 
     853             :         ImplEESdrObject aObj( *this, *static_cast<Reference< XShape > const *>(
     854          58 :                                     mXShapes->getByIndex( n ).getValue()) );
     855          58 :         if( aObj.IsValid() )
     856             :         {
     857          58 :             ImplWriteShape( aObj, rSolverContainer, ePageType );
     858             :         }
     859          58 :     }
     860         127 :     mnPagesWritten++;
     861         127 : }
     862             : 
     863         661 : ImplEscherExSdr::ImplEscherExSdr( EscherEx& rEx )
     864             :         :
     865             :         ImplEESdrWriter( rEx ),
     866             :         mpSdrPage( NULL ),
     867         661 :         mpSolverContainer( NULL )
     868             : {
     869         661 : }
     870             : 
     871             : 
     872        1983 : ImplEscherExSdr::~ImplEscherExSdr()
     873             : {
     874             :     DBG_ASSERT( !mpSolverContainer, "ImplEscherExSdr::~ImplEscherExSdr: unwritten SolverContainer" );
     875         661 :     delete mpSolverContainer;
     876        1322 : }
     877             : 
     878             : 
     879         499 : bool ImplEscherExSdr::ImplInitPage( const SdrPage& rPage )
     880             : {
     881             :     do
     882             :     {
     883             :         SvxDrawPage* pSvxDrawPage;
     884         499 :         if ( mpSdrPage != &rPage || !mXDrawPage.is() )
     885             :         {
     886             :             // eventually write SolverContainer of current page, deletes the Solver
     887         270 :             ImplFlushSolverContainer();
     888             : 
     889         270 :             mpSdrPage = NULL;
     890         270 :             mXDrawPage = pSvxDrawPage = new SvxFmDrawPage( const_cast<SdrPage*>(&rPage) );
     891         270 :             mXShapes = Reference< XShapes >::query( mXDrawPage );
     892         270 :             if ( !mXShapes.is() )
     893           0 :                 break;
     894         270 :             if ( !ImplInitPageValues() )    // ImplEESdrWriter
     895           0 :                 break;
     896         270 :             mpSdrPage = &rPage;
     897             : 
     898         270 :             mpSolverContainer = new EscherSolverContainer;
     899             :         }
     900             :         else
     901         229 :             pSvxDrawPage = SvxDrawPage::getImplementation(mXDrawPage);
     902             : 
     903         499 :         return pSvxDrawPage != 0;
     904             :     } while ( false );
     905             : 
     906           0 :     return false;
     907             : }
     908             : 
     909           0 : bool ImplEscherExSdr::ImplInitUnoShapes( const Reference< XShapes >& rxShapes )
     910             : {
     911             :     // eventually write SolverContainer of current page, deletes the Solver
     912           0 :     ImplFlushSolverContainer();
     913             : 
     914           0 :     if( !rxShapes.is() )
     915           0 :         return false;
     916             : 
     917           0 :     mpSdrPage = 0;
     918           0 :     mXDrawPage.clear();
     919           0 :     mXShapes = rxShapes;
     920             : 
     921           0 :     if( !ImplInitPageValues() )    // ImplEESdrWriter
     922           0 :         return false;
     923             : 
     924           0 :     mpSolverContainer = new EscherSolverContainer;
     925           0 :     return true;
     926             : }
     927             : 
     928         135 : void ImplEscherExSdr::ImplExitPage()
     929             : {
     930             :     // close all groups before the solver container is written
     931         405 :     while( mpEscherEx->GetGroupLevel() )
     932         135 :         mpEscherEx->LeaveGroup();
     933             : 
     934         135 :     ImplFlushSolverContainer();
     935         135 :     mpSdrPage = NULL;   // reset page for next init
     936         135 : }
     937             : 
     938             : 
     939         405 : void ImplEscherExSdr::ImplFlushSolverContainer()
     940             : {
     941         405 :     if ( mpSolverContainer )
     942             :     {
     943         128 :         mpSolverContainer->WriteSolver( mpEscherEx->GetStream() );
     944         128 :         delete mpSolverContainer;
     945         128 :         mpSolverContainer = NULL;
     946             :     }
     947         405 : }
     948             : 
     949         127 : void ImplEscherExSdr::ImplWriteCurrentPage()
     950             : {
     951             :     assert(mpSolverContainer && "ImplEscherExSdr::ImplWriteCurrentPage: no SolverContainer");
     952         127 :     ImplWritePage( *mpSolverContainer, NORMAL );
     953         127 :     ImplExitPage();
     954         127 : }
     955             : 
     956         372 : sal_uInt32 ImplEscherExSdr::ImplWriteTheShape( ImplEESdrObject& rObj , bool ooxmlExport )
     957             : {
     958             :     assert(mpSolverContainer && "ImplEscherExSdr::ImplWriteShape: no SolverContainer");
     959         372 :     return ImplWriteShape( rObj, *mpSolverContainer, NORMAL, ooxmlExport );
     960             : }
     961             : 
     962         127 : void EscherEx::AddSdrPage( const SdrPage& rPage )
     963             : {
     964         127 :     if ( mpImplEscherExSdr->ImplInitPage( rPage ) )
     965         127 :         mpImplEscherExSdr->ImplWriteCurrentPage();
     966         127 : }
     967             : 
     968           0 : void EscherEx::AddUnoShapes( const Reference< XShapes >& rxShapes )
     969             : {
     970           0 :     if ( mpImplEscherExSdr->ImplInitUnoShapes( rxShapes ) )
     971           0 :         mpImplEscherExSdr->ImplWriteCurrentPage();
     972           0 : }
     973             : 
     974         372 : sal_uInt32 EscherEx::AddSdrObject( const SdrObject& rObj, bool ooxmlExport )
     975             : {
     976         372 :     ImplEESdrObject aObj( *mpImplEscherExSdr, rObj, mbOOXML );
     977         372 :     if( aObj.IsValid() )
     978         372 :         return mpImplEscherExSdr->ImplWriteTheShape( aObj, ooxmlExport );
     979           0 :     return 0;
     980             : }
     981             : 
     982             : 
     983           8 : void EscherEx::EndSdrObjectPage()
     984             : {
     985           8 :     mpImplEscherExSdr->ImplExitPage();
     986           8 : }
     987             : 
     988         960 : EscherExHostAppData* EscherEx::StartShape( const Reference< XShape >& /* rShape */, const Rectangle* /*pChildAnchor*/ )
     989             : {
     990         960 :     return NULL;
     991             : }
     992             : 
     993         966 : void EscherEx::EndShape( sal_uInt16 /* nShapeType */, sal_uInt32 /* nShapeID */ )
     994             : {
     995         966 : }
     996             : 
     997         258 : sal_uInt32 EscherEx::QueryTextID( const Reference< XShape >&, sal_uInt32 )
     998             : {
     999         258 :     return 0;
    1000             : }
    1001             : 
    1002             : // add an dummy rectangle shape into the escher stream
    1003           0 : sal_uInt32 EscherEx::AddDummyShape()
    1004             : {
    1005           0 :     OpenContainer( ESCHER_SpContainer );
    1006           0 :     sal_uInt32 nShapeID = GenerateShapeId();
    1007           0 :     AddShape( ESCHER_ShpInst_Rectangle, 0xa00, nShapeID );
    1008           0 :     CloseContainer();
    1009             : 
    1010           0 :     return nShapeID;
    1011             : }
    1012             : 
    1013             : // static
    1014        1959 : const SdrObject* EscherEx::GetSdrObject( const Reference< XShape >& rShape )
    1015             : {
    1016        1959 :     const SdrObject* pRet = 0;
    1017        1959 :     const SvxShape* pSvxShape = SvxShape::getImplementation( rShape );
    1018             :     DBG_ASSERT( pSvxShape, "EscherEx::GetSdrObject: no SvxShape" );
    1019        1959 :     if( pSvxShape )
    1020             :     {
    1021        1959 :         pRet = pSvxShape->GetSdrObject();
    1022             :         DBG_ASSERT( pRet, "EscherEx::GetSdrObject: no SdrObj" );
    1023             :     }
    1024        1959 :     return pRet;
    1025             : }
    1026             : 
    1027             : 
    1028         372 : ImplEESdrObject::ImplEESdrObject( ImplEscherExSdr& rEx,
    1029             :                                     const SdrObject& rObj, bool bOOXML ) :
    1030             :     mnShapeId( 0 ),
    1031             :     mnTextSize( 0 ),
    1032             :     mnAngle( 0 ),
    1033             :     mbValid( false ),
    1034             :     mbPresObj( false ),
    1035             :     mbEmptyPresObj( false ),
    1036         372 :     mbOOXML(bOOXML)
    1037             : {
    1038         372 :     SdrPage* pPage = rObj.GetPage();
    1039             :     DBG_ASSERT( pPage, "ImplEESdrObject::ImplEESdrObject: no SdrPage" );
    1040         372 :     if( pPage && rEx.ImplInitPage( *pPage ) )
    1041             :     {
    1042             :         // why not declare a const parameter if the object will
    1043             :         // not be modified?
    1044         372 :         mXShape = uno::Reference< drawing::XShape >::query( const_cast<SdrObject*>(&rObj)->getUnoShape() );
    1045         372 :         Init( rEx );
    1046             :     }
    1047         372 : }
    1048             : 
    1049         652 : ImplEESdrObject::ImplEESdrObject( ImplEESdrWriter& rEx,
    1050             :                                     const Reference< XShape >& rShape ) :
    1051             :     mXShape( rShape ),
    1052             :     mnShapeId( 0 ),
    1053             :     mnTextSize( 0 ),
    1054             :     mnAngle( 0 ),
    1055             :     mbValid( false ),
    1056             :     mbPresObj( false ),
    1057             :     mbEmptyPresObj( false ),
    1058         652 :     mbOOXML(false)
    1059             : {
    1060         652 :     Init( rEx );
    1061         652 : }
    1062             : 
    1063             : 
    1064        1024 : ImplEESdrObject::~ImplEESdrObject()
    1065             : {
    1066        1024 : }
    1067             : 
    1068         741 : basegfx::B2DRange getUnrotatedGroupBoundRange(const Reference< XShape >& rxShape)
    1069             : {
    1070         741 :     basegfx::B2DRange aRetval;
    1071             : 
    1072             :     try
    1073             :     {
    1074         741 :         if(rxShape.is())
    1075             :         {
    1076         741 :             if(rxShape->getShapeType() == "com.sun.star.drawing.GroupShape")
    1077             :             {
    1078             :                 // it's a group shape, iterate over children
    1079          71 :                 const Reference< XIndexAccess > xXIndexAccess(rxShape, UNO_QUERY);
    1080             : 
    1081          71 :                 if(xXIndexAccess.is())
    1082             :                 {
    1083         759 :                     for(sal_uInt32 n(0), nCnt = xXIndexAccess->getCount(); n < nCnt; ++n)
    1084             :                     {
    1085         688 :                         const Reference< XShape > axShape(xXIndexAccess->getByIndex(n), UNO_QUERY);
    1086             : 
    1087         688 :                         if(axShape.is())
    1088             :                         {
    1089             :                             // we are calculating the bound for a group, correct rotation for sub-objects
    1090             :                             // to get the unrotated bounds for the group
    1091         688 :                             const basegfx::B2DRange aExtend(getUnrotatedGroupBoundRange(axShape));
    1092             : 
    1093         688 :                             aRetval.expand(aExtend);
    1094             :                         }
    1095         688 :                     }
    1096          71 :                 }
    1097             :             }
    1098             :             else
    1099             :             {
    1100             :                 // iT#s a xShape, get its transformation
    1101         670 :                 const Reference< XPropertySet > mXPropSet(rxShape, UNO_QUERY);
    1102             : 
    1103         670 :                 if(mXPropSet.is())
    1104             :                 {
    1105         670 :                     const Any aAny = mXPropSet->getPropertyValue(OUString("Transformation"));
    1106             : 
    1107         670 :                     if(aAny.hasValue())
    1108             :                     {
    1109         670 :                         HomogenMatrix3 aMatrix;
    1110             : 
    1111         670 :                         if(aAny >>= aMatrix)
    1112             :                         {
    1113         670 :                             basegfx::B2DHomMatrix aHomogenMatrix;
    1114             : 
    1115         670 :                             aHomogenMatrix.set(0, 0, aMatrix.Line1.Column1);
    1116         670 :                             aHomogenMatrix.set(0, 1, aMatrix.Line1.Column2);
    1117         670 :                             aHomogenMatrix.set(0, 2, aMatrix.Line1.Column3);
    1118         670 :                             aHomogenMatrix.set(1, 0, aMatrix.Line2.Column1);
    1119         670 :                             aHomogenMatrix.set(1, 1, aMatrix.Line2.Column2);
    1120         670 :                             aHomogenMatrix.set(1, 2, aMatrix.Line2.Column3);
    1121         670 :                             aHomogenMatrix.set(2, 0, aMatrix.Line3.Column1);
    1122         670 :                             aHomogenMatrix.set(2, 1, aMatrix.Line3.Column2);
    1123         670 :                             aHomogenMatrix.set(2, 2, aMatrix.Line3.Column3);
    1124             : 
    1125        1340 :                             basegfx::B2DVector aScale, aTranslate;
    1126             :                             double fRotate, fShearX;
    1127             : 
    1128             :                             // decopose transformation
    1129         670 :                             aHomogenMatrix.decompose(aScale, aTranslate, fRotate, fShearX);
    1130             : 
    1131             :                             // check if rotation needs to be corrected
    1132         670 :                             if(!basegfx::fTools::equalZero(fRotate))
    1133             :                             {
    1134             :                                 // to correct, keep in mind that ppt graphics are rotated around their center
    1135         184 :                                 const basegfx::B2DPoint aCenter(aHomogenMatrix * basegfx::B2DPoint(0.5, 0.5));
    1136             : 
    1137         184 :                                 aHomogenMatrix.translate(-aCenter.getX(), -aCenter.getY());
    1138         184 :                                 aHomogenMatrix.rotate(-fRotate);
    1139         184 :                                 aHomogenMatrix.translate(aCenter.getX(), aCenter.getY());
    1140             :                             }
    1141             : 
    1142             : 
    1143             :                             // check if shear needs to be corrected (always correct shear,
    1144             :                             // ppt does not know about it)
    1145         670 :                             if(!basegfx::fTools::equalZero(fShearX))
    1146             :                             {
    1147           0 :                                 const basegfx::B2DPoint aMinimum(aHomogenMatrix * basegfx::B2DPoint(0.0, 0.0));
    1148             : 
    1149           0 :                                 aHomogenMatrix.translate(-aMinimum.getX(), -aMinimum.getY());
    1150           0 :                                 aHomogenMatrix.shearX(-fShearX);
    1151           0 :                                 aHomogenMatrix.translate(aMinimum.getX(), aMinimum.getY());
    1152             :                             }
    1153             : 
    1154             :                             // create range. It's no longer rotated (or sheared), so use
    1155             :                             // minimum and maximum values
    1156         670 :                             aRetval.expand(aHomogenMatrix * basegfx::B2DPoint(0.0, 0.0));
    1157        1340 :                             aRetval.expand(aHomogenMatrix * basegfx::B2DPoint(1.0, 1.0));
    1158             :                         }
    1159         670 :                     }
    1160         670 :                 }
    1161             :             }
    1162             :         }
    1163             :     }
    1164           0 :     catch(::com::sun::star::uno::Exception&)
    1165             :     {
    1166             :     }
    1167             : 
    1168         741 :     return aRetval;
    1169             : }
    1170             : 
    1171        1024 : void ImplEESdrObject::Init( ImplEESdrWriter& rEx )
    1172             : {
    1173        1024 :     mXPropSet = Reference< XPropertySet >::query( mXShape );
    1174        1024 :     if( mXPropSet.is() )
    1175             :     {
    1176             :         // detect name first to make below test (is group) work
    1177        1024 :         mType = OUString( mXShape->getShapeType() );
    1178        1024 :         (void)mType.startsWith( "com.sun.star.", &mType );  // strip "com.sun.star."
    1179        1024 :         (void)mType.endsWith( "Shape", &mType );  // strip "Shape"
    1180             : 
    1181        1024 :         if(GetType() == "drawing.Group")
    1182             :         {
    1183             :             // if it's a group, the unrotated range is needed for that group
    1184          53 :             const basegfx::B2DRange aUnroatedRange(getUnrotatedGroupBoundRange(mXShape));
    1185          53 :             const Point aNewP(basegfx::fround(aUnroatedRange.getMinX()), basegfx::fround(aUnroatedRange.getMinY()));
    1186          53 :             const Size aNewS(basegfx::fround(aUnroatedRange.getWidth()), basegfx::fround(aUnroatedRange.getHeight()));
    1187             : 
    1188          53 :             SetRect(rEx.ImplMapPoint(aNewP), rEx.ImplMapSize(aNewS));
    1189             :         }
    1190             :         else
    1191             :         {
    1192             :             // if it's no group, use position and size directly, roated/sheared or not
    1193         971 :             const Point aOldP(mXShape->getPosition().X, mXShape->getPosition().Y);
    1194         971 :             const Size aOldS(mXShape->getSize().Width, mXShape->getSize().Height);
    1195             : 
    1196         971 :             SetRect(rEx.ImplMapPoint(aOldP), rEx.ImplMapSize(aOldS));
    1197             :         }
    1198             : 
    1199        1024 :         if( ImplGetPropertyValue( OUString("IsPresentationObject")) )
    1200           0 :             mbPresObj = ::cppu::any2bool( mAny );
    1201             : 
    1202        1024 :         if( mbPresObj && ImplGetPropertyValue( OUString("IsEmptyPresentationObject") ) )
    1203           0 :             mbEmptyPresObj = ::cppu::any2bool( mAny );
    1204             : 
    1205        1024 :         mbValid = true;
    1206             :     }
    1207        1024 : }
    1208             : 
    1209        2971 : bool ImplEESdrObject::ImplGetPropertyValue( const sal_Unicode* rString )
    1210             : {
    1211        2971 :     bool bRetValue = false;
    1212        2971 :     if( mbValid )
    1213             :     {
    1214             :         try
    1215             :         {
    1216        1947 :             mAny = mXPropSet->getPropertyValue( rString );
    1217        1947 :             if( mAny.hasValue() )
    1218        1947 :                 bRetValue = true;
    1219             :         }
    1220           0 :         catch( const ::com::sun::star::uno::Exception& )
    1221             :         {
    1222           0 :             bRetValue = false;
    1223             :         }
    1224             :     }
    1225        2971 :     return bRetValue;
    1226             : }
    1227             : 
    1228        1024 : void ImplEESdrObject::SetRect( const Point& rPos, const Size& rSz )
    1229             : {
    1230        1024 :     maRect = Rectangle( rPos, rSz );
    1231        1024 : }
    1232             : 
    1233        1937 : const SdrObject* ImplEESdrObject::GetSdrObject() const
    1234             : {
    1235        1937 :     return EscherEx::GetSdrObject( mXShape );
    1236             : }
    1237             : 
    1238             : //  loads and  converts text from shape, result is being saved in mnTextSize respeichert
    1239         658 : sal_uInt32 ImplEESdrObject::ImplGetText()
    1240             : {
    1241         658 :     Reference< XText > xXText( mXShape, UNO_QUERY );
    1242         658 :     mnTextSize = 0;
    1243         658 :     if( xXText.is() )
    1244         658 :         mnTextSize = xXText->getString().getLength();
    1245         658 :     return mnTextSize;
    1246             : }
    1247             : 
    1248         223 : bool ImplEESdrObject::ImplHasText() const
    1249             : {
    1250         223 :     Reference< XText > xXText( mXShape, UNO_QUERY );
    1251         223 :     return xXText.is() && !xXText->getString().isEmpty();
    1252             : }
    1253             : 
    1254             : 
    1255         594 : void ImplEESdrObject::SetOOXML(bool bOOXML)
    1256             : {
    1257         594 :     mbOOXML = bOOXML;
    1258         969 : }
    1259             : 
    1260             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11