LCOV - code coverage report
Current view: top level - filter/source/graphicfilter/ieps - ieps.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 269 384 70.1 %
Date: 2015-06-13 12:38:46 Functions: 14 14 100.0 %
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 <tools/solar.h>
      22             : #include <vcl/svapp.hxx>
      23             : #include <vcl/bitmap.hxx>
      24             : #include <vcl/bitmapex.hxx>
      25             : #include <vcl/animate.hxx>
      26             : #include <vcl/gdimtf.hxx>
      27             : #include <vcl/graph.h>
      28             : #include <vcl/window.hxx>
      29             : #include <vcl/graph.hxx>
      30             : #include <vcl/metaact.hxx>
      31             : #include <vcl/virdev.hxx>
      32             : #include <vcl/cvtgrf.hxx>
      33             : #include <vcl/bmpacc.hxx>
      34             : #include <unotools/tempfile.hxx>
      35             : #include <osl/process.h>
      36             : #include <osl/file.hxx>
      37             : #include <osl/thread.h>
      38             : #include <boost/scoped_array.hpp>
      39             : 
      40             : class FilterConfigItem;
      41             : 
      42             : /*************************************************************************
      43             : |*
      44             : |*    ImpSearchEntry()
      45             : |*
      46             : |*    Description       Checks if there is a string(pDest) of length nSize
      47             : |*                      inside the memory area pSource which is nComp bytes long.
      48             : |*                      Check is NON-CASE-SENSITIVE. The return value is the
      49             : |*                      address where the string is found or NULL
      50             : |*
      51             : *************************************************************************/
      52             : 
      53          14 : static sal_uInt8* ImplSearchEntry( sal_uInt8* pSource, sal_uInt8 const * pDest, sal_uLong nComp, sal_uLong nSize )
      54             : {
      55    11425259 :     while ( nComp-- >= nSize )
      56             :     {
      57             :         sal_uLong i;
      58    11450554 :         for ( i = 0; i < nSize; i++ )
      59             :         {
      60    11450543 :             if ( ( pSource[i]&~0x20 ) != ( pDest[i]&~0x20 ) )
      61    11425231 :                 break;
      62             :         }
      63    11425242 :         if ( i == nSize )
      64          11 :             return pSource;
      65    11425231 :         pSource++;
      66             :     }
      67           3 :     return NULL;
      68             : }
      69             : 
      70             : 
      71             : // SecurityCount is the buffersize of the buffer in which we will parse for a number
      72           8 : static long ImplGetNumber( sal_uInt8 **pBuf, int& nSecurityCount )
      73             : {
      74           8 :     bool    bValid = true;
      75           8 :     bool    bNegative = false;
      76           8 :     long    nRetValue = 0;
      77          24 :     while ( ( --nSecurityCount ) && ( ( **pBuf == ' ' ) || ( **pBuf == 0x9 ) ) )
      78           8 :         (*pBuf)++;
      79           8 :     sal_uInt8 nByte = **pBuf;
      80          35 :     while ( nSecurityCount && ( nByte != ' ' ) && ( nByte != 0x9 ) && ( nByte != 0xd ) && ( nByte != 0xa ) )
      81             :     {
      82          19 :         switch ( nByte )
      83             :         {
      84             :             case '.' :
      85             :                 // we'll only use the integer format
      86           0 :                 bValid = false;
      87           0 :                 break;
      88             :             case '-' :
      89           0 :                 bNegative = true;
      90           0 :                 break;
      91             :             default :
      92          19 :                 if ( ( nByte < '0' ) || ( nByte > '9' ) )
      93           0 :                     nSecurityCount = 1;         // error parsing the bounding box values
      94          19 :                 else if ( bValid )
      95             :                 {
      96          19 :                     nRetValue *= 10;
      97          19 :                     nRetValue += nByte - '0';
      98             :                 }
      99          19 :                 break;
     100             :         }
     101          19 :         nSecurityCount--;
     102          19 :         nByte = *(++(*pBuf));
     103             :     }
     104           8 :     if ( bNegative )
     105           0 :         nRetValue = -nRetValue;
     106           8 :     return nRetValue;
     107             : }
     108             : 
     109             : 
     110             : 
     111           3 : static int ImplGetLen( sal_uInt8* pBuf, int nMax )
     112             : {
     113           3 :     int nLen = 0;
     114          62 :     while( nLen != nMax )
     115             :     {
     116          59 :         sal_uInt8 nDat = *pBuf++;
     117          59 :         if ( nDat == 0x0a || nDat == 0x25 )
     118             :             break;
     119          56 :         nLen++;
     120             :     }
     121           3 :     return nLen;
     122             : }
     123             : 
     124           1 : static void MakeAsMeta(Graphic &rGraphic)
     125             : {
     126           1 :     ScopedVclPtrInstance< VirtualDevice > pVDev;
     127           2 :     GDIMetaFile     aMtf;
     128           2 :     Bitmap          aBmp( rGraphic.GetBitmap() );
     129           1 :     Size            aSize = aBmp.GetPrefSize();
     130             : 
     131           1 :     if( !aSize.Width() || !aSize.Height() )
     132             :         aSize = Application::GetDefaultDevice()->PixelToLogic(
     133           0 :             aBmp.GetSizePixel(), MAP_100TH_MM );
     134             :     else
     135             :         aSize = OutputDevice::LogicToLogic( aSize,
     136           1 :             aBmp.GetPrefMapMode(), MAP_100TH_MM );
     137             : 
     138           1 :     pVDev->EnableOutput( false );
     139           1 :     aMtf.Record( pVDev );
     140           1 :     pVDev->DrawBitmap( Point(), aSize, rGraphic.GetBitmap() );
     141           1 :     aMtf.Stop();
     142           1 :     aMtf.WindStart();
     143           1 :     aMtf.SetPrefMapMode( MAP_100TH_MM );
     144           1 :     aMtf.SetPrefSize( aSize );
     145           2 :     rGraphic = aMtf;
     146           1 : }
     147             : 
     148           5 : static oslProcessError runProcessWithPathSearch(const OUString &rProgName,
     149             :     rtl_uString* pArgs[], sal_uInt32 nArgs, oslProcess *pProcess,
     150             :     oslFileHandle *pIn, oslFileHandle *pOut, oslFileHandle *pErr)
     151             : {
     152             :     oslProcessError result;
     153           5 :     oslSecurity pSecurity = osl_getCurrentSecurity();
     154             : #ifdef WNT
     155             :     /*
     156             :      * ooo#72096
     157             :      * On Window the underlying SearchPath searches in order of...
     158             :      * The directory from which the application loaded.
     159             :      * The current directory.
     160             :      * The Windows system directory.
     161             :      * The Windows directory.
     162             :      * The directories that are listed in the PATH environment variable.
     163             :      *
     164             :      * Because one of our programs is called "convert" and there is a convert
     165             :      * in the windows system directory, we want to explicitly search the PATH
     166             :      * to avoid picking up on that one if ImageMagick's convert precedes it in
     167             :      * PATH.
     168             :      *
     169             :      */
     170             :     OUString url;
     171             :     OUString path(reinterpret_cast<const sal_Unicode*>(_wgetenv(L"PATH")));
     172             : 
     173             :     oslFileError err = osl_searchFileURL(rProgName.pData, path.pData, &url.pData);
     174             :     if (err != osl_File_E_None)
     175             :         return osl_Process_E_NotFound;
     176             : 
     177             :     result = osl_executeProcess_WithRedirectedIO(url.pData,
     178             :     pArgs, nArgs, osl_Process_HIDDEN,
     179             :         pSecurity, 0, 0, 0, pProcess, pIn, pOut, pErr);
     180             : #else
     181             :     result = osl_executeProcess_WithRedirectedIO(rProgName.pData,
     182             :         pArgs, nArgs, osl_Process_SEARCHPATH | osl_Process_HIDDEN,
     183           5 :         pSecurity, 0, 0, 0, pProcess, pIn, pOut, pErr);
     184             : #endif
     185           5 :     osl_freeSecurityHandle( pSecurity );
     186           5 :     return result;
     187             : }
     188             : 
     189             : #if defined(WNT)
     190             : #    define EXESUFFIX ".exe"
     191             : #else
     192             : #    define EXESUFFIX ""
     193             : #endif
     194             : 
     195           2 : static bool RenderAsEMF(const sal_uInt8* pBuf, sal_uInt32 nBytesRead, Graphic &rGraphic)
     196             : {
     197           2 :     utl::TempFile aTempOutput;
     198           4 :     utl::TempFile aTempInput;
     199           2 :     aTempOutput.EnableKillingFile();
     200           2 :     aTempInput.EnableKillingFile();
     201           4 :     OUString output;
     202           2 :     osl::FileBase::getSystemPathFromFileURL(aTempOutput.GetURL(), output);
     203           4 :     OUString input;
     204           2 :     osl::FileBase::getSystemPathFromFileURL(aTempInput.GetURL(), input);
     205             : 
     206           2 :     SvStream* pInputStream = aTempInput.GetStream(StreamMode::WRITE);
     207           2 :     sal_uInt64 nCount = pInputStream->Write(pBuf, nBytesRead);
     208           2 :     aTempInput.CloseStream();
     209             : 
     210           4 :     OUString fileName("pstoedit" EXESUFFIX);
     211             :     //fdo#64161 pstoedit under non-windows uses libEMF to output the EMF, but
     212             :     //libEMF cannot calculate the bounding box of text, so the overall bounding
     213             :     //box is not increased to include that of any text in the eps
     214             :     //
     215             :     //-drawbb will force pstoedit to draw a pair of pixels with the bg color to
     216             :     //the topleft and bottom right of the bounding box as pstoedit sees it,
     217             :     //which libEMF will then extend its bounding box to fit
     218             :     //
     219             :     //-usebbfrominput forces pstoedit to take the original ps bounding box
     220             :     //as the bounding box as it sees it, instead of calculating its own
     221             :     //which also doesn't work for this example
     222           4 :     OUString arg1("-usebbfrominput");   //-usebbfrominput use the original ps bounding box
     223           4 :     OUString arg2("-f");
     224           4 :     OUString arg3("emf:-OO -drawbb");   //-drawbb mark out the bounding box extent with bg pixels
     225             :     rtl_uString *args[] =
     226             :     {
     227             :         arg1.pData, arg2.pData, arg3.pData, input.pData, output.pData
     228           2 :     };
     229             :     oslProcess aProcess;
     230           2 :     oslFileHandle pIn = NULL;
     231           2 :     oslFileHandle pOut = NULL;
     232           2 :     oslFileHandle pErr = NULL;
     233             :         oslProcessError eErr = runProcessWithPathSearch(fileName,
     234           2 :             args, sizeof(args)/sizeof(rtl_uString *),
     235           2 :             &aProcess, &pIn, &pOut, &pErr);
     236             : 
     237           2 :     if (eErr!=osl_Process_E_None)
     238           2 :         return false;
     239             : 
     240           0 :     bool bRet = false;
     241           0 :     if (pIn) osl_closeFile(pIn);
     242           0 :     osl_joinProcess(aProcess);
     243           0 :     osl_freeProcessHandle(aProcess);
     244           0 :     bool bEMFSupported=true;
     245           0 :     if (pOut)
     246             :     {
     247           0 :         rtl::ByteSequence seq;
     248           0 :         if (osl_File_E_None == osl_readLine(pOut, reinterpret_cast<sal_Sequence **>(&seq)))
     249             :         {
     250           0 :             OString line( reinterpret_cast<const char *>(seq.getConstArray()), seq.getLength() );
     251           0 :             if (line.startsWith("Unsupported output format"))
     252           0 :                 bEMFSupported=false;
     253             :         }
     254           0 :         osl_closeFile(pOut);
     255             :     }
     256           0 :     if (pErr) osl_closeFile(pErr);
     257           0 :     if (nCount == nBytesRead && bEMFSupported)
     258             :     {
     259           0 :         SvFileStream aFile(output, StreamMode::READ);
     260           0 :         if (GraphicConverter::Import(aFile, rGraphic, ConvertDataFormat::EMF) == ERRCODE_NONE)
     261           0 :             bRet = true;
     262             :     }
     263             : 
     264           2 :     return bRet;
     265             : }
     266             : 
     267             : struct WriteData
     268             : {
     269             :     oslFileHandle   m_pFile;
     270             :     const sal_uInt8 *m_pBuf;
     271             :     sal_uInt32      m_nBytesToWrite;
     272             : };
     273             : 
     274             : extern "C" {
     275             : 
     276           3 : static void WriteFileInThread(void *wData)
     277             : {
     278             :     sal_uInt64 nCount;
     279           3 :     WriteData *wdata = static_cast<WriteData *>(wData);
     280           3 :     osl_writeFile(wdata->m_pFile, wdata->m_pBuf, wdata->m_nBytesToWrite, &nCount);
     281             :     // The number of bytes written does not matter.
     282             :     // The helper process may close its input stream before reading it all.
     283             :     // (e.g. at "showpage" in EPS)
     284             : 
     285             :     // File must be closed here.
     286             :     // Otherwise, the helper process may wait for the next input,
     287             :     // then its stdout is not closed and osl_readFile() blocks.
     288           3 :     if (wdata->m_pFile) osl_closeFile(wdata->m_pFile);
     289           3 : }
     290             : 
     291             : }
     292             : 
     293           3 : static bool RenderAsBMPThroughHelper(const sal_uInt8* pBuf, sal_uInt32 nBytesRead,
     294             :     Graphic &rGraphic, OUString &rProgName, rtl_uString *pArgs[], size_t nArgs)
     295             : {
     296             :     oslProcess aProcess;
     297           3 :     oslFileHandle pIn = NULL;
     298           3 :     oslFileHandle pOut = NULL;
     299           3 :     oslFileHandle pErr = NULL;
     300             :         oslProcessError eErr = runProcessWithPathSearch(rProgName,
     301             :             pArgs, nArgs,
     302           3 :             &aProcess, &pIn, &pOut, &pErr);
     303           3 :     if (eErr!=osl_Process_E_None)
     304           0 :         return false;
     305             : 
     306             :     WriteData Data;
     307           3 :     Data.m_pFile = pIn;
     308           3 :     Data.m_pBuf = pBuf;
     309           3 :     Data.m_nBytesToWrite = nBytesRead;
     310           3 :     oslThread hThread = osl_createThread(WriteFileInThread, &Data);
     311             : 
     312           3 :     bool bRet = false;
     313             :     sal_uInt64 nCount;
     314             :     {
     315           3 :         SvMemoryStream aMemStm;
     316             :         sal_uInt8 aBuf[32000];
     317           3 :         oslFileError eFileErr = osl_readFile(pOut, aBuf, 32000, &nCount);
     318        1981 :         while (eFileErr == osl_File_E_None && nCount)
     319             :         {
     320        1975 :             aMemStm.Write(aBuf, sal::static_int_cast< sal_Size >(nCount));
     321        1975 :             eFileErr = osl_readFile(pOut, aBuf, 32000, &nCount);
     322             :         }
     323             : 
     324           3 :         aMemStm.Seek(0);
     325           3 :         if (
     326           6 :             aMemStm.GetEndOfData() &&
     327           3 :             GraphicConverter::Import(aMemStm, rGraphic, ConvertDataFormat::BMP) == ERRCODE_NONE
     328             :            )
     329             :         {
     330           1 :             MakeAsMeta(rGraphic);
     331           1 :             bRet = true;
     332           3 :         }
     333             :     }
     334           3 :     if (pOut) osl_closeFile(pOut);
     335           3 :     if (pErr) osl_closeFile(pErr);
     336           3 :     osl_joinProcess(aProcess);
     337           3 :     osl_freeProcessHandle(aProcess);
     338           3 :     osl_joinWithThread(hThread);
     339           3 :     osl_destroyThread(hThread);
     340           3 :     return bRet;
     341             : }
     342             : 
     343           1 : static bool RenderAsBMPThroughConvert(const sal_uInt8* pBuf, sal_uInt32 nBytesRead,
     344             :     Graphic &rGraphic)
     345             : {
     346           1 :     OUString fileName("convert" EXESUFFIX);
     347             :     // density in pixel/inch
     348           2 :     OUString arg1("-density");
     349             :     // since the preview is also used for PDF-Export & printing on non-PS-printers,
     350             :     // use some better quality - 300x300 should allow some resizing as well
     351           2 :     OUString arg2("300x300");
     352             :     // read eps from STDIN
     353           2 :     OUString arg3("eps:-");
     354             :     // write bmp to STDOUT
     355           2 :     OUString arg4("bmp:-");
     356             :     rtl_uString *args[] =
     357             :     {
     358             :         arg1.pData, arg2.pData, arg3.pData, arg4.pData
     359           1 :     };
     360             :     return RenderAsBMPThroughHelper(pBuf, nBytesRead, rGraphic, fileName, args,
     361           2 :         sizeof(args)/sizeof(rtl_uString *));
     362             : }
     363             : 
     364           2 : static bool RenderAsBMPThroughGS(const sal_uInt8* pBuf, sal_uInt32 nBytesRead,
     365             :     Graphic &rGraphic)
     366             : {
     367             : #ifdef WNT
     368             :     OUString fileName("gswin32c" EXESUFFIX);
     369             : #else
     370           2 :     OUString fileName("gs" EXESUFFIX);
     371             : #endif
     372           4 :     OUString arg1("-q");
     373           4 :     OUString arg2("-dBATCH");
     374           4 :     OUString arg3("-dNOPAUSE");
     375           4 :     OUString arg4("-dPARANOIDSAFER");
     376           4 :     OUString arg5("-dEPSCrop");
     377           4 :     OUString arg6("-dTextAlphaBits=4");
     378           4 :     OUString arg7("-dGraphicsAlphaBits=4");
     379           4 :     OUString arg8("-r300x300");
     380           4 :     OUString arg9("-sDEVICE=bmp16m");
     381           4 :     OUString arg10("-sOutputFile=-");
     382           4 :     OUString arg11("-");
     383             :     rtl_uString *args[] =
     384             :     {
     385             :         arg1.pData, arg2.pData, arg3.pData, arg4.pData, arg5.pData,
     386             :         arg6.pData, arg7.pData, arg8.pData, arg9.pData, arg10.pData,
     387             :         arg11.pData
     388           2 :     };
     389             :     return RenderAsBMPThroughHelper(pBuf, nBytesRead, rGraphic, fileName, args,
     390           4 :         sizeof(args)/sizeof(rtl_uString *));
     391             : }
     392             : 
     393           2 : static bool RenderAsBMP(const sal_uInt8* pBuf, sal_uInt32 nBytesRead, Graphic &rGraphic)
     394             : {
     395           2 :     if (RenderAsBMPThroughGS(pBuf, nBytesRead, rGraphic))
     396           1 :         return true;
     397             :     else
     398           1 :         return RenderAsBMPThroughConvert(pBuf, nBytesRead, rGraphic);
     399             : }
     400             : 
     401             : // this method adds a replacement action containing the original wmf or tiff replacement,
     402             : // so the original eps can be written when storing to ODF.
     403           2 : void CreateMtfReplacementAction( GDIMetaFile& rMtf, SvStream& rStrm, sal_uInt32 nOrigPos, sal_uInt32 nPSSize,
     404             :                                 sal_uInt32 nPosWMF, sal_uInt32 nSizeWMF, sal_uInt32 nPosTIFF, sal_uInt32 nSizeTIFF )
     405             : {
     406           2 :     OString aComment("EPSReplacementGraphic");
     407           2 :     if ( nSizeWMF || nSizeTIFF )
     408             :     {
     409           0 :         SvMemoryStream aReplacement( nSizeWMF + nSizeTIFF + 28 );
     410           0 :         sal_uInt32 nMagic = 0xc6d3d0c5;
     411           0 :         sal_uInt32 nPPos = 28 + nSizeWMF + nSizeTIFF;
     412           0 :         sal_uInt32 nWPos = nSizeWMF ? 28 : 0;
     413           0 :         sal_uInt32 nTPos = nSizeTIFF ? 28 + nSizeWMF : 0;
     414             : 
     415           0 :         aReplacement.WriteUInt32( nMagic ).WriteUInt32( nPPos ).WriteUInt32( nPSSize )
     416           0 :                     .WriteUInt32( nWPos ).WriteUInt32( nSizeWMF )
     417           0 :                     .WriteUInt32( nTPos ).WriteUInt32( nSizeTIFF );
     418           0 :         if ( nSizeWMF )
     419             :         {
     420           0 :             boost::scoped_array<sal_uInt8> pBuf(new sal_uInt8[ nSizeWMF ]);
     421           0 :             rStrm.Seek( nOrigPos + nPosWMF );
     422           0 :             rStrm.Read( pBuf.get(), nSizeWMF );
     423           0 :             aReplacement.Write( pBuf.get(), nSizeWMF );
     424             :         }
     425           0 :         if ( nSizeTIFF )
     426             :         {
     427           0 :             boost::scoped_array<sal_uInt8> pBuf(new sal_uInt8[ nSizeTIFF ]);
     428           0 :             rStrm.Seek( nOrigPos + nPosTIFF );
     429           0 :             rStrm.Read( pBuf.get(), nSizeTIFF );
     430           0 :             aReplacement.Write( pBuf.get(), nSizeTIFF );
     431             :         }
     432           0 :         rMtf.AddAction( static_cast<MetaAction*>( new MetaCommentAction( aComment, 0, static_cast<const sal_uInt8*>(aReplacement.GetData()), aReplacement.Tell() ) ) );
     433             :     }
     434             :     else
     435           2 :         rMtf.AddAction( static_cast<MetaAction*>( new MetaCommentAction( aComment, 0, NULL, 0 ) ) );
     436           2 : }
     437             : 
     438             : //there is no preview -> make a red box
     439           1 : void MakePreview(sal_uInt8* pBuf, sal_uInt32 nBytesRead,
     440             :     long nWidth, long nHeight, Graphic &rGraphic)
     441             : {
     442           1 :     GDIMetaFile aMtf;
     443           2 :     ScopedVclPtrInstance< VirtualDevice > pVDev;
     444           2 :     vcl::Font       aFont;
     445             : 
     446           1 :     pVDev->EnableOutput( false );
     447           1 :     aMtf.Record( pVDev );
     448           1 :     pVDev->SetLineColor( Color( COL_RED ) );
     449           1 :     pVDev->SetFillColor();
     450             : 
     451           1 :     aFont.SetColor( COL_LIGHTRED );
     452             : //  aFont.SetSize( Size( 0, 32 ) );
     453             : 
     454           1 :     pVDev->Push( PushFlags::FONT );
     455           1 :     pVDev->SetFont( aFont );
     456             : 
     457           1 :     Rectangle aRect( Point( 1, 1 ), Size( nWidth - 2, nHeight - 2 ) );
     458           1 :     pVDev->DrawRect( aRect );
     459             : 
     460           2 :     OUString aString;
     461             :     int nLen;
     462           1 :     sal_uInt8* pDest = ImplSearchEntry( pBuf, reinterpret_cast<sal_uInt8 const *>("%%Title:"), nBytesRead - 32, 8 );
     463           1 :     if ( pDest )
     464             :     {
     465           1 :         pDest += 8;
     466           1 :         if ( *pDest == ' ' )
     467           1 :             pDest++;
     468           1 :         nLen = ImplGetLen( pDest, 32 );
     469           1 :         sal_uInt8 aOldValue(pDest[ nLen ]); pDest[ nLen ] = 0;
     470           1 :         if ( strcmp( reinterpret_cast<char*>(pDest), "none" ) != 0 )
     471             :         {
     472           1 :             aString += " Title:" + OUString::createFromAscii( reinterpret_cast<char*>(pDest) ) + "\n";
     473             :         }
     474           1 :         pDest[ nLen ] = aOldValue;
     475             :     }
     476           1 :     pDest = ImplSearchEntry( pBuf, reinterpret_cast<sal_uInt8 const *>("%%Creator:"), nBytesRead - 32, 10 );
     477           1 :     if ( pDest )
     478             :     {
     479           1 :         pDest += 10;
     480           1 :         if ( *pDest == ' ' )
     481           1 :             pDest++;
     482           1 :         nLen = ImplGetLen( pDest, 32 );
     483           1 :         sal_uInt8 aOldValue(pDest[ nLen ]); pDest[ nLen ] = 0;
     484           1 :         aString += " Creator:" + OUString::createFromAscii( reinterpret_cast<char*>(pDest) ) + "\n";
     485           1 :         pDest[ nLen ] = aOldValue;
     486             :     }
     487           1 :     pDest = ImplSearchEntry( pBuf, reinterpret_cast<sal_uInt8 const *>("%%CreationDate:"), nBytesRead - 32, 15 );
     488           1 :     if ( pDest )
     489             :     {
     490           1 :         pDest += 15;
     491           1 :         if ( *pDest == ' ' )
     492           1 :             pDest++;
     493           1 :         nLen = ImplGetLen( pDest, 32 );
     494           1 :         sal_uInt8 aOldValue(pDest[ nLen ]); pDest[ nLen ] = 0;
     495           1 :         if ( strcmp( reinterpret_cast<char*>(pDest), "none" ) != 0 )
     496             :         {
     497           1 :             aString += " CreationDate:" + OUString::createFromAscii( reinterpret_cast<char*>(pDest) ) + "\n";
     498             :         }
     499           1 :         pDest[ nLen ] = aOldValue;
     500             :     }
     501           1 :     pDest = ImplSearchEntry( pBuf, reinterpret_cast<sal_uInt8 const *>("%%LanguageLevel:"), nBytesRead - 4, 16 );
     502           1 :     if ( pDest )
     503             :     {
     504           0 :         pDest += 16;
     505           0 :         int nCount = 4;
     506           0 :         long nNumber = ImplGetNumber( &pDest, nCount );
     507           0 :         if ( nCount && ( (sal_uInt32)nNumber < 10 ) )
     508             :         {
     509           0 :             aString += " LanguageLevel:" + OUString::number( nNumber );
     510             :         }
     511             :     }
     512           1 :     pVDev->DrawText( aRect, aString, DrawTextFlags::Clip | DrawTextFlags::MultiLine );
     513           1 :     pVDev->Pop();
     514           1 :     aMtf.Stop();
     515           1 :     aMtf.WindStart();
     516           1 :     aMtf.SetPrefMapMode( MAP_POINT );
     517           1 :     aMtf.SetPrefSize( Size( nWidth, nHeight ) );
     518           2 :     rGraphic = aMtf;
     519           1 : }
     520             : 
     521             : 
     522             : //================== GraphicImport - the exported function ================
     523             : 
     524             : // this needs to be kept in sync with
     525             : // ImpFilterLibCacheEntry::GetImportFunction() from
     526             : // vcl/source/filter/graphicfilter.cxx
     527             : #if defined(DISABLE_DYNLOADING)
     528             : #define GraphicImport ipsGraphicImport
     529             : #endif
     530             : 
     531             : extern "C" SAL_DLLPUBLIC_EXPORT bool SAL_CALL
     532           3 : GraphicImport( SvStream & rStream, Graphic & rGraphic, FilterConfigItem* )
     533             : {
     534           3 :     if ( rStream.GetError() )
     535           0 :         return false;
     536             : 
     537           3 :     Graphic     aGraphic;
     538           3 :     bool    bRetValue = false;
     539           3 :     bool    bHasPreview = false;
     540             :     sal_uInt32  nSignature, nPSStreamPos, nPSSize;
     541           3 :     sal_uInt32  nSizeWMF = 0;
     542           3 :     sal_uInt32  nPosWMF = 0;
     543           3 :     sal_uInt32  nSizeTIFF = 0;
     544           3 :     sal_uInt32  nPosTIFF = 0;
     545           3 :     sal_uInt32  nOrigPos = nPSStreamPos = rStream.Tell();
     546           3 :     SvStreamEndian nOldFormat = rStream.GetEndian();
     547           3 :     rStream.SetEndian( SvStreamEndian::LITTLE );
     548           3 :     rStream.ReadUInt32( nSignature );
     549           3 :     if ( nSignature == 0xc6d3d0c5 )
     550             :     {
     551           1 :         rStream.ReadUInt32( nPSStreamPos ).ReadUInt32( nPSSize ).ReadUInt32( nPosWMF ).ReadUInt32( nSizeWMF );
     552             : 
     553             :         // first we try to get the metafile grafix
     554             : 
     555           1 :         if ( nSizeWMF )
     556             :         {
     557           0 :             if ( nPosWMF != 0 )
     558             :             {
     559           0 :                 rStream.Seek( nOrigPos + nPosWMF );
     560           0 :                 if ( GraphicConverter::Import( rStream, aGraphic, ConvertDataFormat::WMF ) == ERRCODE_NONE )
     561           0 :                     bHasPreview = bRetValue = true;
     562             :             }
     563             :         }
     564             :         else
     565             :         {
     566           1 :             rStream.ReadUInt32( nPosTIFF ).ReadUInt32( nSizeTIFF );
     567             : 
     568             :             // else we have to get the tiff grafix
     569             : 
     570           1 :             if ( nPosTIFF && nSizeTIFF )
     571             :             {
     572           1 :                 rStream.Seek( nOrigPos + nPosTIFF );
     573           1 :                 if ( GraphicConverter::Import( rStream, aGraphic, ConvertDataFormat::TIF ) == ERRCODE_NONE )
     574             :                 {
     575           0 :                     MakeAsMeta(aGraphic);
     576           0 :                     rStream.Seek( nOrigPos + nPosTIFF );
     577           0 :                     bHasPreview = bRetValue = true;
     578             :                 }
     579             :             }
     580             :         }
     581             :     }
     582             :     else
     583             :     {
     584           2 :         nPSStreamPos = nOrigPos;            // no preview available _>so we must get the size manually
     585           2 :         nPSSize = rStream.Seek( STREAM_SEEK_TO_END ) - nOrigPos;
     586             :     }
     587           3 :     sal_uInt8* pHeader = new sal_uInt8[ 22 ];
     588           3 :     rStream.Seek( nPSStreamPos );
     589           3 :     rStream.Read( pHeader, 22 );    // check PostScript header
     590           6 :     if ( ImplSearchEntry( pHeader, reinterpret_cast<sal_uInt8 const *>("%!PS-Adobe"), 10, 10 ) &&
     591           3 :         ImplSearchEntry( &pHeader[ 15 ], reinterpret_cast<sal_uInt8 const *>("EPS"), 3, 3 ) )
     592             :     {
     593           3 :         bool bGraphicLinkCreated = false;
     594             : 
     595           3 :         rStream.Seek( nPSStreamPos );
     596           3 :         sal_uInt8* pBuf = new sal_uInt8[ nPSSize ];
     597             : 
     598           3 :         sal_uInt32  nBufStartPos = rStream.Tell();
     599           3 :         sal_uInt32  nBytesRead = rStream.Read( pBuf, nPSSize );
     600           3 :         if ( nBytesRead == nPSSize )
     601             :         {
     602           2 :             int nSecurityCount = 32;
     603           2 :             if ( !bHasPreview )     // if there is no tiff/wmf preview, we will parse for an preview in the eps prolog
     604             :             {
     605           2 :                 sal_uInt8* pDest = ImplSearchEntry( pBuf, reinterpret_cast<sal_uInt8 const *>("%%BeginPreview:"), nBytesRead - 32, 15 );
     606           2 :                 if ( pDest  )
     607             :                 {
     608           0 :                     pDest += 15;
     609           0 :                     long nWidth = ImplGetNumber( &pDest, nSecurityCount );
     610           0 :                     long nHeight = ImplGetNumber( &pDest, nSecurityCount );
     611           0 :                     long nBitDepth = ImplGetNumber( &pDest, nSecurityCount );
     612           0 :                     long nScanLines = ImplGetNumber( &pDest, nSecurityCount );
     613           0 :                     pDest = ImplSearchEntry( pDest, reinterpret_cast<sal_uInt8 const *>("%"), 16, 1 );       // go to the first Scanline
     614           0 :                     if ( nSecurityCount && pDest && nWidth && nHeight && ( ( nBitDepth == 1 ) || ( nBitDepth == 8 ) ) && nScanLines )
     615             :                     {
     616           0 :                         rStream.Seek( nBufStartPos + ( pDest - pBuf ) );
     617             : 
     618           0 :                         Bitmap aBitmap( Size( nWidth, nHeight ), 1 );
     619           0 :                         BitmapWriteAccess* pAcc = aBitmap.AcquireWriteAccess();
     620           0 :                         if ( pAcc )
     621             :                         {
     622           0 :                             bool bIsValid = true;
     623           0 :                             sal_uInt8 nDat = 0;
     624             :                             char nByte;
     625           0 :                             for ( long y = 0; bIsValid && ( y < nHeight ); y++ )
     626             :                             {
     627           0 :                                 int nBitsLeft = 0;
     628           0 :                                 for ( long x = 0; x < nWidth; x++ )
     629             :                                 {
     630           0 :                                     if ( --nBitsLeft < 0 )
     631             :                                     {
     632           0 :                                         while ( bIsValid && ( nBitsLeft != 7 ) )
     633             :                                         {
     634           0 :                                             rStream.ReadChar( nByte );
     635           0 :                                             switch ( nByte )
     636             :                                             {
     637             :                                                 case 0x0a :
     638           0 :                                                     if ( --nScanLines < 0 )
     639           0 :                                                         bIsValid = false;
     640             :                                                 case 0x09 :
     641             :                                                 case 0x0d :
     642             :                                                 case 0x20 :
     643             :                                                 case 0x25 :
     644           0 :                                                 break;
     645             :                                                 default:
     646             :                                                 {
     647           0 :                                                     if ( nByte >= '0' )
     648             :                                                     {
     649           0 :                                                         if ( nByte > '9' )
     650             :                                                         {
     651           0 :                                                             nByte &=~0x20;  // case none sensitive for hexadecimal values
     652           0 :                                                             nByte -= ( 'A' - 10 );
     653           0 :                                                             if ( nByte > 15 )
     654           0 :                                                                 bIsValid = false;
     655             :                                                         }
     656             :                                                         else
     657           0 :                                                             nByte -= '0';
     658           0 :                                                         nBitsLeft += 4;
     659           0 :                                                         nDat <<= 4;
     660           0 :                                                         nDat |= ( nByte ^ 0xf ); // in epsi a zero bit represents white color
     661             :                                                     }
     662             :                                                     else
     663           0 :                                                         bIsValid = false;
     664             :                                                 }
     665           0 :                                                 break;
     666             :                                             }
     667             :                                         }
     668             :                                     }
     669           0 :                                     if ( nBitDepth == 1 )
     670           0 :                                         pAcc->SetPixelIndex( y, x, static_cast<sal_uInt8>(nDat >> nBitsLeft) & 1 );
     671             :                                     else
     672             :                                     {
     673           0 :                                         pAcc->SetPixelIndex( y, x, nDat ? 1 : 0 );  // nBitDepth == 8
     674           0 :                                         nBitsLeft = 0;
     675             :                                     }
     676             :                                 }
     677             :                             }
     678           0 :                             if ( bIsValid )
     679             :                             {
     680           0 :                                 ScopedVclPtrInstance<VirtualDevice> pVDev;
     681           0 :                                 GDIMetaFile     aMtf;
     682           0 :                                 Size            aSize;
     683           0 :                                 pVDev->EnableOutput( false );
     684           0 :                                 aMtf.Record( pVDev );
     685           0 :                                 aSize = aBitmap.GetPrefSize();
     686           0 :                                 if( !aSize.Width() || !aSize.Height() )
     687           0 :                                     aSize = Application::GetDefaultDevice()->PixelToLogic( aBitmap.GetSizePixel(), MAP_100TH_MM );
     688             :                                 else
     689           0 :                                     aSize = OutputDevice::LogicToLogic( aSize, aBitmap.GetPrefMapMode(), MAP_100TH_MM );
     690           0 :                                 pVDev->DrawBitmap( Point(), aSize, aBitmap );
     691           0 :                                 aMtf.Stop();
     692           0 :                                 aMtf.WindStart();
     693           0 :                                 aMtf.SetPrefMapMode( MAP_100TH_MM );
     694           0 :                                 aMtf.SetPrefSize( aSize );
     695           0 :                                 aGraphic = aMtf;
     696           0 :                                 bHasPreview = bRetValue = true;
     697             :                             }
     698           0 :                             Bitmap::ReleaseAccess( pAcc );
     699           0 :                         }
     700             :                     }
     701             :                 }
     702             :             }
     703             : 
     704           2 :             sal_uInt8* pDest = ImplSearchEntry( pBuf, reinterpret_cast<sal_uInt8 const *>("%%BoundingBox:"), nBytesRead, 14 );
     705           2 :             if ( pDest )
     706             :             {
     707           2 :                 nSecurityCount = 100;
     708             :                 long nNumb[4];
     709           2 :                 nNumb[0] = nNumb[1] = nNumb[2] = nNumb[3] = 0;
     710           2 :                 pDest += 14;
     711          10 :                 for ( int i = 0; ( i < 4 ) && nSecurityCount; i++ )
     712             :                 {
     713           8 :                     nNumb[ i ] = ImplGetNumber( &pDest, nSecurityCount );
     714             :                 }
     715           2 :                 if ( nSecurityCount)
     716             :                 {
     717           2 :                     bGraphicLinkCreated = true;
     718           2 :                     GfxLink     aGfxLink( pBuf, nPSSize, GFX_LINK_TYPE_EPS_BUFFER, true ) ;
     719           4 :                     GDIMetaFile aMtf;
     720             : 
     721           2 :                     long nWidth =  nNumb[2] - nNumb[0] + 1;
     722           2 :                     long nHeight = nNumb[3] - nNumb[1] + 1;
     723             : 
     724             :                     // if there is no preview -> try with gs to make one
     725           2 :                     if( !bHasPreview )
     726             :                     {
     727           2 :                         bHasPreview = RenderAsEMF(pBuf, nBytesRead, aGraphic);
     728           2 :                         if (!bHasPreview)
     729           2 :                             bHasPreview = RenderAsBMP(pBuf, nBytesRead, aGraphic);
     730             :                     }
     731             : 
     732             :                     // if there is no preview -> make a red box
     733           2 :                     if( !bHasPreview )
     734             :                     {
     735             :                         MakePreview(pBuf, nBytesRead, nWidth, nHeight,
     736           1 :                             aGraphic);
     737             :                     }
     738             : 
     739             :                     aMtf.AddAction( static_cast<MetaAction*>( new MetaEPSAction( Point(), Size( nWidth, nHeight ),
     740           2 :                                                                       aGfxLink, aGraphic.GetGDIMetaFile() ) ) );
     741           2 :                     CreateMtfReplacementAction( aMtf, rStream, nOrigPos, nPSSize, nPosWMF, nSizeWMF, nPosTIFF, nSizeTIFF );
     742           2 :                     aMtf.WindStart();
     743           2 :                     aMtf.SetPrefMapMode( MAP_POINT );
     744           2 :                     aMtf.SetPrefSize( Size( nWidth, nHeight ) );
     745           2 :                     rGraphic = aMtf;
     746           4 :                     bRetValue = true;
     747             :                 }
     748             :             }
     749             :         }
     750             : 
     751           3 :         if ( !bGraphicLinkCreated )
     752           1 :             delete[] pBuf;
     753             :     }
     754           3 :     delete[] pHeader;
     755           3 :     rStream.SetEndian(nOldFormat);
     756           3 :     rStream.Seek( nOrigPos );
     757           3 :     return bRetValue;
     758             : }
     759             : 
     760             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11