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