00001 
00002 #include <unistd.h>
00003 #include <stdio.h>
00004 #include <qimage.h>
00005 #include <qfile.h>
00006 #include <qpainter.h>
00007 #include <qprinter.h>
00008 #include <kapplication.h>
00009 #include <ktempfile.h>
00010 #include <kdebug.h>
00011 #include "eps.h"
00012 
00013 #define BUFLEN 200
00014 
00015 #define BBOX "%%BoundingBox:"
00016 #define BBOX_LEN strlen(BBOX)
00017 
00018 static bool seekToCodeStart( QIODevice * io, Q_UINT32 & ps_offset, Q_UINT32 & ps_size )
00019 {
00020     char buf[4]; 
00021     ps_offset=0L;
00022     ps_size=0L;
00023 
00024     if ( io->readBlock(buf, 2)!=2 ) 
00025     {
00026         kdError(399) << "kimgio EPS: EPS file has less than 2 bytes." << endl;
00027         return false;
00028     }
00029 
00030     if ( buf[0]=='%' && buf[1]=='!' ) 
00031     {
00032         kdDebug(399) << "kimgio EPS: normal EPS file" << endl;
00033     }
00034     else if ( buf[0]==char(0xc5) && buf[1]==char(0xd0) ) 
00035     {   
00036         if ( io->readBlock(buf+2, 2)!=2 ) 
00037         {
00038             kdError(399) << "kimgio EPS: potential MS-DOS EPS file has less than 4 bytes." << endl;
00039             return false;
00040         }
00041         if ( buf[2]==char(0xd3) && buf[3]==char(0xc6) ) 
00042         {
00043             if (io->readBlock(buf, 4)!=4) 
00044             {
00045                 kdError(399) << "kimgio EPS: cannot read offset of MS-DOS EPS file" << endl;
00046                 return false;
00047             }
00048             ps_offset 
00049                 = ((unsigned char) buf[0])
00050                 + ((unsigned char) buf[1] << 8)
00051                 + ((unsigned char) buf[2] << 16)
00052                 + ((unsigned char) buf[3] << 24);
00053             if (io->readBlock(buf, 4)!=4) 
00054             {
00055                 kdError(399) << "kimgio EPS: cannot read size of MS-DOS EPS file" << endl;
00056                 return false;
00057             }
00058             ps_size 
00059                 = ((unsigned char) buf[0])
00060                 + ((unsigned char) buf[1] << 8)
00061                 + ((unsigned char) buf[2] << 16)
00062                 + ((unsigned char) buf[3] << 24);
00063             kdDebug(399) << "kimgio EPS: Offset: " << ps_offset <<" Size: " << ps_size << endl;
00064             if ( !io->at(ps_offset) ) 
00065             {
00066                 kdError(399) << "kimgio EPS: cannot seek in MS-DOS EPS file" << endl;
00067                 return false;
00068             }
00069             if ( io->readBlock(buf, 2)!=2 ) 
00070             {
00071                 kdError(399) << "kimgio EPS: PostScript code has less than 2 bytes." << endl;
00072                 return false;
00073             }
00074             if ( buf[0]=='%' && buf[1]=='!' ) 
00075             {
00076                 kdDebug(399) << "kimgio EPS: MS-DOS EPS file" << endl;
00077             }
00078             else
00079             {
00080                 kdError(399) << "kimgio EPS: supposed Postscript code of a MS-DOS EPS file doe not start with %!." << endl;
00081                 return false;
00082             }
00083         }
00084         else
00085         {
00086             kdError(399) << "kimgio EPS: wrong magic for potential MS-DOS EPS file!" << endl;
00087             return false;
00088         }
00089     }
00090     else
00091     {
00092         kdError(399) << "kimgio EPS: not an EPS file!" << endl;
00093         return false;
00094     }
00095     return true;
00096 }
00097 
00098 static bool bbox ( QIODevice *io, int *x1, int *y1, int *x2, int *y2)
00099 {
00100         char buf[BUFLEN+1];
00101 
00102         bool ret = false;
00103 
00104         while (io->readLine(buf, BUFLEN) > 0)
00105         {
00106                 if (strncmp (buf, BBOX, BBOX_LEN) == 0)
00107                 {
00108                         
00109                         
00110                         float _x1, _y1, _x2, _y2;
00111                         if ( sscanf (buf, "%*s %f %f %f %f",
00112                                 &_x1, &_y1, &_x2, &_y2) == 4) {
00113                                 kdDebug(399) << "kimgio EPS BBOX: " << _x1 << " " << _y1 << " " << _x2 << " " << _y2 << endl;
00114                                 *x1=(int)_x1; *y1=(int)_y1; *x2=(int)_x2; *y2=(int)_y2;
00115                                 ret = true;
00116                                 break;
00117                         }
00118                 }
00119         }
00120 
00121         return ret;
00122 }
00123 
00124 KDE_EXPORT void kimgio_eps_read (QImageIO *image)
00125 {
00126         kdDebug(399) << "kimgio EPS: starting..." << endl;
00127 
00128         FILE * ghostfd;
00129         int x1, y1, x2, y2;
00130         
00131         
00132 
00133         QString cmdBuf;
00134         QString tmp;
00135 
00136         QIODevice* io = image->ioDevice();
00137         Q_UINT32 ps_offset, ps_size;
00138 
00139         
00140         if ( !seekToCodeStart(io, ps_offset, ps_size) )
00141             return;
00142 
00143         
00144         if ( !bbox (io, &x1, &y1, &x2, &y2)) {
00145             kdError(399) << "kimgio EPS: no bounding box found!" << endl;
00146             return;
00147         }
00148 
00149         KTempFile tmpFile;
00150         tmpFile.setAutoDelete(true);
00151 
00152         if( tmpFile.status() != 0 ) {
00153             kdError(399) << "kimgio EPS: no temp file!" << endl;
00154             return;
00155         }
00156         tmpFile.close(); 
00157 
00158         
00159         
00160 
00161         x2 -= x1;
00162         y2 -= y1;
00163         
00164         double xScale = 1.0;
00165         double yScale = 1.0;
00166     bool needsScaling = false;
00167         int wantedWidth = x2;
00168         int wantedHeight = y2;
00169 
00170         if (image->parameters())
00171         {
00172             
00173             QStringList params = QStringList::split(':', image->parameters());
00174             if (params.count() >= 2 && x2 != 0.0 && y2 != 0.0)
00175             {
00176                 wantedWidth = params[0].toInt();
00177                 xScale = (double)wantedWidth / (double)x2;
00178                 wantedHeight = params[1].toInt();
00179                 yScale = (double)wantedHeight / (double)y2;
00180                 
00181                 
00182         needsScaling = true;
00183             }
00184         }
00185 
00186         
00187 
00188         cmdBuf = "gs -sOutputFile=";
00189         cmdBuf += tmpFile.name();
00190         cmdBuf += " -q -g";
00191         tmp.setNum( wantedWidth );
00192         cmdBuf += tmp;
00193         tmp.setNum( wantedHeight );
00194         cmdBuf += "x";
00195         cmdBuf += tmp;
00196         cmdBuf += " -dSAFER -dPARANOIDSAFER -dNOPAUSE -sDEVICE=ppm -c "
00197                 "0 0 moveto "
00198                 "1000 0 lineto "
00199                 "1000 1000 lineto "
00200                 "0 1000 lineto "
00201                 "1 1 254 255 div setrgbcolor fill "
00202                 "0 0 0 setrgbcolor - -c showpage quit";
00203 
00204         
00205 
00206         ghostfd = popen (QFile::encodeName(cmdBuf), "w");
00207 
00208         if ( ghostfd == 0 ) {
00209             kdError(399) << "kimgio EPS: no GhostScript?" << endl;
00210             return;
00211         }
00212 
00213         fprintf (ghostfd, "\n%d %d translate\n", -qRound(x1*xScale), -qRound(y1*yScale));
00214         if ( needsScaling )
00215             fprintf (ghostfd, "%g %g scale\n", xScale, yScale);
00216 
00217         
00218 
00219         io->reset(); 
00220         if (ps_offset>0L) 
00221               io->at(ps_offset);
00222         QByteArray buffer ( io->readAll() );
00223 
00224         
00225         if (ps_size<=0L || ps_size>buffer.size())
00226             ps_size=buffer.size();
00227 
00228         fwrite(buffer.data(), sizeof(char), ps_size, ghostfd);
00229         buffer.resize(0);
00230 
00231         pclose ( ghostfd );
00232 
00233         
00234         QImage myimage;
00235         if( myimage.load (tmpFile.name()) ) {
00236                 image->setImage (myimage);
00237                 image->setStatus (0);
00238                 kdDebug(399) << "kimgio EPS: success!" << endl;
00239         }
00240         else
00241             kdError(399) << "kimgio EPS: no image!" << endl;
00242 
00243         
00244         return;
00245 }
00246 
00247 
00248 KDE_EXPORT void kimgio_eps_write( QImageIO *imageio )
00249 {
00250   QPrinter psOut(QPrinter::PrinterResolution);
00251   QPainter p;
00252 
00253   
00254   psOut.setCreator( "KDE " KDE_VERSION_STRING  );
00255   psOut.setOutputToFile( true );
00256 
00257   
00258   KTempFile tmpFile(QString::null, ".eps");
00259   tmpFile.setAutoDelete(true);
00260   if ( tmpFile.status() != 0)
00261      return;
00262   tmpFile.close(); 
00263 
00264   psOut.setOutputFileName(tmpFile.name());
00265   psOut.setFullPage(true);
00266 
00267   
00268   p.begin( &psOut );
00269   
00270   p.setClipRect( 0, 0, imageio->image().width(), imageio->image().height(), QPainter::CoordPainter);
00271   p.drawImage( QPoint( 0, 0 ), imageio->image() );
00272   p.end();
00273 
00274   
00275   QFile inFile(tmpFile.name());
00276   inFile.open( IO_ReadOnly );
00277 
00278   QTextStream in( &inFile );
00279   in.setEncoding( QTextStream::Latin1 );
00280   QTextStream out( imageio->ioDevice() );
00281   out.setEncoding( QTextStream::Latin1 );
00282 
00283   QString szInLine = in.readLine();
00284   out << szInLine << '\n';
00285 
00286   while( !in.atEnd() ){
00287     szInLine = in.readLine();
00288     out << szInLine << '\n';
00289   }
00290 
00291   inFile.close();
00292 
00293   imageio->setStatus(0);
00294 }