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

Generated by: LCOV version 1.10