26#include <tqpaintdevicemetrics.h>
28#include <tqtextstream.h>
32#include <tqapplication.h>
33#include <tqdragobject.h>
37#include <tdeversion.h>
38#if ! KDE_IS_VERSION( 3,1,90 )
39#include <kdebugclasses.h>
41#include <tdetempfile.h>
44#include "KoPictureKey.h"
45#include "KoPictureBase.h"
46#include "KoPictureEps.h"
49KoPictureEps::KoPictureEps(
void) : m_psStreamStart(0), m_psStreamLength(0), m_cacheIsInFastMode(true)
52 m_cachedPixmap.setOptimization(TQPixmap::MemoryOptim);
55KoPictureEps::~KoPictureEps(
void)
59KoPictureBase* KoPictureEps::newCopy(
void)
const
61 return new KoPictureEps(*
this);
64KoPictureType::Type KoPictureEps::getType(
void)
const
66 return KoPictureType::TypeEps;
69bool KoPictureEps::isNull(
void)
const
71 return m_rawData.isNull();
74TQImage KoPictureEps::scaleWithGhostScript(
const TQSize& size,
const int resolutionx,
const int resolutiony )
76 if (!m_boundingBox.width() || !m_boundingBox.height())
78 kdDebug(30003) <<
"EPS image has a null size! (in KoPictureEps::scaleWithGhostScript)" << endl;
87 const char* deviceTable[] = {
"png16m",
"bmp16m",
"ppm", 0 };
91 for (
int i = 0; deviceTable[i]; ++i)
93 if ( tryScaleWithGhostScript( img, size, resolutionx, resolutiony, deviceTable[i] ) != -1 )
100 kdError(30003) <<
"Image from GhostScript cannot be loaded (in KoPictureEps::scaleWithGhostScript)" << endl;
106int KoPictureEps::tryScaleWithGhostScript(TQImage &image,
const TQSize& size,
const int resolutionx,
const int resolutiony,
const char* device )
109 kdDebug(30003) <<
"Sampling with GhostScript, using device \"" << device <<
"\" (in KoPictureEps::tryScaleWithGhostScript)" << endl;
112 tmpFile.setAutoDelete(
true);
114 if ( tmpFile.status() )
116 kdError(30003) <<
"No KTempFile! (in KoPictureEps::tryScaleWithGhostScript)" << endl;
120 const int wantedWidth = size.width();
121 const int wantedHeight = size.height();
122 const double xScale = double(size.width()) / double(m_boundingBox.width());
123 const double yScale = double(size.height()) / double(m_boundingBox.height());
127 TQString cmdBuf (
"gs -sOutputFile=" );
128 cmdBuf += TDEProcess::quote(tmpFile.name());
130 cmdBuf += TQString::number( wantedWidth );
132 cmdBuf += TQString::number( wantedHeight );
134 if ( ( resolutionx > 0) && ( resolutiony > 0) )
140 cmdBuf += TQString::number( resolutionx );
142 cmdBuf += TQString::number( resolutiony );
146 cmdBuf +=
" -dSAFER -dPARANOIDSAFER -dNOPAUSE -sDEVICE=";
150 cmdBuf +=
" -c showpage quit";
154 FILE* ghostfd = popen (TQFile::encodeName(cmdBuf),
"w");
158 kdError(30003) <<
"No connection to GhostScript (in KoPictureEps::tryScaleWithGhostScript)" << endl;
163 fprintf (ghostfd,
"\n%d %d translate\n", -tqRound(m_boundingBox.left()*xScale), -tqRound(m_boundingBox.top()*yScale));
164 fprintf (ghostfd,
"%g %g scale\n", xScale, yScale);
168 fwrite( m_rawData.data() + m_psStreamStart,
sizeof(
char), m_psStreamLength, ghostfd);
173 if( !image.load (tmpFile.name()) )
178 if ( image.size() != size )
182 image = image.scale( size );
184 kdDebug(30003) <<
"Image parameters: " << image.width() <<
"x" << image.height() <<
"x" << image.depth() << endl;
188void KoPictureEps::scaleAndCreatePixmap(
const TQSize& size,
bool fastMode,
const int resolutionx,
const int resolutiony )
190 kdDebug(30003) <<
"KoPictureEps::scaleAndCreatePixmap " << size <<
" " << (fastMode?TQString(
"fast"):TQString(
"slow"))
191 <<
" resolutionx: " << resolutionx <<
" resolutiony: " << resolutiony << endl;
192 if ((size==m_cachedSize)
193 && ((fastMode) || (!m_cacheIsInFastMode)))
199 kdDebug(30003) <<
"Already cached!" << endl;
204 if ( !isSlowResizeModeAllowed() )
206 kdDebug(30003) <<
"User has disallowed slow mode!" << endl;
211 if ( fastMode && !m_cachedSize.isEmpty())
213 kdDebug(30003) <<
"Fast scaling!" << endl;
215 TQImage image( m_cachedPixmap.convertToImage() );
216 m_cachedPixmap=image.scale( size );
217 m_cacheIsInFastMode=
true;
225 TQApplication::setOverrideCursor( TQt::waitCursor );
226 m_cachedPixmap = scaleWithGhostScript( size, resolutionx, resolutiony );
227 TQApplication::restoreOverrideCursor();
228 m_cacheIsInFastMode=
false;
231 kdDebug(30003) <<
"Time: " << (time.elapsed()/1000.0) <<
" s" << endl;
233 kdDebug(30003) <<
"New size: " << size << endl;
236void KoPictureEps::draw(TQPainter& painter,
int x,
int y,
int width,
int height,
int sx,
int sy,
int sw,
int sh,
bool fastMode)
238 if ( !width || !height )
241 TQSize screenSize( width, height );
244 TQPaintDeviceMetrics metrics (painter.device());
245 kdDebug(30003) <<
"Metrics: X: " << metrics.logicalDpiX() <<
" x Y: " << metrics.logicalDpiX() <<
" (in KoPictureEps::draw)" << endl;
247 if ( painter.device()->isExtDev() )
249 kdDebug(30003) <<
"Drawing for a printer (in KoPictureEps::draw)" << endl;
251 TQImage image( scaleWithGhostScript( screenSize, metrics.logicalDpiX(), metrics.logicalDpiY() ) );
254 painter.drawImage( x + sx, y + sy, image, sx, sy, sw, sh );
258 scaleAndCreatePixmap(screenSize, fastMode, metrics.logicalDpiX(), metrics.logicalDpiY() );
262 painter.drawPixmap( x + sx, y + sy, m_cachedPixmap, sx, sy, sw, sh );
266bool KoPictureEps::extractPostScriptStream(
void )
268 kdDebug(30003) <<
"KoPictureEps::extractPostScriptStream" << endl;
269 TQDataStream data( m_rawData, IO_ReadOnly );
270 data.setByteOrder( TQDataStream::LittleEndian );
271 TQ_UINT32 magic, offset, length;
277 kdError(30003) <<
"Length of PS stream is zero!" << endl;
280 if ( offset+length>m_rawData.size() )
282 kdError(30003) <<
"Data stream of the EPSF file is longer than file: " << offset <<
"+" << length <<
">" << m_rawData.size() << endl;
285 m_psStreamStart = offset;
286 m_psStreamLength = length;
290TQString KoPictureEps::readLine(
const TQByteArray& array,
const uint start,
const uint length, uint& pos,
bool& lastCharWasCr )
293 const uint finish = kMin( start + length, (uint)array.size() );
294 for ( ; pos < finish; ++pos )
296 const char ch = array[ pos ];
304 lastCharWasCr =
false;
312 else if ( ch ==
'\r' )
315 lastCharWasCr =
true;
318 else if ( ch ==
char(12) )
326 lastCharWasCr =
false;
333bool KoPictureEps::loadData(
const TQByteArray& array,
const TQString& )
336 kdDebug(30003) <<
"KoPictureEps::load" << endl;
340 if (m_rawData.isNull())
342 kdError(30003) <<
"No data was loaded!" << endl;
346 if ( ( m_rawData[0]==
char(0xc5) ) && ( m_rawData[1]==
char(0xd0) )
347 && ( m_rawData[2]==
char(0xd3) ) && ( m_rawData[3]==
char(0xc6) ) )
350 if (!extractPostScriptStream())
356 m_psStreamLength = m_rawData.size();
360 bool lastWasCr =
false;
361 uint pos = m_psStreamStart;
362 TQString line( readLine( m_rawData, m_psStreamStart, m_psStreamLength, pos, lastWasCr ) );
363 kdDebug(30003) <<
"Header: " << line << endl;
364 if (!line.startsWith(
"%!"))
366 kdError(30003) <<
"Not a PostScript file!" << endl;
370 bool lineIsBoundingBox =
false;
374 line = readLine( m_rawData, m_psStreamStart, m_psStreamLength, pos, lastWasCr );
375 kdDebug(30003) <<
"Checking line: " << line << endl;
377 if (line.startsWith(
"%%BoundingBox:"))
379 lineIsBoundingBox =
true;
384 else if (!line.startsWith(
"%%"))
387 if ( !lineIsBoundingBox )
389 kdError(30003) <<
"KoPictureEps::load: could not find a bounding box!" << endl;
393 TQRegExp exp(
"(\\-?[0-9]+\\.?[0-9]*)\\s(\\-?[0-9]+\\.?[0-9]*)\\s(\\-?[0-9]+\\.?[0-9]*)\\s(\\-?[0-9]+\\.?[0-9]*)");
394 if ( exp.search(line) == -1 )
399 kdError(30003) <<
"Not standard bounding box: " << line << endl;
402 kdDebug(30003) <<
"Reg. Exp. Found: " << exp.capturedTexts() << endl;
403 rect.setLeft((
int)exp.cap(1).toDouble());
404 rect.setTop((
int)exp.cap(2).toDouble());
405 rect.setRight((
int)exp.cap(3).toDouble());
406 rect.setBottom((
int)exp.cap(4).toDouble());
408 m_originalSize=rect.size();
409 kdDebug(30003) <<
"Rect: " << rect <<
" Size: " << m_originalSize << endl;
413bool KoPictureEps::save(TQIODevice* io)
const
416 TQ_ULONG size=io->writeBlock(m_rawData);
417 return (size==m_rawData.size());
420TQSize KoPictureEps::getOriginalSize(
void)
const
422 return m_originalSize;
425TQPixmap KoPictureEps::generatePixmap(
const TQSize& size,
bool smoothScale)
427 scaleAndCreatePixmap(size,!smoothScale, 0, 0);
428 return m_cachedPixmap;
431TQString KoPictureEps::getMimeType(
const TQString&)
const
433 return "image/x-eps";
436TQImage KoPictureEps::generateImage(
const TQSize& size)
439 return scaleWithGhostScript(size, 0, 0);
442void KoPictureEps::clearCache(
void)
444 m_cachedPixmap.resize(0, 0);
445 m_cacheIsInFastMode=
true;
446 m_cachedSize=TQSize();