26#include <tqpaintdevicemetrics.h>
28#include <tqtextstream.h>
32#include <tqapplication.h>
33#include <tqdragobject.h>
37#include <tdetempfile.h>
40#include "KoPictureKey.h"
41#include "KoPictureBase.h"
42#include "KoPictureEps.h"
45KoPictureEps::KoPictureEps(
void) : m_psStreamStart(0), m_psStreamLength(0), m_cacheIsInFastMode(true)
48 m_cachedPixmap.setOptimization(TQPixmap::MemoryOptim);
51KoPictureEps::~KoPictureEps(
void)
55KoPictureBase* KoPictureEps::newCopy(
void)
const
57 return new KoPictureEps(*
this);
60KoPictureType::Type KoPictureEps::getType(
void)
const
62 return KoPictureType::TypeEps;
65bool KoPictureEps::isNull(
void)
const
67 return m_rawData.isNull();
70TQImage KoPictureEps::scaleWithGhostScript(
const TQSize& size,
const int resolutionx,
const int resolutiony )
72 if (!m_boundingBox.width() || !m_boundingBox.height())
74 kdDebug(30003) <<
"EPS image has a null size! (in KoPictureEps::scaleWithGhostScript)" << endl;
83 const char* deviceTable[] = {
"png16m",
"bmp16m",
"ppm", 0 };
87 for (
int i = 0; deviceTable[i]; ++i)
89 if ( tryScaleWithGhostScript( img, size, resolutionx, resolutiony, deviceTable[i] ) != -1 )
96 kdError(30003) <<
"Image from GhostScript cannot be loaded (in KoPictureEps::scaleWithGhostScript)" << endl;
102int KoPictureEps::tryScaleWithGhostScript(TQImage &image,
const TQSize& size,
const int resolutionx,
const int resolutiony,
const char* device )
105 kdDebug(30003) <<
"Sampling with GhostScript, using device \"" << device <<
"\" (in KoPictureEps::tryScaleWithGhostScript)" << endl;
108 tmpFile.setAutoDelete(
true);
110 if ( tmpFile.status() )
112 kdError(30003) <<
"No KTempFile! (in KoPictureEps::tryScaleWithGhostScript)" << endl;
116 const int wantedWidth = size.width();
117 const int wantedHeight = size.height();
118 const double xScale = double(size.width()) / double(m_boundingBox.width());
119 const double yScale = double(size.height()) / double(m_boundingBox.height());
123 TQString cmdBuf (
"gs -sOutputFile=" );
124 cmdBuf += TDEProcess::quote(tmpFile.name());
126 cmdBuf += TQString::number( wantedWidth );
128 cmdBuf += TQString::number( wantedHeight );
130 if ( ( resolutionx > 0) && ( resolutiony > 0) )
136 cmdBuf += TQString::number( resolutionx );
138 cmdBuf += TQString::number( resolutiony );
142 cmdBuf +=
" -dSAFER -dPARANOIDSAFER -dNOPAUSE -sDEVICE=";
146 cmdBuf +=
" -c showpage quit";
150 FILE* ghostfd = popen (TQFile::encodeName(cmdBuf),
"w");
154 kdError(30003) <<
"No connection to GhostScript (in KoPictureEps::tryScaleWithGhostScript)" << endl;
159 fprintf (ghostfd,
"\n%d %d translate\n", -tqRound(m_boundingBox.left()*xScale), -tqRound(m_boundingBox.top()*yScale));
160 fprintf (ghostfd,
"%g %g scale\n", xScale, yScale);
164 fwrite( m_rawData.data() + m_psStreamStart,
sizeof(
char), m_psStreamLength, ghostfd);
169 if( !image.load (tmpFile.name()) )
174 if ( image.size() != size )
178 image = image.scale( size );
180 kdDebug(30003) <<
"Image parameters: " << image.width() <<
"x" << image.height() <<
"x" << image.depth() << endl;
184void KoPictureEps::scaleAndCreatePixmap(
const TQSize& size,
bool fastMode,
const int resolutionx,
const int resolutiony )
186 kdDebug(30003) <<
"KoPictureEps::scaleAndCreatePixmap " << size <<
" " << (fastMode?TQString(
"fast"):TQString(
"slow"))
187 <<
" resolutionx: " << resolutionx <<
" resolutiony: " << resolutiony << endl;
188 if ((size==m_cachedSize)
189 && ((fastMode) || (!m_cacheIsInFastMode)))
195 kdDebug(30003) <<
"Already cached!" << endl;
200 if ( !isSlowResizeModeAllowed() )
202 kdDebug(30003) <<
"User has disallowed slow mode!" << endl;
207 if ( fastMode && !m_cachedSize.isEmpty())
209 kdDebug(30003) <<
"Fast scaling!" << endl;
211 TQImage image( m_cachedPixmap.convertToImage() );
212 m_cachedPixmap=image.scale( size );
213 m_cacheIsInFastMode=true;
221 TQApplication::setOverrideCursor( TQt::waitCursor );
222 m_cachedPixmap = scaleWithGhostScript( size, resolutionx, resolutiony );
223 TQApplication::restoreOverrideCursor();
224 m_cacheIsInFastMode=false;
227 kdDebug(30003) <<
"Time: " << (time.elapsed()/1000.0) <<
" s" << endl;
229 kdDebug(30003) <<
"New size: " << size << endl;
232void KoPictureEps::draw(TQPainter& painter,
int x,
int y,
int width,
int height,
int sx,
int sy,
int sw,
int sh,
bool fastMode)
234 if ( !width || !height )
237 TQSize screenSize( width, height );
240 TQPaintDeviceMetrics metrics (painter.device());
241 kdDebug(30003) <<
"Metrics: X: " << metrics.logicalDpiX() <<
" x Y: " << metrics.logicalDpiX() <<
" (in KoPictureEps::draw)" << endl;
243 if ( painter.device()->isExtDev() )
245 kdDebug(30003) <<
"Drawing for a printer (in KoPictureEps::draw)" << endl;
247 TQImage image( scaleWithGhostScript( screenSize, metrics.logicalDpiX(), metrics.logicalDpiY() ) );
250 painter.drawImage( x + sx, y + sy, image, sx, sy, sw, sh );
254 scaleAndCreatePixmap(screenSize, fastMode, metrics.logicalDpiX(), metrics.logicalDpiY() );
258 painter.drawPixmap( x + sx, y + sy, m_cachedPixmap, sx, sy, sw, sh );
262bool KoPictureEps::extractPostScriptStream(
void )
264 kdDebug(30003) <<
"KoPictureEps::extractPostScriptStream" << endl;
265 TQDataStream data( m_rawData, IO_ReadOnly );
266 data.setByteOrder( TQDataStream::LittleEndian );
267 TQ_UINT32 magic, offset, length;
273 kdError(30003) <<
"Length of PS stream is zero!" << endl;
276 if ( offset+length>m_rawData.size() )
278 kdError(30003) <<
"Data stream of the EPSF file is longer than file: " << offset <<
"+" << length <<
">" << m_rawData.size() << endl;
281 m_psStreamStart = offset;
282 m_psStreamLength = length;
286TQString KoPictureEps::readLine(
const TQByteArray& array,
const uint start,
const uint length, uint& pos,
bool& lastCharWasCr )
289 const uint finish = kMin( start + length, (uint)array.size() );
290 for ( ; pos < finish; ++pos )
292 const char ch = array[ pos ];
300 lastCharWasCr =
false;
308 else if ( ch ==
'\r' )
311 lastCharWasCr =
true;
314 else if ( ch ==
char(12) )
322 lastCharWasCr =
false;
329bool KoPictureEps::loadData(
const TQByteArray& array,
const TQString& )
332 kdDebug(30003) <<
"KoPictureEps::load" << endl;
336 if (m_rawData.isNull())
338 kdError(30003) <<
"No data was loaded!" << endl;
342 if ( ( m_rawData[0]==
char(0xc5) ) && ( m_rawData[1]==
char(0xd0) )
343 && ( m_rawData[2]==
char(0xd3) ) && ( m_rawData[3]==
char(0xc6) ) )
346 if (!extractPostScriptStream())
352 m_psStreamLength = m_rawData.size();
356 bool lastWasCr =
false;
357 uint pos = m_psStreamStart;
358 TQString line( readLine( m_rawData, m_psStreamStart, m_psStreamLength, pos, lastWasCr ) );
359 kdDebug(30003) <<
"Header: " << line << endl;
360 if (!line.startsWith(
"%!"))
362 kdError(30003) <<
"Not a PostScript file!" << endl;
366 bool lineIsBoundingBox =
false;
370 line = readLine( m_rawData, m_psStreamStart, m_psStreamLength, pos, lastWasCr );
371 kdDebug(30003) <<
"Checking line: " << line << endl;
373 if (line.startsWith(
"%%BoundingBox:"))
375 lineIsBoundingBox =
true;
380 else if (!line.startsWith(
"%%"))
383 if ( !lineIsBoundingBox )
385 kdError(30003) <<
"KoPictureEps::load: could not find a bounding box!" << endl;
389 TQRegExp exp(
"(\\-?[0-9]+\\.?[0-9]*)\\s(\\-?[0-9]+\\.?[0-9]*)\\s(\\-?[0-9]+\\.?[0-9]*)\\s(\\-?[0-9]+\\.?[0-9]*)");
390 if ( exp.search(line) == -1 )
395 kdError(30003) <<
"Not standard bounding box: " << line << endl;
398 kdDebug(30003) <<
"Reg. Exp. Found: " << exp.capturedTexts() << endl;
399 rect.setLeft((
int)exp.cap(1).toDouble());
400 rect.setTop((
int)exp.cap(2).toDouble());
401 rect.setRight((
int)exp.cap(3).toDouble());
402 rect.setBottom((
int)exp.cap(4).toDouble());
404 m_originalSize=rect.size();
405 kdDebug(30003) <<
"Rect: " << rect <<
" Size: " << m_originalSize << endl;
409bool KoPictureEps::save(TQIODevice* io)
const
412 TQ_ULONG size=io->writeBlock(m_rawData);
413 return (size==m_rawData.size());
416TQSize KoPictureEps::getOriginalSize(
void)
const
418 return m_originalSize;
421TQPixmap KoPictureEps::generatePixmap(
const TQSize& size,
bool smoothScale)
423 scaleAndCreatePixmap(size,!smoothScale, 0, 0);
424 return m_cachedPixmap;
427TQString KoPictureEps::getMimeType(
const TQString&)
const
429 return "image/x-eps";
432TQImage KoPictureEps::generateImage(
const TQSize& size)
435 return scaleWithGhostScript(size, 0, 0);
438void KoPictureEps::clearCache(
void)
440 m_cachedPixmap.resize(0, 0);
441 m_cacheIsInFastMode=
true;
442 m_cachedSize=TQSize();