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.
166 lines
4.4 KiB
166 lines
4.4 KiB
9 years ago
|
#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));
|
||
|
}
|