Michael Uleysky
9 years ago
3 changed files with 209 additions and 0 deletions
@ -0,0 +1,165 @@
|
||||
#include <string.h> |
||||
#include <unistd.h> |
||||
#include "common.h" |
||||
#include "modgmt_gsfuncs.h" |
||||
|
||||
struct gs_abilities_struct gs_abilities; |
||||
|
||||
static int gs_callback_out(void *caller_handle, const char *buf, int len) |
||||
{ |
||||
struct gs_runtime* r=static_cast<struct gs_runtime*>(caller_handle); |
||||
if(0!=r->out) r->out->append(buf,len); |
||||
return len; |
||||
} |
||||
|
||||
static int gs_callback_err(void *caller_handle, const char *buf, int len) |
||||
{ |
||||
struct gs_runtime* r=static_cast<struct gs_runtime*>(caller_handle); |
||||
if(0!=r->err) r->err->append(buf,len); |
||||
return len; |
||||
} |
||||
|
||||
static int gs_callback_in(void *caller_handle, char *buf, int len) |
||||
{ |
||||
struct gs_runtime* r=static_cast<struct gs_runtime*>(caller_handle); |
||||
if(r->pos>=r->in->length()) return 0; |
||||
size_t rem=r->in->length()-r->pos; |
||||
if(rem>static_cast<size_t>(len)) rem=len; |
||||
memcpy(buf,r->in->c_str()+r->pos,rem); |
||||
r->pos+=rem; |
||||
return rem; |
||||
} |
||||
|
||||
struct gsworkthreadpars |
||||
{ |
||||
struct gs_runtime* r; |
||||
gs_callback input_callback; |
||||
int fd; |
||||
const std::string* opts; |
||||
int ret; |
||||
}; |
||||
|
||||
// This function call gs_* in separate thread, because ghostscript write to stdout
|
||||
static void* gsworkthread(void* x) |
||||
{ |
||||
struct gsworkthreadpars* p=reinterpret_cast<struct gsworkthreadpars*>(x); |
||||
WordList wl; |
||||
if(-1==p->fd) wl=Split("-dSAFER -q -o/dev/null "+*(p->opts)+" -"); |
||||
else wl=Split("-dSAFER -dDOINTERPOLATE -q -o/dev/fd/"+ToString(p->fd)+" "+*(p->opts)+" -"); |
||||
int argc=wl.size()+1; |
||||
char** argv; |
||||
int i; |
||||
void* gs; |
||||
|
||||
argv=new char*[argc]; |
||||
argv[0]=new char[2]; argv[0][0]='G'; argv[0][1]=0; |
||||
i=1; |
||||
for(auto& opt: wl) |
||||
{ |
||||
argv[i]=new char[opt.length()+1]; |
||||
memcpy(argv[i],opt.c_str(),opt.length()+1); |
||||
i++; |
||||
} |
||||
|
||||
p->ret=gsapi_new_instance(&gs,p->r); |
||||
if(p->ret<0) goto end; |
||||
gsapi_set_stdio(gs,p->input_callback?p->input_callback:gs_callback_in,gs_callback_out,gs_callback_err); |
||||
p->ret=gsapi_init_with_args(gs,argc,argv); |
||||
if(0==p->ret || e_Quit==p->ret) p->ret=gsapi_exit(gs); |
||||
else gsapi_exit(gs); |
||||
if(e_Quit==p->ret) p->ret=0; |
||||
gsapi_delete_instance(gs); |
||||
|
||||
end: |
||||
close(p->fd); |
||||
for(i=0;i<argc;i++) delete[] argv[i]; |
||||
delete[] argv; |
||||
return &p->ret; |
||||
} |
||||
|
||||
// Main function for prepare and run ghostscript
|
||||
static int GhostRun(const std::string& opts, struct gs_runtime* r, std::string* out, gs_callback input=0) |
||||
{ |
||||
struct gsworkthreadpars wp; |
||||
int* pret; |
||||
|
||||
wp.r=r; |
||||
wp.input_callback=input; |
||||
wp.opts=&opts; |
||||
wp.ret=0; |
||||
wp.fd=-1; |
||||
|
||||
if(0!=out) |
||||
{ |
||||
int pipefd[2]; |
||||
pthread_t wthr; |
||||
ssize_t br; |
||||
char buffer[4096]; |
||||
|
||||
pipe(pipefd); |
||||
wp.fd=pipefd[1]; |
||||
|
||||
out->erase(); |
||||
pthread_create(&wthr,0,&gsworkthread,&wp); |
||||
do |
||||
{ |
||||
br=read(pipefd[0],buffer,4096); |
||||
out->append(buffer,br); |
||||
} while(0!=br); |
||||
close(pipefd[0]); |
||||
out->shrink_to_fit(); |
||||
pthread_join(wthr,reinterpret_cast<void**>(&pret)); |
||||
} |
||||
else pret=reinterpret_cast<int*>(gsworkthread(&wp)); |
||||
|
||||
return *pret; |
||||
} |
||||
|
||||
|
||||
// This function run ghostscript with input data in string
|
||||
int GhostRun(const std::string& opts, const std::string& input, std::string* sout, std::string* serr, std::string* out) |
||||
{ |
||||
struct gs_runtime r; |
||||
|
||||
r.in=&input; |
||||
r.pos=0; |
||||
r.out=sout; |
||||
r.err=serr; |
||||
return GhostRun(opts,&r,out); |
||||
} |
||||
|
||||
// This function run ghostscript with input data provided by callback function
|
||||
int GhostRun(const std::string& opts, gs_callback input, void* inputdata, std::string* sout, std::string* serr, std::string* out) |
||||
{ |
||||
struct gs_runtime r; |
||||
|
||||
r.indata=inputdata; |
||||
r.out=sout; |
||||
r.err=serr; |
||||
return GhostRun(opts,&r,out,input); |
||||
} |
||||
|
||||
void CheckGhostscriptAbilities() |
||||
{ |
||||
std::string out; |
||||
gs_abilities.havepdf=gs_abilities.havebbox=gs_abilities.havepngmono=gs_abilities.havepngmonod=gs_abilities.havepng16=gs_abilities.havepng256=gs_abilities.havepnggray=gs_abilities.havepng16m=gs_abilities.havejpeg=gs_abilities.havejpeggray=false; |
||||
|
||||
if(0!=GhostRun("-sDEVICE=nullpage","devicenames ==",&out,0,0)) return; |
||||
|
||||
WordList wl=Split(out,"[]/ \t"); |
||||
for(auto& i:wl) |
||||
{ |
||||
if("pdfwrite"==i) gs_abilities.havepdf=true; |
||||
if("bbox"==i) gs_abilities.havebbox=true; |
||||
if("pngmono"==i) gs_abilities.havepngmono=true; |
||||
if("pngmonod"==i) gs_abilities.havepngmonod=true; |
||||
if("png16"==i) gs_abilities.havepng16=true; |
||||
if("png256"==i) gs_abilities.havepng256=true; |
||||
if("pnggray"==i) gs_abilities.havepnggray=true; |
||||
if("png16m"==i) gs_abilities.havepng16m=true; |
||||
if("jpeg"==i) gs_abilities.havejpeg=true; |
||||
if("jpeggray"==i) gs_abilities.havejpeggray=true; |
||||
} |
||||
|
||||
// gs_abilities.havepdf=(0==GhostRun("-sDEVICE=pdfwrite -dCompatibilityLevel=1.4","gsave 1 0 0 setrgbcolor 5 setlinewidth 100 100 moveto 200 200 lineto stroke grestore showpage",0,0,0));
|
||||
} |
@ -0,0 +1,38 @@
|
||||
#ifndef MODGMT_GSFUNCS_H |
||||
#define MODGMT_GSFUNCS_H |
||||
#include <string> |
||||
#include <ghostscript/iapi.h> |
||||
#include <ghostscript/ierrors.h> |
||||
|
||||
struct gs_abilities_struct |
||||
{ |
||||
bool havepngmono,havepngmonod,havepng16,havepng256,havepnggray,havepng16m; |
||||
bool havejpeg,havejpeggray; |
||||
bool havepdf,havebbox; |
||||
}; |
||||
|
||||
extern struct gs_abilities_struct gs_abilities; |
||||
|
||||
struct gs_runtime |
||||
{ |
||||
union |
||||
{ |
||||
struct |
||||
{ |
||||
const std::string* in; |
||||
uint pos; |
||||
}; |
||||
void* indata; |
||||
}; |
||||
std::string* out; |
||||
std::string* err; |
||||
}; |
||||
|
||||
typedef int (*gs_callback)(void *caller_handle, char *buf, int len); |
||||
|
||||
int GhostRun(const std::string& opts, const std::string& input, std::string* sout, std::string* serr, std::string* out); |
||||
int GhostRun(const std::string& opts, gs_callback input, void* inputdata, std::string* sout, std::string* serr, std::string* out); |
||||
|
||||
void CheckGhostscriptAbilities(); |
||||
|
||||
#endif |
Loading…
Reference in new issue