LCOV - code coverage report
Current view: top level - libreoffice/sw/source/filter/ww8 - wrtww8gr.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 5 384 1.3 %
Date: 2012-12-27 Functions: 3 13 23.1 %
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             : 
      21             : #include <com/sun/star/embed/XEmbedPersist.hpp>
      22             : #include <com/sun/star/embed/Aspects.hpp>
      23             : #include <com/sun/star/embed/ElementModes.hpp>
      24             : #include <rtl/math.hxx>
      25             : #include <svtools/filter.hxx>
      26             : #include <svl/itemiter.hxx>
      27             : #include "svl/urihelper.hxx"
      28             : 
      29             : #include <svtools/embedhlp.hxx>
      30             : 
      31             : #include <vcl/virdev.hxx>
      32             : #include <vcl/svapp.hxx>
      33             : 
      34             : #include <hintids.hxx>
      35             : #include <editeng/boxitem.hxx>
      36             : #include <editeng/shaditem.hxx>
      37             : #include <filter/msfilter/msoleexp.hxx>
      38             : #include <editeng/lrspitem.hxx> // SvxLRSpaceItem
      39             : #include <editeng/ulspitem.hxx>
      40             : #include <editeng/fhgtitem.hxx>
      41             : #include <svx/svdoole2.hxx>
      42             : 
      43             : #include <unotools/ucbstreamhelper.hxx>
      44             : #include <fmtanchr.hxx>
      45             : #include <ndgrf.hxx>
      46             : #include <frmfmt.hxx>       // class SwFlyFrmFmt
      47             : #include <grfatr.hxx>       // class SwCropGrf
      48             : #include <ndole.hxx>
      49             : #include <ndtxt.hxx>
      50             : #include <fmtfsize.hxx>
      51             : #include <fmtornt.hxx>
      52             : 
      53             : #include <writerfilter/doctok/sprmids.hxx>
      54             : 
      55             : #include <doc.hxx>
      56             : #include "writerhelper.hxx"
      57             : #include "writerwordglue.hxx"
      58             : #include "ww8struc.hxx"
      59             : #include "wrtww8.hxx"
      60             : #include "ww8par.hxx"
      61             : #include "escher.hxx"
      62             : 
      63             : #include "docsh.hxx"
      64             : #include <cstdio>
      65             : 
      66             : #if OSL_DEBUG_LEVEL > 1
      67             : #include <stdio.h>
      68             : #endif
      69             : 
      70             : using namespace ::com::sun::star;
      71             : using namespace nsFieldFlags;
      72             : 
      73             : // ToDo:
      74             : // 5. Die MapModes, die Win nicht kann, umrechnen
      75             : 
      76             : // OutGrf() wird fuer jeden GrafNode im Doc gerufen. Es wird ein PicLocFc-Sprm
      77             : // eingefuegt, der statt Adresse ein Magic sal_uLong enthaelt. Ausserdem wird
      78             : // in der Graf-Klasse der GrfNode-Ptr gemerkt ( fuers spaetere Ausgeben der
      79             : // Grafiken und Patchen der PicLocFc-Attribute )
      80             : 
      81           0 : void WW8Export::OutputGrfNode( const SwGrfNode& /*rNode*/ )
      82             : {
      83             :     OSL_TRACE("WW8Export::OutputGrfNode( const SwGrfNode& )" );
      84             :     OSL_ENSURE( mpParentFrame, "frame not set!" );
      85           0 :     if ( mpParentFrame )
      86             :     {
      87           0 :         OutGrf( *mpParentFrame );
      88           0 :         pFib->fHasPic = 1;
      89             :     }
      90           0 : }
      91             : 
      92           0 : bool WW8Export::TestOleNeedsGraphic(const SwAttrSet& rSet,
      93             :     SvStorageRef xOleStg, SvStorageRef xObjStg, String &rStorageName,
      94             :     SwOLENode *pOLENd)
      95             : {
      96           0 :     bool bGraphicNeeded = false;
      97           0 :     SfxItemIter aIter( rSet );
      98           0 :     const SfxPoolItem* pItem = aIter.GetCurItem();
      99             : 
     100           0 :     do {
     101           0 :         switch (pItem->Which())
     102             :         {
     103             :             /*
     104             :             For an inline object these properties are irrelevent because they
     105             :             will be the same as the defaults that msword applies in their
     106             :             absence, so if that is all that there is for these inline objects
     107             :             then if there turns out to be enough information in the object
     108             :             itself to regenerate the correct size and preview of the object
     109             :             then we will not need to provide an additional graphics preview in
     110             :             the data stream, which can save a lot of disk space.
     111             :             */
     112             :             case RES_FRM_SIZE:
     113             :             case RES_CNTNT:
     114             :             case RES_VERT_ORIENT:
     115             :             case RES_ANCHOR:
     116           0 :                 break;
     117             :             default:
     118           0 :                 bGraphicNeeded = true;
     119             :         }
     120           0 :     } while( !bGraphicNeeded && !aIter.IsAtEnd() &&
     121             :         0 != ( pItem = aIter.NextItem() ) );
     122             : 
     123             :     /*
     124             :     Now we must see if the object contains a preview itself which is equal to
     125             :     the preview that we are currently using. If the graphics are equal then we
     126             :     dont need to store another preview
     127             :     */
     128           0 :     GDIMetaFile aWMF;
     129           0 :     long nX=0,nY=0;
     130           0 :     if (!bGraphicNeeded && SwWW8ImplReader::ImportOleWMF(xOleStg,aWMF,nX,nY))
     131             :     {
     132             :         // bGraphicNeeded set to true is right / fixes #i51670#.
     133           0 :         bGraphicNeeded = true;
     134           0 :         Point aTmpPoint;
     135           0 :         Rectangle aRect( aTmpPoint, Size( nX, nY ) );
     136           0 :         Graphic aGraph(aWMF);
     137             : 
     138           0 :         ErrCode nErr = ERRCODE_NONE;
     139           0 :         Rectangle aVisArea;
     140           0 :         sal_Int64 nAspect = embed::Aspects::MSOLE_CONTENT;
     141           0 :         if ( pOLENd )
     142           0 :             nAspect = pOLENd->GetAspect();
     143             :         SdrOle2Obj *pRet = SvxMSDffManager::CreateSdrOLEFromStorage(
     144           0 :             rStorageName,xObjStg,pDoc->GetDocStorage(),aGraph,aRect,aVisArea,0,nErr,0,nAspect);
     145             : 
     146           0 :         if (pRet)
     147             :         {
     148           0 :             uno::Reference< embed::XEmbeddedObject > xObj = pOLENd->GetOLEObj().GetOleRef();
     149           0 :             if ( xObj.is() )
     150             :             {
     151           0 :                 SvStream* pGraphicStream = NULL;
     152           0 :                 comphelper::EmbeddedObjectContainer aCnt( pDoc->GetDocStorage() );
     153             :                 try
     154             :                 {
     155             :                     uno::Reference< embed::XEmbedPersist > xPersist(
     156             :                             xObj,
     157           0 :                             uno::UNO_QUERY_THROW );
     158             : 
     159             :                     // it makes no sence to search the object in the container by reference since the object was created
     160             :                     // outside of the container and was not inserted there, only the name makes sence
     161             :                     pGraphicStream =
     162           0 :                             ::utl::UcbStreamHelper::CreateStream( aCnt.GetGraphicStream( xPersist->getEntryName() ) );
     163             :                 }
     164           0 :                 catch( const uno::Exception& )
     165             :                 {}
     166             : 
     167             :                 OSL_ENSURE( pGraphicStream && !pGraphicStream->GetError(), "No graphic stream available!" );
     168           0 :                 if ( pGraphicStream && !pGraphicStream->GetError() )
     169             :                 {
     170           0 :                     Graphic aGr1;
     171           0 :                     GraphicFilter& rGF = GraphicFilter::GetGraphicFilter();
     172           0 :                     if( rGF.ImportGraphic( aGr1, aEmptyStr, *pGraphicStream, GRFILTER_FORMAT_DONTKNOW ) == GRFILTER_OK )
     173             :                     {
     174           0 :                         Graphic aGr2;
     175           0 :                         delete pGraphicStream;
     176             :                         pGraphicStream =
     177           0 :                                 ::utl::UcbStreamHelper::CreateStream( aCnt.GetGraphicStream( pRet->GetObjRef() ) );
     178           0 :                         if( rGF.ImportGraphic( aGr2, aEmptyStr, *pGraphicStream, GRFILTER_FORMAT_DONTKNOW ) == GRFILTER_OK )
     179             :                         {
     180           0 :                             if ( aGr1 == aGr2 )
     181           0 :                                 bGraphicNeeded = false;
     182           0 :                         }
     183           0 :                     }
     184             :                 }
     185             :                 else
     186           0 :                     delete pGraphicStream;
     187             :             }
     188             : 
     189           0 :             delete pRet;
     190           0 :         }
     191             :     }
     192             :     else
     193           0 :         bGraphicNeeded = true;
     194           0 :     return bGraphicNeeded;
     195             : }
     196             : 
     197           0 : void WW8Export::OutputOLENode( const SwOLENode& rOLENode )
     198             : {
     199             :     OSL_TRACE("WW8Export::OutputOLENode( const SwOLENode& rOLENode )" );
     200             :     sal_uInt8 *pSpecOLE;
     201             :     sal_uInt8 *pDataAdr;
     202             :     short nSize;
     203             :     static sal_uInt8 aSpecOLE_WW8[] = {
     204             :             0x03, 0x6a, 0, 0, 0, 0, // sprmCPicLocation
     205             :             0x0a, 0x08, 1,          // sprmCFOLE2
     206             :             0x56, 0x08, 1           // sprmCFObj
     207             :         };
     208             :     static sal_uInt8 aSpecOLE_WW6[] = {
     209             :             68, 4, 0, 0, 0, 0,      // sprmCPicLocation (len is 4)
     210             :             75, 1,                  // sprmCFOLE2
     211             :             118, 1                  // sprmCFObj
     212             :         };
     213             : 
     214           0 :     if ( bWrtWW8 )
     215             :     {
     216           0 :         pSpecOLE = aSpecOLE_WW8;
     217           0 :         nSize = sizeof( aSpecOLE_WW8 );
     218             :     }
     219             :     else
     220             :     {
     221           0 :         pSpecOLE = aSpecOLE_WW6;
     222           0 :         nSize = sizeof( aSpecOLE_WW6 );
     223             :     }
     224           0 :     pDataAdr = pSpecOLE + 2; //WW6 sprm is 1 but has 1 byte len as well.
     225             : 
     226           0 :     SvStorageRef xObjStg = GetWriter().GetStorage().OpenSotStorage(
     227             :         rtl::OUString(SL::aObjectPool), STREAM_READWRITE |
     228           0 :         STREAM_SHARE_DENYALL );
     229             : 
     230           0 :     if( xObjStg.Is()  )
     231             :     {
     232           0 :         uno::Reference < embed::XEmbeddedObject > xObj(const_cast<SwOLENode&>(rOLENode).GetOLEObj().GetOleRef());
     233           0 :         if( xObj.is() )
     234             :         {
     235           0 :             const embed::XEmbeddedObject *pObj = xObj.get();
     236           0 :             WW8OleMap& rPointerToObjId = GetOLEMap();
     237             :             //Don't want to use pointer ids, as is traditional, because we need
     238             :             //to put this into a 32bit value, and on 64bit the bottom bits
     239             :             //might collide and two unrelated ole objects end up considered the
     240             :             //same.  Don't want to simply start at 0 which is a special value
     241           0 :             sal_Int32 nPictureId = SAL_MAX_INT32 - rPointerToObjId.size();
     242           0 :             WW8OleMap::value_type entry = std::make_pair(pObj, nPictureId);
     243           0 :             std::pair<WW8OleMap::iterator, bool> aRes = rPointerToObjId.insert(entry);
     244           0 :             bool bIsNotDuplicate = aRes.second; //.second is false when element already existed
     245           0 :             nPictureId = aRes.first->second;
     246           0 :             Set_UInt32(pDataAdr, nPictureId);
     247           0 :             String sStorageName = rtl::OUString('_');
     248           0 :             sStorageName += String::CreateFromInt32( nPictureId );
     249             :             SvStorageRef xOleStg = xObjStg->OpenSotStorage( sStorageName,
     250           0 :                                 STREAM_READWRITE| STREAM_SHARE_DENYALL );
     251           0 :             if( xOleStg.Is() )
     252             :             {
     253             :                 /*
     254             :                 If this object storage has been written already don't
     255             :                 waste time rewriting it
     256             :                 */
     257           0 :                 if (bIsNotDuplicate)
     258             :                 {
     259           0 :                     sal_Int64 nAspect = rOLENode.GetAspect();
     260           0 :                     svt::EmbeddedObjectRef aObjRef( xObj, nAspect );
     261           0 :                     GetOLEExp().ExportOLEObject( aObjRef, *xOleStg );
     262           0 :                     if ( nAspect == embed::Aspects::MSOLE_ICON )
     263             :                     {
     264           0 :                         ::rtl::OUString aObjInfo( "\3ObjInfo" );
     265           0 :                         if ( !xOleStg->IsStream( aObjInfo ) )
     266             :                         {
     267           0 :                             const sal_uInt8 pObjInfoData[] = { 0x40, 0x00, 0x03, 0x00 };
     268           0 :                             SvStorageStreamRef rObjInfoStream = xOleStg->OpenSotStream( aObjInfo );
     269           0 :                             if ( rObjInfoStream.Is() && !rObjInfoStream->GetError() )
     270             :                             {
     271           0 :                                 rObjInfoStream->Write( pObjInfoData, sizeof( pObjInfoData ) );
     272           0 :                                 xOleStg->Commit();
     273           0 :                             }
     274           0 :                         }
     275           0 :                     }
     276             :                 }
     277             : 
     278             :                 // write as embedded field - the other things will be done
     279             :                 // in the escher export
     280           0 :                 String sServer(FieldString(ww::eEMBED));
     281           0 :                 sServer += xOleStg->GetUserName();
     282           0 :                 sServer += ' ';
     283             : 
     284             :                 OutputField(0, ww::eEMBED, sServer, WRITEFIELD_START |
     285           0 :                     WRITEFIELD_CMD_START | WRITEFIELD_CMD_END);
     286             : 
     287           0 :                 pChpPlc->AppendFkpEntry( Strm().Tell(),
     288           0 :                         nSize, pSpecOLE );
     289             : 
     290           0 :                 bool bEndCR = true;
     291             :                 /*
     292             :                 In the word filter we only need a preview image for
     293             :                 floating images, and then only (the usual case) if the
     294             :                 object doesn't contain enough information to reconstruct
     295             :                 what we need.
     296             : 
     297             :                 We don't need a graphic for inline objects, so we don't
     298             :                 even need the overhead of a graphic in that case.
     299             :                 */
     300           0 :                 bool bGraphicNeeded = false;
     301             : 
     302           0 :                 if (mpParentFrame)
     303             :                 {
     304           0 :                     bGraphicNeeded = true;
     305             : 
     306           0 :                     if (mpParentFrame->IsInline())
     307             :                     {
     308             :                         const SwAttrSet& rSet =
     309           0 :                             mpParentFrame->GetFrmFmt().GetAttrSet();
     310           0 :                         bEndCR = false;
     311             :                         bGraphicNeeded = TestOleNeedsGraphic(rSet,
     312           0 :                             xOleStg, xObjStg, sStorageName, const_cast<SwOLENode*>(&rOLENode));
     313             :                     }
     314             :                 }
     315             : 
     316           0 :                 if (!bGraphicNeeded)
     317           0 :                     WriteChar(0x1);
     318             :                 else
     319             :                 {
     320             :                     /*
     321             :                     ##897##
     322             :                     We need to insert the graphic representation of
     323             :                     this object for the inline case, otherwise word
     324             :                     has no place to find the dimensions of the ole
     325             :                     object, and will not be able to draw it
     326             :                     */
     327           0 :                     OutGrf(*mpParentFrame);
     328             :                 }
     329             : 
     330             :                 OutputField(0, ww::eEMBED, aEmptyStr,
     331           0 :                     WRITEFIELD_END | WRITEFIELD_CLOSE);
     332             : 
     333           0 :                 if (bEndCR) //No newline in inline case
     334           0 :                     WriteCR();
     335           0 :             }
     336           0 :         }
     337           0 :     }
     338           0 : }
     339             : 
     340           0 : void WW8Export::OutputLinkedOLE( const rtl::OUString& rOleId )
     341             : {
     342           0 :     uno::Reference< embed::XStorage > xDocStg = pDoc->GetDocStorage();
     343           0 :     uno::Reference< embed::XStorage > xOleStg = xDocStg->openStorageElement( "OLELinks", embed::ElementModes::READ );
     344           0 :     SotStorageRef xObjSrc = SotStorage::OpenOLEStorage( xOleStg, rOleId, STREAM_READ );
     345             : 
     346           0 :     SotStorageRef xObjStg = GetWriter().GetStorage().OpenSotStorage(
     347             :         rtl::OUString(SL::aObjectPool), STREAM_READWRITE |
     348           0 :         STREAM_SHARE_DENYALL );
     349             : 
     350           0 :     if( xObjStg.Is() && xObjSrc.Is() )
     351             :     {
     352             :         SotStorageRef xOleDst = xObjStg->OpenSotStorage( rOleId,
     353           0 :                 STREAM_READWRITE | STREAM_SHARE_DENYALL );
     354           0 :         if ( xOleDst.Is() )
     355           0 :             xObjSrc->CopyTo( xOleDst );
     356             : 
     357           0 :         if ( !xOleDst->GetError( ) )
     358             :         {
     359           0 :             xOleDst->Commit();
     360             : 
     361             :             // Ouput the cPicLocation attribute
     362           0 :             ww::bytes* pBuf = new ww::bytes();
     363           0 :             GetWriter().InsUInt16( *pBuf, NS_sprm::LN_CPicLocation );
     364           0 :             GetWriter().InsUInt32( *pBuf, rOleId.copy( 1 ).toInt32() );
     365             : 
     366           0 :             GetWriter().InsUInt16( *pBuf, NS_sprm::LN_CFOle2 );
     367           0 :             pBuf->push_back( 1 );
     368             : 
     369           0 :             GetWriter().InsUInt16( *pBuf, NS_sprm::LN_CFSpec );
     370           0 :             pBuf->push_back( 1 );
     371             : 
     372           0 :             GetWriter().InsUInt16( *pBuf, NS_sprm::LN_CFObj );
     373           0 :             pBuf->push_back( 1 );
     374             : 
     375           0 :             pChpPlc->AppendFkpEntry( Strm().Tell(), pBuf->size(), pBuf->data() );
     376           0 :             delete pBuf;
     377           0 :         }
     378           0 :     }
     379           0 : }
     380             : 
     381           0 : void WW8Export::OutGrf(const sw::Frame &rFrame)
     382             : {
     383             :     // GrfNode fuer spaeteres rausschreiben der Grafik merken
     384           0 :     pGrf->Insert(rFrame);
     385             : 
     386           0 :     pChpPlc->AppendFkpEntry( Strm().Tell(), pO->size(), pO->data() );
     387           0 :     pO->clear();
     388             : 
     389             :     // #i29408#
     390             :     // linked, as-character anchored graphics have to be exported as fields.
     391           0 :     const SwGrfNode* pGrfNd = rFrame.IsInline() && rFrame.GetContent()
     392           0 :                               ? rFrame.GetContent()->GetGrfNode() : 0;
     393           0 :     if ( pGrfNd && pGrfNd->IsLinkedFile() )
     394             :     {
     395           0 :         String sStr( FieldString(ww::eINCLUDEPICTURE) );
     396           0 :         sStr.AppendAscii(" \"");
     397             :         {
     398           0 :             if ( pGrfNd )
     399             :             {
     400           0 :                 String aFileURL;
     401           0 :                 pGrfNd->GetFileFilterNms( &aFileURL, 0 );
     402           0 :                 sStr += aFileURL;
     403             :             }
     404             :         }
     405           0 :         sStr.AppendAscii("\" \\d");
     406             : 
     407             :         OutputField( 0, ww::eINCLUDEPICTURE, sStr,
     408           0 :                    WRITEFIELD_START | WRITEFIELD_CMD_START | WRITEFIELD_CMD_END );
     409             :     }
     410             : 
     411           0 :     WriteChar( (char)1 );   // Grafik-Sonderzeichen in Haupttext einfuegen
     412             : 
     413             :     sal_uInt8 aArr[ 18 ];
     414           0 :     sal_uInt8* pArr = aArr;
     415             : 
     416           0 :     const SwFrmFmt &rFlyFmt = rFrame.GetFrmFmt();
     417           0 :     const RndStdIds eAn = rFlyFmt.GetAttrSet().GetAnchor(false).GetAnchorId();
     418           0 :     if (eAn == FLY_AS_CHAR)
     419             :     {
     420           0 :         sal_Int16 eVert = rFlyFmt.GetVertOrient().GetVertOrient();
     421           0 :         if ((eVert == text::VertOrientation::CHAR_CENTER) || (eVert == text::VertOrientation::LINE_CENTER))
     422             :         {
     423           0 :             bool bVert = false;
     424             :             //The default for word in vertical text mode is to center,
     425             :             //otherwise a sub/super script hack is employed
     426           0 :             if (pOutFmtNode && pOutFmtNode->ISA(SwCntntNode) )
     427             :             {
     428           0 :                 const SwTxtNode* pTxtNd = (const SwTxtNode*)pOutFmtNode;
     429           0 :                 SwPosition aPos(*pTxtNd);
     430           0 :                 bVert = pDoc->IsInVerticalText(aPos);
     431             :             }
     432           0 :             if (!bVert)
     433             :             {
     434           0 :                 SwTwips nHeight = rFlyFmt.GetFrmSize().GetHeight();
     435           0 :                 nHeight/=20; //nHeight was in twips, want it in half points, but
     436             :                              //then half of total height.
     437             :                 long nFontHeight = ((const SvxFontHeightItem&)
     438           0 :                     GetItem(RES_CHRATR_FONTSIZE)).GetHeight();
     439           0 :                 nHeight-=nFontHeight/20;
     440             : 
     441           0 :                 if (bWrtWW8)
     442           0 :                     Set_UInt16( pArr, NS_sprm::LN_CHpsPos );
     443             :                 else
     444           0 :                     Set_UInt8( pArr, 101 );
     445           0 :                 Set_UInt16( pArr, -((sal_Int16)nHeight));
     446             :             }
     447             :         }
     448             :     }
     449             : 
     450             :     // sprmCFSpec
     451           0 :     if( bWrtWW8 )
     452           0 :         Set_UInt16( pArr, 0x855 );
     453             :     else
     454           0 :         Set_UInt8( pArr, 117 );
     455           0 :     Set_UInt8( pArr, 1 );
     456             : 
     457             :     // sprmCPicLocation
     458           0 :     if( bWrtWW8 )
     459           0 :         Set_UInt16( pArr, NS_sprm::LN_CPicLocation );
     460             :     else
     461             :     {
     462           0 :         Set_UInt8( pArr, 68 );
     463           0 :         Set_UInt8( pArr, 4 );
     464             :     }
     465           0 :     Set_UInt32( pArr, GRF_MAGIC_321 );
     466             : 
     467             :     // Magic variieren, damit verschiedene Grafik-Attribute nicht
     468             :     // gemerged werden
     469             :     static sal_uInt8 nAttrMagicIdx = 0;
     470           0 :     --pArr;
     471           0 :     Set_UInt8( pArr, nAttrMagicIdx++ );
     472           0 :     pChpPlc->AppendFkpEntry( Strm().Tell(), static_cast< short >(pArr - aArr), aArr );
     473             : 
     474             :     // #i75464#
     475             :     // Check, if graphic isn't exported as-character anchored.
     476             :     // Otherwise, an additional paragraph is exported for a graphic, which is
     477             :     // forced to be treated as inline, because it's anchored inside another frame.
     478           0 :     if ( !rFrame.IsInline() &&
     479           0 :          ( ((eAn == FLY_AT_PARA) && ( bWrtWW8 || !IsInTable() )) ||
     480             :            (eAn == FLY_AT_PAGE)) )
     481             :     {
     482           0 :         WriteChar( (char)0x0d ); // umgebenden Rahmen mit CR abschliessen
     483             : 
     484             :         static sal_uInt8 nSty[2] = { 0, 0 };
     485           0 :         pO->insert( pO->end(), nSty, nSty+2 );     // Style #0
     486           0 :         bool bOldGrf = bOutGrf;
     487           0 :         bOutGrf = true;
     488             : 
     489           0 :         OutputFormat( rFrame.GetFrmFmt(), false, false, true ); // Fly-Attrs
     490             : 
     491           0 :         bOutGrf = bOldGrf;
     492           0 :         pPapPlc->AppendFkpEntry( Strm().Tell(), pO->size(), pO->data() );
     493           0 :         pO->clear();
     494             :     }
     495             :     // #i29408#
     496             :     // linked, as-character anchored graphics have to be exported as fields.
     497           0 :     else if ( pGrfNd && pGrfNd->IsLinkedFile() )
     498             :     {
     499           0 :         OutputField( 0, ww::eINCLUDEPICTURE, String(), WRITEFIELD_CLOSE );
     500             :     }
     501           0 : }
     502             : 
     503           0 : GraphicDetails& GraphicDetails::operator=(const GraphicDetails &rOther)
     504             : {
     505           0 :     maFly = rOther.maFly;
     506           0 :     mnPos = rOther.mnPos;
     507           0 :     mnWid = rOther.mnWid;
     508           0 :     mnHei = rOther.mnHei;
     509           0 :     return *this;
     510             : }
     511             : 
     512           0 : void SwWW8WrGrf::Insert(const sw::Frame &rFly)
     513             : {
     514           0 :     const Size aSize( rFly.GetLayoutSize() );
     515           0 :     const sal_uInt16 nWidth = static_cast< sal_uInt16 >(aSize.Width());
     516           0 :     const sal_uInt16 nHeight = static_cast< sal_uInt16 >(aSize.Height());
     517           0 :     maDetails.push_back(GraphicDetails(rFly, nWidth, nHeight));
     518           0 : }
     519             : 
     520           0 : void SwWW8WrGrf::WritePICFHeader(SvStream& rStrm, const sw::Frame &rFly,
     521             :     sal_uInt16 mm, sal_uInt16 nWidth, sal_uInt16 nHeight, const SwAttrSet* pAttrSet)
     522             : {
     523           0 :     sal_Int16 nXSizeAdd = 0, nYSizeAdd = 0;
     524           0 :     sal_Int16 nCropL = 0, nCropR = 0, nCropT = 0, nCropB = 0;
     525             : 
     526             :             // Crop-AttributInhalt in Header schreiben ( falls vorhanden )
     527             :     const SfxPoolItem* pItem;
     528           0 :     if (pAttrSet && (SFX_ITEM_ON
     529           0 :         == pAttrSet->GetItemState(RES_GRFATR_CROPGRF, false, &pItem)))
     530             :     {
     531           0 :         const SwCropGrf& rCr = *(SwCropGrf*)pItem;
     532           0 :         nCropL = (sal_Int16)rCr.GetLeft();
     533           0 :         nCropR = (sal_Int16)rCr.GetRight();
     534           0 :         nCropT = (sal_Int16)rCr.GetTop();
     535           0 :         nCropB = (sal_Int16)rCr.GetBottom();
     536           0 :         nXSizeAdd = nXSizeAdd - (sal_Int16)( rCr.GetLeft() + rCr.GetRight() );
     537           0 :         nYSizeAdd = nYSizeAdd - (sal_Int16)( rCr.GetTop() + rCr.GetBottom() );
     538             :     }
     539             : 
     540           0 :     Size aGrTwipSz(rFly.GetSize());
     541           0 :     bool bWrtWW8 = rWrt.bWrtWW8;
     542           0 :     sal_uInt16 nHdrLen = bWrtWW8 ? 0x44 : 0x3A;
     543             : 
     544           0 :     sal_uInt8 aArr[ 0x44 ] = { 0 };
     545             : 
     546           0 :     sal_uInt8* pArr = aArr + 0x2E;  //Do borders first
     547             : 
     548           0 :     const SwAttrSet& rAttrSet = rFly.GetFrmFmt().GetAttrSet();
     549           0 :     if (SFX_ITEM_ON == rAttrSet.GetItemState(RES_BOX, false, &pItem))
     550             :     {
     551           0 :         const SvxBoxItem* pBox = (const SvxBoxItem*)pItem;
     552           0 :         if( pBox )
     553             :         {
     554           0 :             bool bShadow = false;               // Shadow ?
     555             :             const SvxShadowItem* pSI =
     556           0 :                 sw::util::HasItem<SvxShadowItem>(rAttrSet, RES_SHADOW);
     557           0 :             if (pSI)
     558             :             {
     559           0 :                 bShadow = (pSI->GetLocation() != SVX_SHADOW_NONE) &&
     560           0 :                     (pSI->GetWidth() != 0);
     561             :             }
     562             : 
     563             :             sal_uInt8 aLnArr[4] = { BOX_LINE_TOP, BOX_LINE_LEFT,
     564           0 :                                 BOX_LINE_BOTTOM, BOX_LINE_RIGHT };
     565           0 :             for( sal_uInt8 i = 0; i < 4; ++i )
     566             :             {
     567           0 :                 const ::editeng::SvxBorderLine* pLn = pBox->GetLine( aLnArr[ i ] );
     568           0 :                 WW8_BRC aBrc;
     569           0 :                 if (pLn)
     570             :                 {
     571             :                     aBrc = rWrt.TranslateBorderLine( *pLn,
     572           0 :                         pBox->GetDistance( aLnArr[ i ] ), bShadow );
     573             :                 }
     574             : 
     575             :                 //use importer logic to determine how large the exported
     576             :                 //border will really be in word and adjust accordingly
     577             :                 short nSpacing;
     578           0 :                 short nThick = aBrc.DetermineBorderProperties(!bWrtWW8,
     579           0 :                     &nSpacing);
     580           0 :                 switch (aLnArr[ i ])
     581             :                 {
     582             :                     case BOX_LINE_TOP:
     583             :                     case BOX_LINE_BOTTOM:
     584           0 :                         nHeight -= bShadow ? nThick*2 : nThick;
     585           0 :                         nHeight = nHeight - nSpacing;
     586           0 :                         break;
     587             :                     case BOX_LINE_LEFT:
     588             :                     case BOX_LINE_RIGHT:
     589             :                     default:
     590           0 :                         nWidth -= bShadow ? nThick*2 : nThick;
     591           0 :                         nWidth = nWidth - nSpacing;
     592           0 :                         break;
     593             :                 }
     594           0 :                 memcpy( pArr, &aBrc.aBits1, 2);
     595           0 :                 pArr+=2;
     596             : 
     597           0 :                 if( bWrtWW8 )
     598             :                 {
     599           0 :                     memcpy( pArr, &aBrc.aBits2, 2);
     600           0 :                     pArr+=2;
     601             :                 }
     602             :             }
     603             :         }
     604             :     }
     605             : 
     606           0 :     pArr = aArr + 4;                                //skip lcb
     607           0 :     Set_UInt16( pArr, nHdrLen );                    // set cbHeader
     608             : 
     609           0 :     Set_UInt16( pArr, mm );                         // set mm
     610             : 
     611             :     /*
     612             :     Just in case our original size is too big to fit inside a ushort we can
     613             :     substitute the final size and loose on retaining the scaling factor but
     614             :     still keep the correct display size anyway.
     615             :     */
     616           0 :     if ( (aGrTwipSz.Width() > SHRT_MAX) || (aGrTwipSz.Height() > SHRT_MAX)
     617           0 :         || (aGrTwipSz.Width() < 0 ) || (aGrTwipSz.Height() < 0) )
     618             :     {
     619           0 :         aGrTwipSz.Width() = nWidth;
     620           0 :         aGrTwipSz.Height() = nHeight;
     621             :     }
     622             :     using namespace sw::types;
     623             :     // set xExt & yExt
     624           0 :     Set_UInt16(pArr, msword_cast<sal_uInt16>(aGrTwipSz.Width() * 254L / 144));
     625           0 :     Set_UInt16(pArr, msword_cast<sal_uInt16>(aGrTwipSz.Height() * 254L / 144));
     626           0 :     pArr += 16;
     627             :     // skip hMF & rcWinMF
     628             :     // set dxaGoal & dyaGoal
     629           0 :     Set_UInt16(pArr, msword_cast<sal_uInt16>(aGrTwipSz.Width()));
     630           0 :     Set_UInt16(pArr, msword_cast<sal_uInt16>(aGrTwipSz.Height()));
     631             : 
     632           0 :     if( aGrTwipSz.Width() + nXSizeAdd )             // set mx
     633             :     {
     634           0 :         double fVal = nWidth * 1000.0 / (aGrTwipSz.Width() + nXSizeAdd);
     635           0 :         Set_UInt16( pArr, (sal_uInt16)::rtl::math::round(fVal) );
     636             :     }
     637             :     else
     638           0 :         pArr += 2;
     639             : 
     640           0 :     if( aGrTwipSz.Height() + nYSizeAdd )            // set my
     641             :     {
     642           0 :         double fVal = nHeight * 1000.0 / (aGrTwipSz.Height() + nYSizeAdd);
     643           0 :         Set_UInt16( pArr, (sal_uInt16)::rtl::math::round(fVal) );
     644             :     }
     645             :     else
     646           0 :         pArr += 2;
     647             : 
     648           0 :     Set_UInt16( pArr, nCropL );                     // set dxaCropLeft
     649           0 :     Set_UInt16( pArr, nCropT );                     // set dyaCropTop
     650           0 :     Set_UInt16( pArr, nCropR );                     // set dxaCropRight
     651           0 :     Set_UInt16( pArr, nCropB );                     // set dyaCropBottom
     652             : 
     653           0 :     rStrm.Write( aArr, nHdrLen );
     654           0 : }
     655             : 
     656           0 : void SwWW8WrGrf::WriteGrfFromGrfNode(SvStream& rStrm, const SwGrfNode &rGrfNd,
     657             :     const sw::Frame &rFly, sal_uInt16 nWidth, sal_uInt16 nHeight)
     658             : {
     659           0 :     if (rGrfNd.IsLinkedFile())     // Linked File
     660             :     {
     661           0 :         String aFileN;
     662           0 :         rGrfNd.GetFileFilterNms( &aFileN, 0 );
     663             : 
     664           0 :             sal_uInt16 mm = 94;                    // 94 = BMP, GIF
     665             : 
     666             :         WritePICFHeader(rStrm, rFly, mm, nWidth, nHeight,
     667           0 :             rGrfNd.GetpSwAttrSet());
     668           0 :         rStrm << (sal_uInt8)aFileN.Len();    // Pascal-String schreiben
     669             :         SwWW8Writer::WriteString8(rStrm, aFileN, false,
     670           0 :             RTL_TEXTENCODING_MS_1252);
     671             :     }
     672             :     else                                // Embedded File oder DDE oder so was
     673             :     {
     674           0 :         if (rWrt.bWrtWW8)
     675             :         {
     676             :             WritePICFHeader(rStrm, rFly, 0x64, nWidth, nHeight,
     677           0 :                 rGrfNd.GetpSwAttrSet());
     678           0 :             SwBasicEscherEx aInlineEscher(&rStrm, rWrt);
     679           0 :             aInlineEscher.WriteGrfFlyFrame(rFly.GetFrmFmt(), 0x401);
     680           0 :             aInlineEscher.WritePictures();
     681             :         }
     682             :         else
     683             :         {
     684           0 :             Graphic& rGrf = const_cast<Graphic&>(rGrfNd.GetGrf());
     685           0 :             bool bSwapped = rGrf.IsSwapOut() ? true : false;
     686             :             // immer ueber den Node einswappen!
     687           0 :             const_cast<SwGrfNode&>(rGrfNd).SwapIn();
     688             : 
     689           0 :             GDIMetaFile aMeta;
     690           0 :             switch (rGrf.GetType())
     691             :             {
     692             :                 case GRAPHIC_BITMAP:        // Bitmap -> in Metafile abspielen
     693             :                     {
     694           0 :                         VirtualDevice aVirt;
     695           0 :                         aMeta.Record(&aVirt);
     696           0 :                         aVirt.DrawBitmap( Point( 0,0 ), rGrf.GetBitmap() );
     697           0 :                         aMeta.Stop();
     698           0 :                         aMeta.WindStart();
     699           0 :                         aMeta.SetPrefMapMode( rGrf.GetPrefMapMode());
     700           0 :                         aMeta.SetPrefSize( rGrf.GetPrefSize());
     701             :                     }
     702           0 :                     break;
     703             :                 case GRAPHIC_GDIMETAFILE :      // GDI ( =SV ) Metafile
     704           0 :                     aMeta = rGrf.GetGDIMetaFile();
     705           0 :                     break;
     706             :                 default:
     707           0 :                     return;
     708             :             }
     709             : 
     710             :             WritePICFHeader(rStrm, rFly, 8, nWidth, nHeight,
     711           0 :                 rGrfNd.GetpSwAttrSet());
     712           0 :             WriteWindowMetafileBits(rStrm, aMeta);
     713             : 
     714           0 :             if (bSwapped)
     715           0 :                 rGrf.SwapOut();
     716             :         }
     717             :     }
     718             : }
     719             : 
     720           0 : void SwWW8WrGrf::WriteGraphicNode(SvStream& rStrm, const GraphicDetails &rItem)
     721             : {
     722           0 :     sal_uInt16 nWidth = rItem.mnWid;
     723           0 :     sal_uInt16 nHeight = rItem.mnHei;
     724           0 :     sal_uInt32 nPos = rStrm.Tell();         // Grafik-Anfang merken
     725             : 
     726           0 :     const sw::Frame &rFly = rItem.maFly;
     727           0 :     switch (rFly.GetWriterType())
     728             :     {
     729             :         case sw::Frame::eGraphic:
     730             :         {
     731           0 :             const SwNode *pNode = rItem.maFly.GetContent();
     732           0 :             const SwGrfNode *pNd = pNode ? pNode->GetGrfNode() : 0;
     733             :             OSL_ENSURE(pNd, "Impossible");
     734           0 :             if (pNd)
     735           0 :                 WriteGrfFromGrfNode(rStrm, *pNd, rItem.maFly, nWidth, nHeight);
     736             :         }
     737           0 :         break;
     738             :         case sw::Frame::eOle:
     739             :         {
     740             : #ifdef OLE_PREVIEW_AS_EMF
     741           0 :             const SwNode *pNode = rItem.maFly.GetContent();
     742           0 :             const SwOLENode *pNd = pNode ? pNode->GetOLENode() : 0;
     743             :             OSL_ENSURE(pNd, "Impossible");
     744           0 :             if (!rWrt.bWrtWW8)
     745             :             {
     746           0 :                 SwOLENode *pOleNd = const_cast<SwOLENode*>(pNd);
     747             :                 OSL_ENSURE( pOleNd, " Wer hat den OleNode versteckt ?" );
     748           0 :                 SwOLEObj&                   rSObj= pOleNd->GetOLEObj();
     749           0 :                 uno::Reference < embed::XEmbeddedObject > rObj(  rSObj.GetOleRef() );
     750             : 
     751           0 :                 comphelper::EmbeddedObjectContainer aCnt( pOleNd->GetDoc()->GetDocStorage() );
     752             : 
     753           0 :                 SvStream* pGraphicStream = ::utl::UcbStreamHelper::CreateStream( aCnt.GetGraphicStream( rObj ) );
     754             :                 OSL_ENSURE( pGraphicStream && !pGraphicStream->GetError(), "No graphic stream available!" );
     755           0 :                 if ( pGraphicStream && !pGraphicStream->GetError() )
     756             :                 {
     757           0 :                     Graphic aGr;
     758           0 :                     GraphicFilter& rGF = GraphicFilter::GetGraphicFilter();
     759           0 :                     if( rGF.ImportGraphic( aGr, aEmptyStr, *pGraphicStream, GRFILTER_FORMAT_DONTKNOW ) == GRFILTER_OK )
     760             :                     {
     761             :                         //TODO/LATER: do we really want to use GDIMetafile?!
     762           0 :                         GDIMetaFile aMtf;
     763           0 :                         aMtf = aGr.GetGDIMetaFile();
     764           0 :                         aMtf.WindStart();
     765             :                         aMtf.Play(Application::GetDefaultDevice(), Point(0, 0),
     766           0 :                             Size(2880, 2880));
     767             :                         WritePICFHeader(rStrm, rFly, 8, nWidth, nHeight,
     768           0 :                             pNd->GetpSwAttrSet());
     769           0 :                         WriteWindowMetafileBits(rStrm, aMtf);
     770           0 :                     }
     771             :                 }
     772             :                 else
     773           0 :                     delete pGraphicStream;
     774             :             }
     775             :             else
     776             :             {
     777             :                 //Convert this ole2 preview in ww8+ to an EMF for better unicode
     778             :                 //support (note that at this moment this breaks StarSymbol
     779             :                 //using graphics because I need to embed starsymbol in exported
     780             :                 //documents.
     781             :                 WritePICFHeader(rStrm, rFly, 0x64, nWidth, nHeight,
     782           0 :                     pNd->GetpSwAttrSet());
     783           0 :                 SwBasicEscherEx aInlineEscher(&rStrm, rWrt);
     784           0 :                 aInlineEscher.WriteOLEFlyFrame(rFly.GetFrmFmt(), 0x401);
     785           0 :                 aInlineEscher.WritePictures();
     786             :             }
     787             : #else
     788             :             // cast away const
     789             :             SwOLENode *pOleNd = const_cast<SwOLENode*>(pNd);
     790             :             OSL_ENSURE( pOleNd, " Wer hat den OleNode versteckt ?" );
     791             :             SwOLEObj&                   rSObj= pOleNd->GetOLEObj();
     792             : 
     793             :             // TODO/LATER: do we need to load object?
     794             :             Graphic* pGr = SdrOle2Obj::GetGraphicFromObject( pOleNd->GetDoc()->GetDocStorage(), rObj );
     795             : 
     796             :             //TODO/LATER: do we really want to use GDIMetafile?!
     797             :             GDIMetaFile aMtf;
     798             :             if ( pGr )
     799             :                 aMtf = pGr->GetGDIMetaFile();
     800             : 
     801             :             Size aS(aMtf.GetPrefSize());
     802             :             aMtf.WindStart();
     803             :             aMtf.Play(Application::GetDefaultDevice(), Point(0, 0),
     804             :                 Size(2880, 2880));
     805             : 
     806             :             WritePICFHeader(rStrm, rFly, 8, nWidth, nHeight,
     807             :                 pNd->GetpSwAttrSet());
     808             :             WriteWindowMetafileBits(rStrm, aMtf);
     809             :             delete pGr;
     810             : #endif
     811             :         }
     812           0 :         break;
     813             :         case sw::Frame::eDrawing:
     814             :         case sw::Frame::eTxtBox:
     815             :         case sw::Frame::eFormControl:
     816             :             OSL_ENSURE(rWrt.bWrtWW8,
     817             :                 "You can't try and export these in WW8 format, a filter bug");
     818             :             /*
     819             :             #i3958# We only export an empty dummy picture frame here, this is
     820             :             what word does the escher export should contain an anchored to
     821             :             character element which is drawn over this dummy and the whole
     822             :             shebang surrounded with a SHAPE field. This isn't *my* hack :-),
     823             :             its what word does.
     824             :             */
     825           0 :             if (rWrt.bWrtWW8)
     826             :             {
     827           0 :                 WritePICFHeader(rStrm, rFly, 0x64, nWidth, nHeight);
     828           0 :                 SwBasicEscherEx aInlineEscher(&rStrm, rWrt);
     829           0 :                 aInlineEscher.WriteEmptyFlyFrame(rFly.GetFrmFmt(), 0x401);
     830             :             }
     831           0 :             break;
     832             :         default:
     833             :             OSL_ENSURE(!this,
     834             :            "Some inline export not implemented, remind cmc before we ship :-)");
     835           0 :             break;
     836             :     }
     837             : 
     838           0 :     sal_uInt32 nPos2 = rStrm.Tell();                    // Ende merken
     839           0 :     rStrm.Seek( nPos );
     840             :     SVBT32 nLen;
     841           0 :     UInt32ToSVBT32( nPos2 - nPos, nLen );             // Grafik-Laenge ausrechnen
     842           0 :     rStrm.Write( nLen, 4 );                         // im Header einpatchen
     843           0 :     rStrm.Seek( nPos2 );                            // Pos wiederherstellen
     844           0 : }
     845             : 
     846             : // SwWW8WrGrf::Write() wird nach dem Text gerufen. Es schreibt die alle
     847             : // Grafiken raus und merkt sich die File-Positionen der Grafiken, damit
     848             : // beim Schreiben der Attribute die Positionen in die PicLocFc-Sprms
     849             : // eingepatcht werden koennen.
     850             : // Das Suchen in den Attributen nach dem Magic sal_uLong und das Patchen
     851             : // passiert beim Schreiben der Attribute. Die SwWW8WrGrf-Klasse liefert
     852             : // hierfuer nur mit GetFPos() sequentiell die Positionen.
     853           4 : void SwWW8WrGrf::Write()
     854             : {
     855           4 :     SvStream& rStrm = *rWrt.pDataStrm;
     856           4 :     myiter aEnd = maDetails.end();
     857           4 :     for (myiter aIter = maDetails.begin(); aIter != aEnd; ++aIter)
     858             :     {
     859           0 :         sal_uInt32 nPos = rStrm.Tell();                 // auf 4 Bytes alignen
     860           0 :         if( nPos & 0x3 )
     861           0 :             SwWW8Writer::FillCount( rStrm, 4 - ( nPos & 0x3 ) );
     862             : 
     863           0 :         bool bDuplicated = false;
     864           0 :         for (myiter aIter2 = maDetails.begin(); aIter2 != aIter; ++aIter2)
     865             :         {
     866           0 :             if (*aIter2 == *aIter)
     867             :             {
     868           0 :                 aIter->mnPos = aIter2->mnPos;
     869           0 :                 bDuplicated = true;
     870           0 :                 break;
     871             :             }
     872             :         }
     873             : 
     874           0 :         if (!bDuplicated)
     875             :         {
     876           0 :             aIter->mnPos = rStrm.Tell();
     877           0 :             WriteGraphicNode(rStrm, *aIter);
     878             :         }
     879             :     }
     880          22 : }
     881             : 
     882             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10