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 }