You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

221 lines
5.6 KiB

/***************************************************************************
* Copyright (C) 2005 by Piotr Szymanski <niedakh@gmail.com> *
* Copyright (C) 2007 by Albert Astals Cid <aacid@kde.org> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
***************************************************************************/
#include "gshandler.h"
#include "interpreter_cmd.h"
#include "ghostscript/ierrors.h"
#include "ghostscript/gdevdsp.h"
#include <kdebug.h>
#include <QFile>
#include <QImage>
static bool handleErrorCode(int code)
{
if ( code>=0 )
return true;
else if ( code <= -100 )
{
switch (code)
{
case e_Fatal:
kDebug() << "fatal internal error " << code << endl;
break;
case e_ExecStackUnderflow:
kDebug() << "stack overflow " << code << endl;
break;
// no error or not important
default:
return true;
}
}
else
{
const char* errors[]= { "", ERROR_NAMES };
int x=(-1)*code;
kDebug() << errors[x] << " " << code << endl;
return false;
}
return true;
}
static int open(void * /*handle*/, void * /*device*/)
{
return 0;
}
static int preclose(void * /*handle*/, void * /*device*/ )
{
return 0;
}
static int close(void * /*handle*/, void * /*device*/ )
{
return 0;
}
static int presize(void * /*handle*/, void * /*device*/, int /*width*/, int /*height*/,
int /*raster*/, unsigned int /*format*/)
{
return 0;
}
static int size(void *handle, void *device, int width, int height, int raster, unsigned int format, unsigned char *pimage)
{
if (handle != 0)
return static_cast <GSHandler*>(handle) -> size (device, width, height, raster, format, pimage);
return 0;
}
static int sync(void * /*handle*/, void * /*device*/ )
{
return 0;
}
static int page(void *handle, void * device, int copies, int flush)
{
if (handle != 0)
return static_cast <GSHandler*>(handle) -> page (device, copies, flush);
return 0;
}
static display_callback device =
{
sizeof( display_callback ),
DISPLAY_VERSION_MAJOR,
DISPLAY_VERSION_MINOR,
&open,
&preclose,
&close,
&presize,
&size,
&sync,
&page,
0,
0,
0
};
GSHandler::GSHandler()
{
m_ghostScriptInstance = 0;
}
void GSHandler::init(const QString &media, double magnify, int width, int height, bool plaformFonts, int aaText, int aaGfx, GSInterpreterCMD *interpreter)
{
int errorCode;
if (m_ghostScriptInstance)
{
gsapi_exit(m_ghostScriptInstance);
gsapi_delete_instance(m_ghostScriptInstance);
}
errorCode = gsapi_new_instance(&m_ghostScriptInstance, this);
handleErrorCode(errorCode);
errorCode = gsapi_set_display_callback(m_ghostScriptInstance, &device);
handleErrorCode(errorCode);
QStringList internalArgs;
internalArgs << " "
<< "-dMaxBitmap=10000000"
<< "-dDELAYSAFER"
<< "-dNOPAUSE"
<< "-dNOPAGEPROMPT"
<< QString("-dTextAlphaBits=%1").arg(aaText)
<< QString("-dGraphicsAlphaBits=%1").arg(aaGfx)
<< QString("-sPAPERSIZE=%1").arg(media.toLower())
<< QString().sprintf("-g%dx%d", width, height)
<< QString().sprintf("-r%fx%f", (magnify * Okular::Utils::dpiX()),
(magnify * Okular::Utils::dpiY()))
<< QString().sprintf("-dDisplayFormat=%d", DISPLAY_COLORS_RGB | DISPLAY_UNUSED_LAST | DISPLAY_DEPTH_8 | DISPLAY_LITTLEENDIAN | DISPLAY_TOPFIRST)
<< QString().sprintf("-sDisplayHandle=16#%llx", (unsigned long long int) this );
if ( !plaformFonts )
internalArgs << "-dNOPLATFONTS";
qDebug() << internalArgs;
int t = internalArgs.count();
char **args = new char*[t];
for (int i = 0; i < t; ++i)
{
args[i] = new char[internalArgs[i].length() + 1];
qstrcpy(*(args+i), internalArgs[i].toLocal8Bit());
}
errorCode = gsapi_init_with_args(m_ghostScriptInstance, t, args);
handleErrorCode(errorCode);
for (int i = 0; i < t; ++i) delete[] args[i];
QString set = "<< /Orientation 0 >> setpagedevice .locksafe";
gsapi_run_string_with_length(m_ghostScriptInstance, set.toLatin1().constData(), set.length(), 0, &errorCode);
handleErrorCode(errorCode);
m_device = interpreter;
}
void GSHandler::process(const QString &filename, const PsPosition &pos)
{
int errorCode;
QFile f(filename);
f.open(QIODevice::ReadOnly);
f.seek(pos.first);
static char buf[32768];
unsigned int read;
int wrote;
size_t left = pos.second - pos.first;
gsapi_run_string_begin(m_ghostScriptInstance, 0, &errorCode);
handleErrorCode(errorCode);
while (left > 0)
{
read = f.read(buf, qMin(sizeof(buf),left));
wrote = gsapi_run_string_continue(m_ghostScriptInstance, buf, read, 0, &errorCode);
handleErrorCode(errorCode);
left -= read;
}
f.close();
gsapi_run_string_end(m_ghostScriptInstance, 0, &errorCode);
}
int GSHandler::size(void * /*device*/, int width, int height, int raster, unsigned int /*format*/, unsigned char *pimage)
{
m_GSwidth = width;
m_GSheight = height;
m_GSraster = raster;
m_GSimage = pimage;
return 0;
}
int GSHandler::page(void * /*device*/, int /*copies*/, int /*flush*/)
{
QImage img;
if (m_GSraster == m_GSwidth * 4)
{
img = QImage(m_GSimage, m_GSwidth, m_GSheight, QImage::Format_RGB32 );
}
else
{
// In case this ends up beign very slow we can try with some memmove
QImage aux(m_GSimage, m_GSraster / 4, m_GSheight, QImage::Format_RGB32 );
img = QImage(aux.copy(0, 0, m_GSwidth, m_GSheight));
}
m_device->fordwardImage(new QImage(img.copy()));
return 0;
}