thumbnailers: reimplement gs thumbnailer

Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
This commit is contained in:
Ivailo Monev 2022-03-01 17:02:19 +02:00
parent 6bf65cde3d
commit 086e12a2a9
7 changed files with 59 additions and 5280 deletions

View file

@ -1,17 +1,23 @@
########### next target ###############
set(gsthumbnail_PART_SRCS gscreator.cpp dscparse.cpp dscparse_adapter.cpp)
set(gsthumbnail_PART_SRCS gscreator.cpp)
kde4_add_plugin(gsthumbnail ${gsthumbnail_PART_SRCS})
target_link_libraries(gsthumbnail
${KDE4_KDECORE_LIBS}
${KDE4_KIO_LIBS}
${QT_QTGUI_LIBRARY}
)
target_link_libraries(gsthumbnail ${KDE4_KDECORE_LIBS} ${KDE4_KIO_LIBS} ${QT_QTGUI_LIBRARY} )
install(TARGETS gsthumbnail DESTINATION ${KDE4_PLUGIN_INSTALL_DIR} )
install(
TARGETS gsthumbnail
DESTINATION ${KDE4_PLUGIN_INSTALL_DIR}
)
########### install files ###############
install( FILES gsthumbnail.desktop DESTINATION ${KDE4_SERVICES_INSTALL_DIR} )
install(
FILES gsthumbnail.desktop
DESTINATION ${KDE4_SERVICES_INSTALL_DIR}
)

File diff suppressed because it is too large Load diff

View file

@ -1,477 +0,0 @@
/* Copyright (C) 2000-2001, Ghostgum Software Pty Ltd. All rights reserved.
This file is part of GSview.
This file is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY. No author or distributor accepts responsibility
to anyone for the consequences of using it or for whether it serves any
particular purpose or works at all, unless he says so in writing. Refer
to the GNU General Public License for full details.
Everyone is granted permission to copy, modify and redistribute this
file, but only under the conditions described in the GNU General
Public License. A copy of this license is supposed to have been given
to you along with this file so you can know your rights and
responsibilities. It should be in a file named COPYING. Among other
things, the copyright notice and this notice must be preserved on all
copies.
*/
/* $Id$ */
/* dscparse.h */
/* Interface for the DSC parser. */
#ifndef _DSCPARSE_H_
#define _DSCPARSE_H_
/* Some local types that may need modification */
typedef bool GSBOOL;
typedef unsigned long GSDWORD; /* must be at least 32 bits */
typedef unsigned int GSWORD; /* must be at least 16 bits */
#ifndef FALSE
# define FALSE ((GSBOOL)0)
# define TRUE ((GSBOOL)(!FALSE))
#endif
#ifndef dsc_private
# ifdef private
# define dsc_private private
# else
# define dsc_private static
# endif
#endif
#ifndef min
# define min(a,b) ((a) < (b) ? (a) : (b))
#endif
/* macros to allow conversion of function declarations to K&R */
#ifndef P0
#define P0() void
#define P1(t1) t1
#define P2(t1,t2) t1,t2
#define P3(t1,t2,t3) t1,t2,t3
#define P4(t1,t2,t3,t4) t1,t2,t3,t4
#define P5(t1,t2,t3,t4,t5) t1,t2,t3,t4,t5
#define P6(t1,t2,t3,t4,t5,t6) t1,t2,t3,t4,t5,t6
#endif
/* maximum legal length of lines in a DSC compliant file */
#define DSC_LINE_LENGTH 255
/* memory for strings is allocated in chunks of this length */
#define CDSC_STRING_CHUNK 4096
/* page array is allocated in chunks of this many pages */
#define CDSC_PAGE_CHUNK 128
/* buffer length for storing lines passed to dsc_scan_data() */
/* must be at least 2 * DSC_LINE_LENGTH */
/* We choose 8192 as twice the length passed to us by GSview */
#define CDSC_DATA_LENGTH 8192
/* Return codes from dsc_scan_data()
* < 0 = error
* >=0 = OK
*
* -1 = error, usually insufficient memory.
* 0-9 = normal
* 10-99 = internal codes, should not be seen.
* 100-999 = identifier of last DSC comment processed.
*/
typedef enum {
CDSC_ERROR = -1, /* Fatal error, usually insufficient memory */
CDSC_OK = 0, /* OK, no DSC comment found */
CDSC_NOTDSC = 1, /* Not DSC, or DSC is being ignored */
/* Any section */
CDSC_UNKNOWNDSC = 100, /* DSC comment not recognised */
/* Header section */
CDSC_PSADOBE = 200, /* %!PS-Adobe- */
CDSC_BEGINCOMMENTS = 201, /* %%BeginComments */
CDSC_ENDCOMMENTS = 202, /* %%EndComments */
CDSC_PAGES = 203, /* %%Pages: */
CDSC_CREATOR = 204, /* %%Creator: */
CDSC_CREATIONDATE = 205, /* %%CreationDate: */
CDSC_TITLE = 206, /* %%Title: */
CDSC_FOR = 207, /* %%For: */
CDSC_LANGUAGELEVEL = 208, /* %%LanguageLevel: */
CDSC_BOUNDINGBOX = 209, /* %%BoundingBox: */
CDSC_ORIENTATION = 210, /* %%Orientation: */
CDSC_PAGEORDER = 211, /* %%PageOrder: */
CDSC_DOCUMENTMEDIA = 212, /* %%DocumentMedia: */
CDSC_DOCUMENTPAPERSIZES = 213, /* %%DocumentPaperSizes: */
CDSC_DOCUMENTPAPERFORMS = 214, /* %%DocumentPaperForms: */
CDSC_DOCUMENTPAPERCOLORS = 215, /* %%DocumentPaperColors: */
CDSC_DOCUMENTPAPERWEIGHTS = 216, /* %%DocumentPaperWeights: */
CDSC_DOCUMENTDATA = 217, /* %%DocumentData: */
CDSC_REQUIREMENTS = 218, /* IGNORED %%Requirements: */
CDSC_DOCUMENTNEEDEDFONTS = 219, /* IGNORED %%DocumentNeededFonts: */
CDSC_DOCUMENTSUPPLIEDFONTS = 220, /* IGNORED %%DocumentSuppliedFonts: */
CDSC_HIRESBOUNDINGBOX = 221, /* %%HiResBoundingBox: */
CDSC_CROPBOX = 222, /* %%CropBox: */
/* Preview section */
CDSC_BEGINPREVIEW = 301, /* %%BeginPreview */
CDSC_ENDPREVIEW = 302, /* %%EndPreview */
/* Defaults section */
CDSC_BEGINDEFAULTS = 401, /* %%BeginDefaults */
CDSC_ENDDEFAULTS = 402, /* %%EndDefaults */
/* also %%PageMedia, %%PageOrientation, %%PageBoundingBox */
/* Prolog section */
CDSC_BEGINPROLOG = 501, /* %%BeginProlog */
CDSC_ENDPROLOG = 502, /* %%EndProlog */
CDSC_BEGINFONT = 503, /* IGNORED %%BeginFont */
CDSC_ENDFONT = 504, /* IGNORED %%EndFont */
CDSC_BEGINFEATURE = 505, /* IGNORED %%BeginFeature */
CDSC_ENDFEATURE = 506, /* IGNORED %%EndFeature */
CDSC_BEGINRESOURCE = 507, /* IGNORED %%BeginResource */
CDSC_ENDRESOURCE = 508, /* IGNORED %%EndResource */
CDSC_BEGINPROCSET = 509, /* IGNORED %%BeginProcSet */
CDSC_ENDPROCSET = 510, /* IGNORED %%EndProcSet */
/* Setup section */
CDSC_BEGINSETUP = 601, /* %%BeginSetup */
CDSC_ENDSETUP = 602, /* %%EndSetup */
CDSC_FEATURE = 603, /* IGNORED %%Feature: */
CDSC_PAPERCOLOR = 604, /* IGNORED %%PaperColor: */
CDSC_PAPERFORM = 605, /* IGNORED %%PaperForm: */
CDSC_PAPERWEIGHT = 606, /* IGNORED %%PaperWeight: */
CDSC_PAPERSIZE = 607, /* %%PaperSize: */
/* also %%Begin/EndFeature, %%Begin/EndResource */
/* Page section */
CDSC_PAGE = 700, /* %%Page: */
CDSC_PAGETRAILER = 701, /* IGNORED %%PageTrailer */
CDSC_BEGINPAGESETUP = 702, /* IGNORED %%BeginPageSetup */
CDSC_ENDPAGESETUP = 703, /* IGNORED %%EndPageSetup */
CDSC_PAGEMEDIA = 704, /* %%PageMedia: */
/* also %%PaperColor, %%PaperForm, %%PaperWeight, %%PaperSize */
CDSC_PAGEORIENTATION = 705, /* %%PageOrientation: */
CDSC_PAGEBOUNDINGBOX = 706, /* %%PageBoundingBox: */
/* also %%Begin/EndFont, %%Begin/EndFeature */
/* also %%Begin/EndResource, %%Begin/EndProcSet */
CDSC_INCLUDEFONT = 707, /* IGNORED %%IncludeFont: */
CDSC_VIEWINGORIENTATION = 708, /* %%ViewingOrientation: */
/* Trailer section */
CDSC_TRAILER = 800, /* %%Trailer */
/* also %%Pages, %%BoundingBox, %%Orientation, %%PageOrder, %%DocumentMedia */
/* %%Page is recognised as an error */
/* also %%DocumentNeededFonts, %%DocumentSuppliedFonts */
/* End of File */
CDSC_EOF = 900 /* %%EOF */
} CDSC_RETURN_CODE;
/* stored in dsc->preview */
typedef enum {
CDSC_NOPREVIEW = 0,
CDSC_EPSI = 1,
CDSC_TIFF = 2,
CDSC_WMF = 3,
CDSC_PICT = 4
} CDSC_PREVIEW_TYPE;
/* stored in dsc->page_order */
typedef enum {
CDSC_ORDER_UNKNOWN = 0,
CDSC_ASCEND = 1,
CDSC_DESCEND = 2,
CDSC_SPECIAL = 3
} CDSC_PAGE_ORDER;
/* stored in dsc->page_orientation and dsc->page[pagenum-1].orientation */
typedef enum {
CDSC_ORIENT_UNKNOWN = 0,
CDSC_PORTRAIT = 1,
CDSC_LANDSCAPE = 2,
CDSC_UPSIDEDOWN = 3,
CDSC_SEASCAPE = 4
} CDSC_ORIENTATION_ENUM;
/* stored in dsc->document_data */
typedef enum {
CDSC_DATA_UNKNOWN = 0,
CDSC_CLEAN7BIT = 1,
CDSC_CLEAN8BIT = 2,
CDSC_BINARY = 3
} CDSC_DOCUMENT_DATA ;
typedef struct CDSCBBOX_S {
int llx;
int lly;
int urx;
int ury;
} CDSCBBOX;
typedef struct CDSCFBBOX_S {
float fllx;
float flly;
float furx;
float fury;
} CDSCFBBOX;
typedef struct CDSCMEDIA_S {
const char *name;
float width; /* PostScript points */
float height;
float weight; /* GSM */
const char *colour;
const char *type;
CDSCBBOX *mediabox; /* Used by GSview for PDF MediaBox */
} CDSCMEDIA;
#define CDSC_KNOWN_MEDIA 46
extern const CDSCMEDIA dsc_known_media[CDSC_KNOWN_MEDIA];
typedef struct CDSCCTM_S { /* used for %%ViewingOrientation */
float xx;
float xy;
float yx;
float yy;
/* float ty; */
/* float ty; */
} CDSCCTM;
typedef struct CDSCPAGE_S {
int ordinal;
const char *label;
unsigned long begin;
unsigned long end;
unsigned int orientation;
const CDSCMEDIA *media;
CDSCBBOX *bbox; /* PageBoundingBox, also used by GSview for PDF CropBox */
CDSCCTM *viewing_orientation;
} CDSCPAGE;
/* binary DOS EPS header */
typedef struct CDSCDOSEPS_S {
GSDWORD ps_begin;
GSDWORD ps_length;
GSDWORD wmf_begin;
GSDWORD wmf_length;
GSDWORD tiff_begin;
GSDWORD tiff_length;
GSWORD checksum;
} CDSCDOSEPS;
/* rather than allocated every string with malloc, we allocate
* chunks of 4k and place the (usually) short strings in these
* chunks.
*/
typedef struct CDSCSTRING_S CDSCSTRING;
struct CDSCSTRING_S {
unsigned int index;
unsigned int length;
char *data;
CDSCSTRING *next;
};
/* DSC error reporting */
typedef enum {
CDSC_MESSAGE_BBOX = 0,
CDSC_MESSAGE_EARLY_TRAILER = 1,
CDSC_MESSAGE_EARLY_EOF = 2,
CDSC_MESSAGE_PAGE_IN_TRAILER = 3,
CDSC_MESSAGE_PAGE_ORDINAL = 4,
CDSC_MESSAGE_PAGES_WRONG = 5,
CDSC_MESSAGE_EPS_NO_BBOX = 6,
CDSC_MESSAGE_EPS_PAGES = 7,
CDSC_MESSAGE_NO_MEDIA = 8,
CDSC_MESSAGE_ATEND = 9,
CDSC_MESSAGE_DUP_COMMENT = 10,
CDSC_MESSAGE_DUP_TRAILER = 11,
CDSC_MESSAGE_BEGIN_END = 12,
CDSC_MESSAGE_BAD_SECTION = 13,
CDSC_MESSAGE_LONG_LINE = 14,
CDSC_MESSAGE_INCORRECT_USAGE = 15
} CDSC_MESSAGE_ERROR;
/* severity */
typedef enum {
CDSC_ERROR_INFORM = 0, /* Not an error */
CDSC_ERROR_WARN = 1, /* Not a DSC error itself, */
CDSC_ERROR_ERROR = 2 /* DSC error */
} CDSC_MESSAGE_SEVERITY;
/* response */
typedef enum {
CDSC_RESPONSE_OK = 0,
CDSC_RESPONSE_CANCEL = 1,
CDSC_RESPONSE_IGNORE_ALL = 2
} CDSC_RESPONSE;
extern const char * const dsc_message[];
typedef struct CDSC_S CDSC;
struct CDSC_S {
/* public data */
GSBOOL dsc; /* TRUE if DSC comments found */
GSBOOL ctrld; /* TRUE if has CTRLD at start of stream */
GSBOOL pjl; /* TRUE if has HP PJL at start of stream */
GSBOOL epsf; /* TRUE if EPSF */
GSBOOL pdf; /* TRUE if Portable Document Format */
unsigned int preview; /* enum CDSC_PREVIEW_TYPE */
char *dsc_version; /* first line of file */
unsigned int language_level;
unsigned int document_data; /* Clean7Bit, Clean8Bit, Binary */
/* enum CDSC_DOCUMENT_DATA */
/* DSC sections */
unsigned long begincomments;
unsigned long endcomments;
unsigned long beginpreview;
unsigned long endpreview;
unsigned long begindefaults;
unsigned long enddefaults;
unsigned long beginprolog;
unsigned long endprolog;
unsigned long beginsetup;
unsigned long endsetup;
unsigned long begintrailer;
unsigned long endtrailer;
CDSCPAGE *page;
unsigned int page_count; /* number of %%Page: pages in document */
unsigned int page_pages; /* number of pages in document from %%Pages: */
unsigned int page_order; /* enum CDSC_PAGE_ORDER */
unsigned int page_orientation; /* the default page orientation */
/* enum CDSC_ORIENTATION */
CDSCCTM *viewing_orientation;
unsigned int media_count; /* number of media items */
CDSCMEDIA **media; /* the array of media */
const CDSCMEDIA *page_media;/* the default page media */
CDSCBBOX *bbox; /* the document bounding box */
CDSCBBOX *page_bbox; /* the default page bounding box */
CDSCDOSEPS *doseps; /* DOS binary header */
char *dsc_title;
char *dsc_creator;
char *dsc_date;
char *dsc_for;
unsigned int max_error; /* highest error number that will be reported */
const int *severity; /* array of severity values, one per error */
/* private data */
void *caller_data; /* pointer to be provided when calling */
/* error and debug callbacks */
int id; /* last DSC comment found */
int scan_section; /* section currently being scanned */
/* enum CDSC_SECTION */
unsigned long doseps_end; /* ps_begin+ps_length, otherwise 0 */
unsigned int page_chunk_length; /* number of pages allocated */
unsigned long file_length; /* length of document */
/* If provided we try to recognise %%Trailer and %%EOF */
/* incorrectly embedded inside document. */
/* Can be left set to default value of 0 */
int skip_document; /* recursion level of %%BeginDocument: */
int skip_bytes; /* #bytes to ignore from BeginData: */
/* or DOSEPS preview section */
int skip_lines; /* #lines to ignore from BeginData: */
GSBOOL skip_pjl; /* TRUE if skip PJL until first PS comment */
int begin_font_count; /* recursion level of %%BeginFont */
int begin_feature_count; /* recursion level of %%BeginFeature */
int begin_resource_count; /* recursion level of %%BeginResource */
int begin_procset_count; /* recursion level of %%BeginProcSet */
/* buffer for input */
char data[CDSC_DATA_LENGTH];/* start of buffer */
unsigned int data_length; /* length of data in buffer */
unsigned int data_index; /* offset to next char in buffer */
unsigned long data_offset; /* offset from start of document */
/* to byte in data[0] */
GSBOOL eof; /* TRUE if there is no more data */
/* information about DSC line */
char *line; /* pointer to last read DSC line */
/* not null terminated */
unsigned int line_length; /* number of characters in line */
GSBOOL eol; /* TRUE if dsc_line contains EOL */
GSBOOL last_cr; /* TRUE if last line ended in \r */
/* check next time for \n */
unsigned int line_count; /* line number */
GSBOOL long_line; /* TRUE if found a line longer than 255 characters */
char last_line[256]; /* previous DSC line, used for %%+ */
/* more efficient string storage (for short strings) than malloc */
CDSCSTRING *string_head; /* linked list head */
CDSCSTRING *string; /* current list item */
/* memory allocation routines */
void *(*memalloc)(P2(size_t size, void *closure_data));
void (*memfree)(P2(void *ptr, void *closure_data));
void *mem_closure_data;
/* function for printing debug messages */
void (*debug_print_fn)(P2(void *caller_data, const char *str));
/* function for reporting errors in DSC comments */
int (*dsc_error_fn)(P5(void *caller_data, CDSC *dsc,
unsigned int explanation, const char *line, unsigned int line_len));
/* public data */
/* Added 2001-10-01 */
CDSCFBBOX *hires_bbox; /* the hires document bounding box */
CDSCFBBOX *crop_box; /* the size of the trimmed page */
};
/* Public functions */
/* Create and initialise DSC parser */
CDSC *dsc_init(P1(void *caller_data));
CDSC *dsc_init_with_alloc(P4(
void *caller_data,
void *(*memalloc)(size_t size, void *closure_data),
void (*memfree)(void *ptr, void *closure_data),
void *closure_data));
/* Free the DSC parser */
void dsc_free(P1(CDSC *dsc));
/* Tell DSC parser how long document will be, to allow ignoring
* of early %%Trailer and %%EOF. This is optional.
*/
void dsc_set_length(P2(CDSC *dsc, unsigned long len));
/* Process a buffer containing DSC comments and PostScript */
int dsc_scan_data(P3(CDSC *dsc, const char *data, int len));
/* All data has been processed, fixup any DSC errors */
int dsc_fixup(P1(CDSC *dsc));
/* Install error query function */
void dsc_set_error_function(P2(CDSC *dsc,
int (*dsc_error_fn)(P5(void *caller_data, CDSC *dsc,
unsigned int explanation, const char *line, unsigned int line_len))));
/* Install print function for debug messages */
void dsc_set_debug_function(P2(CDSC *dsc,
void (*debug_fn)(P2(void *caller_data, const char *str))));
/* Print a message to debug output, if provided */
void dsc_debug_print(P2(CDSC *dsc, const char *str));
/* should be internal only functions, but made available to
* GSview for handling PDF
*/
int dsc_add_page(P3(CDSC *dsc, int ordinal, char *label));
int dsc_add_media(P2(CDSC *dsc, CDSCMEDIA *media));
int dsc_set_page_bbox(P6(CDSC *dsc, unsigned int page_number,
int llx, int lly, int urx, int ury));
#endif
// vim:sw=4:sts=4:ts=8:noet

View file

@ -1,420 +0,0 @@
/**
* Copyright (C) 2001 the KGhostView authors. See file AUTHORS.
*
* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "dscparse_adapter.h"
using namespace std;
/*-- KDSCBBOX implementation -----------------------------------------------*/
KDSCBBOX::KDSCBBOX() :
_llx( 0 ), _lly( 0 ),
_urx( 0 ), _ury( 0 )
{}
KDSCBBOX::KDSCBBOX( const KDSCBBOX& b ) :
_llx( b._llx ), _lly( b._lly ),
_urx( b._urx ), _ury( b._ury )
{}
KDSCBBOX::KDSCBBOX( int llx, int lly, int urx, int ury ) :
_llx( llx ), _lly( lly ),
_urx( urx ), _ury( ury )
{}
KDSCBBOX::KDSCBBOX( const CDSCBBOX& bbox ) :
_llx( bbox.llx ), _lly( bbox.lly ),
_urx( bbox.urx ), _ury( bbox.ury )
{}
KDSCBBOX& KDSCBBOX::operator = ( const KDSCBBOX& b )
{
_llx = b._llx; _lly = b._lly; _urx = b._urx; _ury = b._ury;
return *this;
}
bool KDSCBBOX::operator == ( const KDSCBBOX& b )
{
return ( _llx == b._llx && _lly == b._lly
&& _urx == b._urx && _ury == b._ury );
}
bool KDSCBBOX::operator != ( const KDSCBBOX& b )
{
return !( *this == b );
}
int KDSCBBOX::llx() const { return _llx; }
int KDSCBBOX::lly() const { return _lly; }
int KDSCBBOX::urx() const { return _urx; }
int KDSCBBOX::ury() const { return _ury; }
int KDSCBBOX::width() const { return _urx - _llx; }
int KDSCBBOX::height() const { return _ury - _lly; }
QSize KDSCBBOX::size() const { return QSize( width(), height() ); }
ostream& operator << ( ostream& os, const KDSCBBOX& source )
{
os << "{ llx: "<< source.llx() << ", lly: " << source.lly()
<< " urx: "<< source.urx() << ", ury: " << source.ury() << " }";
return os;
}
/*-- KDSCError implementation ----------------------------------------------*/
KDSCError::KDSCError( Type type, Severity severity, const QByteArray& line,
unsigned int lineNumber ) :
_type( type ),
_severity( severity ),
_line( line ),
_lineNumber( lineNumber )
{}
KDSCError::Type KDSCError::type() const
{
return _type;
}
KDSCError::Severity KDSCError::severity() const
{
return _severity;
}
QByteArray KDSCError::line() const
{
return _line;
}
unsigned int KDSCError::lineNumber() const
{
return _lineNumber;
}
/*-- KDSCOkErrorHandler implementation -------------------------------------*/
KDSCErrorHandler::Response KDSCOkErrorHandler::error( const KDSCError& err )
{
cout << "KDSC: error in line " << err.lineNumber() << endl;
//cout << err.line() << endl;
return Ok;
}
/*-- KDSC implementation ---------------------------------------------------*/
KDSC::KDSC() :
_errorHandler( 0 ),
_commentHandler( 0 )
{
_cdsc = dsc_init( this );
Q_ASSERT( _cdsc != 0 );
_scanHandler = new KDSCScanHandler( _cdsc );
}
KDSC::~KDSC()
{
dsc_free( _cdsc );
delete _scanHandler;
}
QString KDSC::dsc_version() const
{
return QString( _cdsc->dsc_version );
}
bool KDSC::dsc() const
{
return ( _cdsc->dsc == TRUE );
}
bool KDSC::ctrld() const
{
return ( _cdsc->ctrld == TRUE );
}
bool KDSC::pjl() const
{
return ( _cdsc->pjl == TRUE );
}
bool KDSC::epsf() const
{
return ( _cdsc->epsf == TRUE );
}
bool KDSC::pdf() const
{
return ( _cdsc->pdf == TRUE );
}
unsigned int KDSC::preview() const
{
return _cdsc->preview;
}
unsigned int KDSC::language_level() const
{
return _cdsc->language_level;
}
unsigned int KDSC::document_data() const
{
return _cdsc->document_data;
}
unsigned long KDSC::begincomments() const
{
return _cdsc->begincomments;
}
unsigned long KDSC::endcomments() const
{
return _cdsc->endcomments;
}
unsigned long KDSC::beginpreview() const
{
return _cdsc->beginpreview;
}
unsigned long KDSC::endpreview() const
{
return _cdsc->endpreview;
}
unsigned long KDSC::begindefaults() const
{
return _cdsc->begindefaults;
}
unsigned long KDSC::enddefaults() const
{
return _cdsc->enddefaults;
}
unsigned long KDSC::beginprolog() const
{
return _cdsc->beginprolog;
}
unsigned long KDSC::endprolog() const
{
return _cdsc->endprolog;
}
unsigned long KDSC::beginsetup() const
{
return _cdsc->beginsetup;
}
unsigned long KDSC::endsetup() const
{
return _cdsc->endsetup;
}
unsigned long KDSC::begintrailer() const
{
return _cdsc->begintrailer;
}
unsigned long KDSC::endtrailer() const
{
return _cdsc->endtrailer;
}
CDSCPAGE* KDSC::page() const
{
return _cdsc->page;
}
unsigned int KDSC::page_count() const
{
return _cdsc->page_count;
}
unsigned int KDSC::page_pages() const
{
return _cdsc->page_pages;
}
unsigned int KDSC::page_order() const
{
return _cdsc->page_order;
}
unsigned int KDSC::page_orientation() const
{
return _cdsc->page_orientation;
}
CDSCCTM* KDSC::viewing_orientation() const
{
return _cdsc->viewing_orientation;
}
unsigned int KDSC::media_count() const
{
return _cdsc->media_count;
}
CDSCMEDIA** KDSC::media() const
{
return _cdsc->media;
}
const CDSCMEDIA* KDSC::page_media() const
{
return _cdsc->page_media;
}
auto_ptr<KDSCBBOX> KDSC::bbox() const
{
if( _cdsc->bbox == 0 )
return auto_ptr<KDSCBBOX>( 0 );
else
return auto_ptr<KDSCBBOX>( new KDSCBBOX( *_cdsc->bbox ) );
}
auto_ptr<KDSCBBOX> KDSC::page_bbox() const
{
if( _cdsc->page_bbox == 0 )
return auto_ptr<KDSCBBOX>( 0 );
else
return auto_ptr<KDSCBBOX>( new KDSCBBOX( *_cdsc->page_bbox ) );
}
QString KDSC::dsc_title() const
{
return QString( _cdsc->dsc_title );
}
QString KDSC::dsc_creator() const
{
return QString( _cdsc->dsc_creator );
}
QString KDSC::dsc_date() const
{
return QString( _cdsc->dsc_date );
}
QString KDSC::dsc_for() const
{
return QString( _cdsc->dsc_for );
}
bool KDSC::scanData( char* buffer, unsigned int count )
{
return _scanHandler->scanData( buffer, count );
}
int KDSC::fixup()
{
return dsc_fixup( _cdsc );
}
KDSCErrorHandler* KDSC::errorHandler() const
{
return _errorHandler;
}
void KDSC::setErrorHandler( KDSCErrorHandler* errorHandler )
{
_errorHandler = errorHandler;
if( errorHandler == 0 )
dsc_set_error_function( _cdsc, 0 );
else
dsc_set_error_function( _cdsc, &errorFunction );
}
KDSCCommentHandler* KDSC::commentHandler() const
{
return _commentHandler;
}
void KDSC::setCommentHandler( KDSCCommentHandler* commentHandler )
{
if( _commentHandler != 0 && commentHandler == 0 )
{
delete _scanHandler;
_scanHandler = new KDSCScanHandler( _cdsc );
}
else if( _commentHandler == 0 && commentHandler != 0 )
{
delete _scanHandler;
_scanHandler = new KDSCScanHandlerByLine( _cdsc, commentHandler );
}
_commentHandler = commentHandler;
}
bool KDSC::isStructured() const
{
return epsf() ? ( page_count() > 1 ) : ( page_count() > 0 );
}
CDSC* KDSC::cdsc() const
{
return _cdsc;
}
int KDSC::errorFunction( void* caller_data, CDSC* dsc,
unsigned int explanation, const char* line, unsigned int line_len )
{
KDSCError error(
static_cast< KDSCError::Type >( explanation ),
static_cast< KDSCError::Severity >( dsc->severity[explanation] ),
QByteArray( line, line_len + 1 ),
dsc->line_count
);
KDSC* kdsc = static_cast< KDSC* >( caller_data );
Q_ASSERT( kdsc );
return kdsc->errorHandler()->error( error );
}
bool KDSCScanHandlerByLine::scanData( char* buf, unsigned int count )
{
char* lineStart = buf;
char* it = buf;
while( it < buf + count )
{
if( *it++ == '\n' )
{
int retval = dsc_scan_data( _cdsc, lineStart, it - lineStart );
if( retval < 0 )
return false;
else if( retval > 0 )
{
_commentHandler->comment(
static_cast<KDSCCommentHandler::Name>( retval ) );
}
lineStart = it;
}
}
if( it != lineStart )
{
// Scan the remaining part of the string.
return ( dsc_scan_data( _cdsc, lineStart, it - lineStart ) < 0 );
}
else
return true;
}
// vim:sw=4:sts=4:ts=8:noet

View file

@ -1,336 +0,0 @@
/**
* Copyright (C) 2001 the KGhostView authors. See file AUTHORS.
*
* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef DSCPARSE_ADAPTER_H
#define DSCPARSE_ADAPTER_H
#include <iostream>
#include <map>
#include <memory>
#include <qsize.h>
#include <qstring.h>
#include "dscparse.h"
class KDSCBBOX
{
public:
KDSCBBOX();
KDSCBBOX( const KDSCBBOX& b );
KDSCBBOX( int llx, int lly, int urx, int ury );
KDSCBBOX( const CDSCBBOX& bbox );
KDSCBBOX& operator = ( const KDSCBBOX& b );
bool operator == ( const KDSCBBOX& b );
bool operator != ( const KDSCBBOX& b );
int llx() const;
int lly() const;
int urx() const;
int ury() const;
int width() const;
int height() const;
QSize size() const;
private:
int _llx, _lly, _urx, _ury;
};
std::ostream& operator << ( std::ostream&, const KDSCBBOX& );
class KDSCError
{
public:
enum Type
{
BBox = CDSC_MESSAGE_BBOX,
EarlyTrailer = CDSC_MESSAGE_EARLY_TRAILER,
EarlyEOF = CDSC_MESSAGE_EARLY_EOF,
PageInTrailer = CDSC_MESSAGE_PAGE_IN_TRAILER,
PageOrdinal = CDSC_MESSAGE_PAGE_ORDINAL,
PagesWrong = CDSC_MESSAGE_PAGES_WRONG,
EPSNoBBox = CDSC_MESSAGE_EPS_NO_BBOX,
EPSPages = CDSC_MESSAGE_EPS_PAGES,
NoMedia = CDSC_MESSAGE_NO_MEDIA,
AtEnd = CDSC_MESSAGE_ATEND,
DuplicateComment = CDSC_MESSAGE_DUP_COMMENT,
DuplicateTrailer = CDSC_MESSAGE_DUP_TRAILER,
BeginEnd = CDSC_MESSAGE_BEGIN_END,
BadSection = CDSC_MESSAGE_BAD_SECTION,
LongLine = CDSC_MESSAGE_LONG_LINE,
IncorrectUsage = CDSC_MESSAGE_INCORRECT_USAGE
};
enum Severity
{
Information = CDSC_ERROR_INFORM,
Warning = CDSC_ERROR_WARN,
Error = CDSC_ERROR_ERROR
};
KDSCError( Type, Severity, const QByteArray& line,
unsigned int lineNumber );
Type type() const;
Severity severity() const;
QByteArray line() const;
unsigned int lineNumber() const;
private:
Type _type;
Severity _severity;
QByteArray _line;
unsigned int _lineNumber;
};
class KDSCErrorHandler
{
public:
virtual ~KDSCErrorHandler() {}
enum Response
{
Ok = CDSC_RESPONSE_OK,
Cancel = CDSC_RESPONSE_CANCEL,
IgnoreAll = CDSC_RESPONSE_IGNORE_ALL
};
virtual Response error( const KDSCError& ) = 0;
};
class KDSCOkErrorHandler : public KDSCErrorHandler
{
Response error( const KDSCError& );
};
class KDSCCommentHandler
{
public:
virtual ~KDSCCommentHandler() {}
enum Name
{
// Header section
PSAdobe = CDSC_PSADOBE,
BeginComments = CDSC_BEGINCOMMENTS,
EndComments = CDSC_ENDCOMMENTS,
Pages = CDSC_PAGES,
Creator = CDSC_CREATOR,
CreationDate = CDSC_CREATIONDATE,
Title = CDSC_TITLE,
For = CDSC_FOR,
LanguageLevel = CDSC_LANGUAGELEVEL,
BoundingBox = CDSC_BOUNDINGBOX,
Orientation = CDSC_ORIENTATION,
PageOrder = CDSC_PAGEORDER,
DocumentMedia = CDSC_DOCUMENTMEDIA,
DocumentPaperSizes = CDSC_DOCUMENTPAPERSIZES,
DocumentPaperForms = CDSC_DOCUMENTPAPERFORMS,
DocumentPaperColors = CDSC_DOCUMENTPAPERCOLORS,
DocumentPaperWeights = CDSC_DOCUMENTPAPERWEIGHTS,
DocumentData = CDSC_DOCUMENTDATA,
Requirements = CDSC_REQUIREMENTS,
DocumentNeededFonts = CDSC_DOCUMENTNEEDEDFONTS,
DocumentSuppliedFonts = CDSC_DOCUMENTSUPPLIEDFONTS,
HiResBoundingBox = CDSC_HIRESBOUNDINGBOX,
CropBox = CDSC_CROPBOX,
// Preview section
BeginPreview = CDSC_BEGINPREVIEW,
EndPreview = CDSC_ENDPREVIEW,
// Defaults section
BeginDefaults = CDSC_BEGINDEFAULTS,
EndDefaults = CDSC_ENDDEFAULTS,
// also %%PageMedia, %%PageOrientation, %%PageBoundingBox
// Prolog section
BeginProlog = CDSC_BEGINPROLOG,
EndProlog = CDSC_ENDPROLOG,
BeginFont = CDSC_BEGINFONT,
EndFont = CDSC_ENDFONT,
BeginFeature = CDSC_BEGINFEATURE,
EndFeature = CDSC_ENDFEATURE,
BeginResource = CDSC_BEGINRESOURCE,
EndResource = CDSC_ENDRESOURCE,
BeginProcset = CDSC_BEGINPROCSET,
EndProcset = CDSC_ENDPROCSET,
// Setup section
BeginSetup = CDSC_BEGINSETUP,
EndSetup = CDSC_ENDSETUP,
Feature = CDSC_FEATURE,
PaperColor = CDSC_PAPERCOLOR,
PaperForm = CDSC_PAPERFORM,
PaperWeight = CDSC_PAPERWEIGHT,
PaperSize = CDSC_PAPERSIZE,
// also %%Begin/EndFeature, %%Begin/EndResource
// Page section
Page = CDSC_PAGE,
PageTrailer = CDSC_PAGETRAILER,
BeginPageSetup = CDSC_BEGINPAGESETUP,
EndPageSetup = CDSC_ENDPAGESETUP,
PageMedia = CDSC_PAGEMEDIA,
// also %%PaperColor, %%PaperForm, %%PaperWeight, %%PaperSize
PageOrientation = CDSC_PAGEORIENTATION,
PageBoundingBox = CDSC_PAGEBOUNDINGBOX,
// also %%Begin/EndFont, %%Begin/EndFeature
// also %%Begin/EndResource, %%Begin/EndProcSet
IncludeFont = CDSC_INCLUDEFONT,
ViewingOrientation = CDSC_VIEWINGORIENTATION,
// Trailer section
Trailer = CDSC_TRAILER,
// also %%Pages, %%BoundingBox, %%Orientation, %%PageOrder,
// %%DocumentMedia
// %%Page is recognised as an error
// also %%DocumentNeededFonts, %%DocumentSuppliedFonts
// End of File */
Eof = CDSC_EOF
};
virtual void comment( Name name ) { std::cout << name << std::endl; }
};
class KDSCScanHandler;
class KDSC
{
public:
KDSC();
~KDSC();
/*--- Adapter for CDSC ------------------------------------------------*/
QString dsc_version() const;
bool dsc() const;
bool ctrld() const;
bool pjl() const;
bool epsf() const;
bool pdf() const;
unsigned int preview() const;
unsigned int language_level() const;
unsigned int document_data() const;
unsigned long begincomments() const;
unsigned long endcomments() const;
unsigned long beginpreview() const;
unsigned long endpreview() const;
unsigned long begindefaults() const;
unsigned long enddefaults() const;
unsigned long beginprolog() const;
unsigned long endprolog() const;
unsigned long beginsetup() const;
unsigned long endsetup() const;
unsigned long begintrailer() const;
unsigned long endtrailer() const;
CDSCPAGE* page() const;
unsigned int page_count() const;
unsigned int page_pages() const;
unsigned int page_order() const;
unsigned int page_orientation() const;
CDSCCTM* viewing_orientation() const;
unsigned int media_count() const;
CDSCMEDIA** media() const;
const CDSCMEDIA* page_media() const;
std::auto_ptr<KDSCBBOX> bbox() const;
std::auto_ptr<KDSCBBOX> page_bbox() const;
// CDSCDOSEPS *doseps;
QString dsc_title() const;
QString dsc_creator() const;
QString dsc_date() const;
QString dsc_for() const;
// unsigned int max_error
bool scanData( char*, unsigned int );
/**
* Tidy up from incorrect DSC comments.
*/
int fixup();
KDSCErrorHandler* errorHandler() const;
void setErrorHandler( KDSCErrorHandler* );
KDSCCommentHandler* commentHandler() const;
void setCommentHandler( KDSCCommentHandler* );
/*--- Extra methods for convenience -----------------------------------*/
bool isStructured() const;
/*--- Temporary -------------------------------------------------------*/
CDSC* cdsc() const;
protected:
static int errorFunction( void* caller_data, CDSC* dsc,
unsigned int explanation,
const char* line, unsigned int line_len );
private:
CDSC* _cdsc;
KDSCErrorHandler* _errorHandler;
KDSCCommentHandler* _commentHandler;
KDSCScanHandler* _scanHandler;
};
class KDSCScanHandler
{
public:
virtual ~KDSCScanHandler() {}
KDSCScanHandler( CDSC* cdsc ) : _cdsc( cdsc ) {}
virtual bool scanData( char* buf, unsigned int count )
{
return ( dsc_scan_data( _cdsc, buf, count ) >= 0 );
}
protected:
CDSC* _cdsc;
};
class KDSCScanHandlerByLine : public KDSCScanHandler
{
public:
KDSCScanHandlerByLine( CDSC* cdsc, KDSCCommentHandler* commentHandler ) :
KDSCScanHandler( cdsc ),
_commentHandler( commentHandler )
{}
virtual bool scanData( char* buf, unsigned int count );
protected:
KDSCCommentHandler* _commentHandler;
};
#endif
// vim:sw=4:sts=4:ts=8:noet

View file

@ -1,12 +1,9 @@
/* This file is part of the KDE libraries
Copyright (C) 2001 Malte Starostik <malte@kde.org>
Handling of EPS previews Copyright (C) 2003 Philipp Hullmann <phull@gmx.de>
/* This file is part of the KDE project
Copyright (C) 2022 Ivailo Monev <xakepa10@gmail.com>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
License version 2, as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
@ -17,613 +14,61 @@
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
/* This function gets a path of a DVI, EPS, PS or PDF file and
produces a PNG-Thumbnail which is stored as a QImage
The program works as follows
1. Test if file is a DVI file
2. Create a child process (1), in which the
file is to be changed into a PNG
3. Child-process (1) :
4. If file is DVI continue with 6
5. If file is no DVI continue with 9
6. Create another child process (2), in which the DVI is
turned into PS using dvips
7. Parent process (2) :
Turn the recently created PS file into a PNG file using gs
8. continue with 10
9. Turn the PS,PDF or EPS file into a PNG file using gs
10. Parent process (1)
store data in a QImage
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <assert.h>
#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
#include <sys/time.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <errno.h>
#include <kdemacros.h>
#include <qcolor.h>
#include <qfile.h>
#include <qimage.h>
#include <qregexp.h>
#include <QVector>
*/
#include "gscreator.h"
#include "dscparse_adapter.h"
#include "dscparse.h"
#include <QImage>
#include <QFileInfo>
#include <QProcess>
#include <kstandarddirs.h>
#include <ktemporaryfile.h>
#include <kdebug.h>
#include <kdemacros.h>
extern "C"
{
KDE_EXPORT ThumbCreator *new_creator()
{
return new GSCreator;
return new GSCreator();
}
}
// This PS snippet will be prepended to the actual file so that only
// the first page is output.
static const char *psprolog =
"%!PS-Adobe-3.0\n"
"/.showpage.orig /showpage load def\n"
"/.showpage.firstonly {\n"
" .showpage.orig\n"
" quit\n"
"} def\n"
"/showpage { .showpage.firstonly } def\n";
// This is the code recommended by Adobe tech note 5002 for including
// EPS files.
static const char *epsprolog =
"%!PS-Adobe-3.0\n"
"userdict begin /pagelevel save def /showpage { } def\n"
"0 setgray 0 setlinecap 1 setlinewidth 0 setlinejoin 10 setmiterlimit\n"
"[ ] 0 setdash newpath false setoverprint false setstrokeadjust\n";
static const char * gsargs_ps[] = {
"gs",
"-sDEVICE=png16m",
"-sOutputFile=-",
"-dSAFER",
"-dPARANOIDSAFER",
"-dNOPAUSE",
"-dFirstPage=1",
"-dLastPage=1",
"-q",
"-",
0, // file name
"-c",
"showpage",
"-c",
"quit",
0
};
static const char * gsargs_eps[] = {
"gs",
"-sDEVICE=png16m",
"-sOutputFile=-",
"-dSAFER",
"-dPARANOIDSAFER",
"-dNOPAUSE",
0, // page size
0, // resolution
"-q",
"-",
0, // file name
"-c",
"pagelevel",
"-c",
"restore",
"-c",
"end",
"-c",
"showpage",
"-c",
"quit",
0
};
static const char *dvipsargs[] = {
"dvips",
"-n",
"1",
"-q",
"-o",
"-",
0, // file name
0
};
static bool correctDVI(const QString& filename);
namespace {
bool got_sig_term = false;
void handle_sigterm( int ) {
got_sig_term = true;
}
}
bool GSCreator::create(const QString &path, int width, int height, QImage &img)
bool GSCreator::create(const QString &path, int, int, QImage &img)
{
// The code in the loop (when testing whether got_sig_term got set)
// should read some variation of:
// parentJob()->wasKilled()
//
// Unfortunatelly, that's currently impossible without breaking BIC.
// So we need to catch the signal ourselves.
// Otherwise, on certain funny PS files (for example
// http://www.tjhsst.edu/~Eedanaher/pslife/life.ps )
// gs would run forever after we were dead.
// #### Reconsider for KDE 4 ###
// (24/12/03 - luis_pedro)
//
typedef void ( *sighandler_t )( int );
// according to linux's "man signal" the above typedef is a gnu extension
sighandler_t oldhandler = signal( SIGTERM, handle_sigterm );
int input[2];
int output[2];
int dvipipe[2];
QByteArray data(1024, '\0');
bool ok = false;
// Test if file is DVI
bool no_dvi =!correctDVI(path);
if (pipe(input) == -1) {
return false;
}
if (pipe(output) == -1) {
close(input[0]);
close(input[1]);
return false;
}
KDSC dsc;
endComments = false;
dsc.setCommentHandler(this);
if (no_dvi)
{
FILE* fp = fopen(QFile::encodeName(path), "r");
if (fp == 0) return false;
char buf[4096];
int count;
while ((count = fread(buf, sizeof(char), 4096, fp)) != 0
&& !endComments) {
dsc.scanData(buf, count);
}
fclose(fp);
if (dsc.pjl() || dsc.ctrld()) {
// this file is a mess.
return false;
}
}
const bool is_encapsulated = no_dvi &&
(path.indexOf(QRegExp("\\.epsi?$", Qt::CaseInsensitive)) > 0) &&
(dsc.bbox()->width() > 0) && (dsc.bbox()->height() > 0) &&
(dsc.page_count() <= 1);
char translation[64] = "";
char pagesize[32] = "";
char resopt[32] = "";
std::auto_ptr<KDSCBBOX> bbox = dsc.bbox();
if (is_encapsulated) {
// GhostScript's rendering at the extremely low resolutions
// required for thumbnails leaves something to be desired. To
// get nicer images, we render to four times the required
// resolution and let QImage scale the result.
const int hres = (width * 72) / bbox->width();
const int vres = (height * 72) / bbox->height();
const int resolution = (hres > vres ? vres : hres) * 4;
const int gswidth = ((bbox->urx() - bbox->llx()) * resolution) / 72;
const int gsheight = ((bbox->ury() - bbox->lly()) * resolution) / 72;
snprintf(pagesize, 31, "-g%ix%i", gswidth, gsheight);
snprintf(resopt, 31, "-r%i", resolution);
snprintf(translation, 63,
" 0 %i sub 0 %i sub translate\n", bbox->llx(),
bbox->lly());
}
const CDSC_PREVIEW_TYPE previewType =
static_cast<CDSC_PREVIEW_TYPE>(dsc.preview());
switch (previewType) {
case CDSC_TIFF:
case CDSC_WMF:
case CDSC_PICT:
// FIXME: these should take precedence, since they can hold
// color previews, which EPSI can't (or can it?).
break;
case CDSC_EPSI:
{
const int xscale = bbox->width() / width;
const int yscale = bbox->height() / height;
const int scale = xscale < yscale ? xscale : yscale;
if (getEPSIPreview(path,
dsc.beginpreview(),
dsc.endpreview(),
img,
bbox->width() / scale,
bbox->height() / scale))
return true;
// If the preview extraction routine fails, gs is used to
// create a thumbnail.
}
break;
case CDSC_NOPREVIEW:
default:
// need to run ghostscript in these cases
break;
}
pid_t pid = fork();
if (pid == 0) {
// Child process (1)
// close(STDERR_FILENO);
// find first zero entry in gsargs and put the filename
// or - (stdin) there, if DVI
const char **gsargs = gsargs_ps;
const char **arg = gsargs;
if (no_dvi && is_encapsulated) {
gsargs = gsargs_eps;
arg = gsargs;
// find first zero entry and put page size there
while (*arg) ++arg;
*arg = pagesize;
// find second zero entry and put resolution there
while (*arg) ++arg;
*arg = resopt;
const QString gsexe = KStandardDirs::findExe("gs");
if (gsexe.isEmpty()) {
kWarning() << "Ghostscript is not available";
return false;
}
// find next zero entry and put the filename there
QByteArray fname = QFile::encodeName( path );
while (*arg)
++arg;
if( no_dvi )
*arg = fname.data();
else
*arg = "-";
// find first zero entry in dvipsargs and put the filename there
arg = dvipsargs;
while (*arg)
++arg;
*arg = fname.data();
if( !no_dvi ){
pipe(dvipipe);
pid_t pid_two = fork();
if( pid_two == 0 ){
// Child process (2), reopen stdout on the pipe "dvipipe" and exec dvips
close(input[0]);
close(input[1]);
close(output[0]);
close(output[1]);
close(dvipipe[0]);
dup2( dvipipe[1], STDOUT_FILENO);
execvp(dvipsargs[0], const_cast<char *const *>(dvipsargs));
exit(1);
}
else if(pid_two != -1){
close(input[1]);
close(output[0]);
close(dvipipe[1]);
dup2( dvipipe[0], STDIN_FILENO);
dup2( output[1], STDOUT_FILENO);
execvp(gsargs[0], const_cast<char *const *>(gsargs));
exit(1);
}
else{
// fork() (2) failed, close these
close(dvipipe[0]);
close(dvipipe[1]);
}
const QStringList gsargs = QStringList()
<< QLatin1String("-q")
<< QLatin1String("-dNOPAUSE")
<< QLatin1String("-dSAFER")
<< QLatin1String("-dBATCH")
<< QLatin1String("-dFirstPage=1")
<< QLatin1String("-dLastPage=1")
<< QLatin1String("-sDEVICE=png16m")
<< QLatin1String("-sOutputFile=-")
<< path;
QProcess gsprocess;
gsprocess.start(gsexe, gsargs);
if (gsprocess.waitForFinished() == false || gsprocess.exitCode() != 0) {
kWarning() << gsprocess.readAllStandardError();
return false;
}
else if( no_dvi ){
// Reopen stdin/stdout on the pipes and exec gs
close(input[1]);
close(output[0]);
const QByteArray gsimage = gsprocess.readAllStandardOutput();
dup2(input[0], STDIN_FILENO);
dup2(output[1], STDOUT_FILENO);
execvp(gsargs[0], const_cast<char *const *>(gsargs));
exit(1);
}
}
else if (pid != -1) {
// Parent process, write first-page-only-hack (the hack is not
// used if DVI) and read the png output
close(input[0]);
close(output[1]);
const char *prolog;
if (is_encapsulated)
prolog = epsprolog;
else
prolog = psprolog;
int count = write(input[1], prolog, strlen(prolog));
if (is_encapsulated)
write(input[1], translation, strlen(translation));
close(input[1]);
if (count == static_cast<int>(strlen(prolog))) {
int offset = 0;
while (!ok) {
fd_set fds;
FD_ZERO(&fds);
FD_SET(output[0], &fds);
struct timeval tv;
tv.tv_sec = 20;
tv.tv_usec = 0;
got_sig_term = false;
if (select(output[0] + 1, &fds, 0, 0, &tv) <= 0) {
if ( ( errno == EINTR || errno == EAGAIN ) && !got_sig_term ) continue;
break; // error, timeout or master wants us to quit (SIGTERM)
}
if (FD_ISSET(output[0], &fds)) {
count = read(output[0], data.data() + offset, 1024);
if (count == -1)
break;
else
if (count) // prepare for next block
{
offset += count;
data.resize(offset + 1024);
}
else // got all data
{
data.resize(offset);
ok = true;
}
}
}
}
if (!ok) // error or timeout, gs probably didn't exit yet
{
kill(pid, SIGTERM);
if (img.loadFromData(gsimage, "PNG") == false) {
kWarning() << "Could not load ghostscript image";
return false;
}
int status = 0;
int ret;
do {
ret = waitpid(pid, &status, 0);
} while (ret == -1 && errno == EINTR);
if (ret != pid || (status != 0 && status != 256) )
ok = false;
}
else {
// fork() (1) failed, close these
close(input[0]);
close(input[1]);
close(output[1]);
}
close(output[0]);
int l = img.loadFromData( data );
if ( got_sig_term &&
oldhandler != SIG_ERR &&
oldhandler != SIG_DFL &&
oldhandler != SIG_IGN ) {
oldhandler( SIGTERM ); // propagate the signal. Other things might rely on it
}
if ( oldhandler != SIG_ERR ) signal( SIGTERM, oldhandler );
return ok && l;
return true;
}
ThumbCreator::Flags GSCreator::flags() const
{
return static_cast<Flags>(DrawFrame);
}
void GSCreator::comment(Name name)
{
switch (name) {
case EndPreview:
case BeginProlog:
case Page:
endComments = true;
break;
default:
break;
}
}
// Quick function to check if the filename corresponds to a valid DVI
// file. Returns true if <filename> is a DVI file, false otherwise.
static bool correctDVI(const QString& filename)
{
QFile f(filename);
if (!f.open(QIODevice::ReadOnly))
return false;
unsigned char test[4];
if ( f.read( (char *)test,2)<2 || test[0] != 247 || test[1] != 2 )
return false;
int n = f.size();
if ( n < 134 ) // Too short for a dvi file
return false;
f.seek( n-4 );
unsigned char trailer[4] = { 0xdf,0xdf,0xdf,0xdf };
if ( f.read( (char *)test, 4 )<4 || strncmp( (char *)test, (char*) trailer, 4 ) )
return false;
// We suppose now that the dvi file is complete and OK
return true;
}
bool GSCreator::getEPSIPreview(const QString &path, long start, long
end, QImage &outimg, int imgwidth, int imgheight)
{
FILE *fp;
fp = fopen(QFile::encodeName(path), "r");
if (fp == 0) return false;
const long previewsize = end - start + 1;
char *buf = (char *) malloc(previewsize);
fseek(fp, start, SEEK_SET);
int count = fread(buf, sizeof(char), previewsize - 1, fp);
fclose(fp);
buf[previewsize - 1] = 0;
if (count != previewsize - 1)
{
free(buf);
return false;
}
QString previewstr = QString::fromLatin1(buf);
free(buf);
int offset = 0;
while ((offset < previewsize) && !(previewstr[offset].isDigit())) offset++;
int digits = 0;
while ((offset + digits < previewsize) && previewstr[offset + digits].isDigit()) digits++;
int width = previewstr.mid(offset, digits).toInt();
offset += digits + 1;
while ((offset < previewsize) && !(previewstr[offset].isDigit())) offset++;
digits = 0;
while ((offset + digits < previewsize) && previewstr[offset + digits].isDigit()) digits++;
int height = previewstr.mid(offset, digits).toInt();
offset += digits + 1;
while ((offset < previewsize) && !(previewstr[offset].isDigit())) offset++;
digits = 0;
while ((offset + digits < previewsize) && previewstr[offset + digits].isDigit()) digits++;
int depth = previewstr.mid(offset, digits).toInt();
// skip over the rest of the BeginPreview comment
while ((offset < previewsize) &&
previewstr[offset] != '\n' &&
previewstr[offset] != '\r') offset++;
while ((offset < previewsize) && previewstr[offset] != '%') offset++;
#if QT_VERSION < 0x041200
unsigned int imagedepth;
switch (depth) {
case 1:
case 2:
case 4:
case 8:
imagedepth = 8;
break;
case 12: // valid, but not (yet) supported
default: // illegal value
return false;
}
unsigned int colors = (1U << depth);
QImage img(width, height, QImage::Format_Indexed8);
img.setColorCount(colors);
if (imagedepth <= 8) {
for (unsigned int gray = 0; gray < colors; gray++) {
unsigned int grayvalue = (255U * (colors - 1 - gray)) / (colors - 1);
img.setColor(gray, qRgb(grayvalue, grayvalue, grayvalue));
}
}
#else
QImage img(width, height, QImage::Format_RGB32);
#endif
const unsigned int bits_per_scan_line = width * depth;
unsigned int bytes_per_scan_line = bits_per_scan_line / 8;
if (bits_per_scan_line % 8) bytes_per_scan_line++;
const unsigned int bindatabytes = height * bytes_per_scan_line;
QVector<unsigned char> bindata(bindatabytes);
for (unsigned int i = 0; i < bindatabytes; i++) {
if (offset >= previewsize)
return false;
while (!isxdigit(previewstr[offset].toLatin1()) && offset < previewsize)
offset++;
bool ok = false;
bindata[i] = static_cast<unsigned char>(previewstr.mid(offset, 2).toUInt(&ok, 16));
if (!ok)
return false;
offset += 2;
}
for (int scanline = 0; scanline < height; scanline++) {
unsigned char *scanlineptr = img.scanLine(scanline);
for (int pixelindex = 0; pixelindex < width; pixelindex++) {
unsigned char pixelvalue = 0;
const unsigned int bitoffset =
scanline * bytes_per_scan_line * 8U + pixelindex * depth;
for (int depthindex = 0; depthindex < depth;
depthindex++) {
const unsigned int byteindex = (bitoffset + depthindex) / 8U;
const unsigned int bitindex =
7 - ((bitoffset + depthindex) % 8U);
const unsigned char bitvalue =
(bindata[byteindex] & static_cast<unsigned char>(1U << bitindex)) >> bitindex;
pixelvalue |= (bitvalue << depthindex);
}
scanlineptr[pixelindex] = pixelvalue;
}
}
#if QT_VERSION < 0x041200
outimg = img.convertToFormat(QImage::Format_RGB32).scaled(imgwidth, imgheight, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
#else
outimg = img.scaled(imgwidth, imgheight, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
#endif
return true;
return ThumbCreator::None;
}

View file

@ -1,10 +1,9 @@
/* This file is part of the KDE libraries
Copyright (C) 2000 Malte Starostik <malte@kde.org>
/* This file is part of the KDE project
Copyright (C) 2022 Ivailo Monev <xakepa10@gmail.com>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
License version 2, as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
@ -15,28 +14,19 @@
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
*/
#ifndef _GSCREATOR_H_
#define _GSCREATOR_H_
#include <kio/thumbcreator.h>
#include "dscparse_adapter.h"
class GSCreator : public ThumbCreator, public KDSCCommentHandler
class GSCreator : public ThumbCreator
{
public:
GSCreator() {}
virtual bool create(const QString &path, int, int, QImage &img);
virtual Flags flags() const;
void comment(Name name);
private:
static bool getEPSIPreview(const QString &path,
long start, long end,
QImage &outimg,
int imgwidth, int imgheight);
bool endComments;
virtual ThumbCreator::Flags flags() const;
};
#endif