diff options
Diffstat (limited to 'Build/source/utils/asymptote/picture.cc')
-rw-r--r-- | Build/source/utils/asymptote/picture.cc | 1515 |
1 files changed, 0 insertions, 1515 deletions
diff --git a/Build/source/utils/asymptote/picture.cc b/Build/source/utils/asymptote/picture.cc deleted file mode 100644 index 9cb847ae099..00000000000 --- a/Build/source/utils/asymptote/picture.cc +++ /dev/null @@ -1,1515 +0,0 @@ -/***** - * picture.cc - * Andy Hammerlindl 2002/06/06 - * - * Stores a picture as a list of drawElements and handles its output to - * PostScript. - *****/ - -#include "errormsg.h" -#include "picture.h" -#include "util.h" -#include "settings.h" -#include "interact.h" -#include "drawverbatim.h" -#include "drawlabel.h" -#include "drawlayer.h" -#include "drawsurface.h" -#include "drawpath3.h" - -#ifdef __MSDOS__ -#include "sys/cygwin.h" -#endif - -using std::ifstream; -using std::ofstream; -using vm::array; - -using namespace settings; -using namespace gl; - -texstream::~texstream() { - string texengine=getSetting<string>("tex"); - bool context=settings::context(texengine); - string name; - if(!context) - name=stripFile(outname()); - name += "texput."; - unlink((name+"aux").c_str()); - unlink((name+"log").c_str()); - unlink((name+"out").c_str()); - if(settings::pdf(texengine)) { - unlink((name+"pdf").c_str()); - unlink((name+"m9").c_str()); - } else - unlink((name+"pbsdat").c_str()); - if(context) { - unlink("cont-new.log"); - unlink((name+"tex").c_str()); - unlink((name+"top").c_str()); - unlink((name+"tua").c_str()); - unlink((name+"tui").c_str()); - } -} - -namespace camp { - -extern void draw(); - -bool isIdTransform3(const double* t) -{ - return (t == NULL || (t[0]==1 && t[1]==0 && t[2]==0 && t[3]==0 && - t[4]==0 && t[5]==1 && t[6]==0 && t[7]==0 && - t[8]==0 && t[9]==0 && t[10]==1 && t[11]==0 && - t[12]==0 && t[13]==0 && t[14]==0 && t[15]==1)); -} - -// copy array to 4x4 transform matrix with range checks -void copyArray4x4C(double*& dest, const vm::array *a) -{ - double tt[16]; - const size_t n=checkArray(a); - const string fourbyfour="4x4 array of doubles expected"; - if(n != 4) reportError(fourbyfour); - - for(size_t i=0; i < 4; i++) { - const vm::array *ai=vm::read<vm::array*>(a,i); - const size_t aisize=checkArray(ai); - double *tti=tt+4*i; - if(aisize == 4) { - for(size_t j=0; j < 4; j++) - tti[j]=vm::read<double>(ai,j); - } else reportError(fourbyfour); - } - - copyTransform3(dest,tt); -} - -void copyTransform3(double*& d, const double* s, GCPlacement placement) - -{ - if(s != NULL) { - if(d == NULL) - d=placement == NoGC ? new double[16] : new(placement) double[16]; - memcpy(d,s,sizeof(double)*16); - } -} - -// t = s*r -void multiplyTransform3(double*& t, const double* s, const double* r) -{ - if(isIdTransform3(s)) { - copyTransform3(t,r); - } else if(isIdTransform3(r)) { - copyTransform3(t,s); - } else { - t=new(UseGC) double[16]; - for(size_t i=0; i < 4; i++) { - size_t i4=4*i; - const double *si=s+i4; - const double& s0=si[0]; - const double& s1=si[1]; - const double& s2=si[2]; - const double& s3=si[3]; - double *ti=t+i4; - ti[0]=s0*r[0]+s1*r[4]+s2*r[8]+s3*r[12]; - ti[1]=s0*r[1]+s1*r[5]+s2*r[9]+s3*r[13]; - ti[2]=s0*r[2]+s1*r[6]+s2*r[10]+s3*r[14]; - ti[3]=s0*r[3]+s1*r[7]+s2*r[11]+s3*r[15]; - } - } -} - -double xratio(const triple& v) {return v.getx()/v.getz();} -double yratio(const triple& v) {return v.gety()/v.getz();} - -class matrixstack { - mem::stack<const double*> mstack; - -public: - // return current transform - const double* T() const - { - if(mstack.empty()) - return NULL; - else - return mstack.top(); - } - // we store the accumulated transform of all pushed transforms - void push(const double *r) - { - double* T3 = NULL; - multiplyTransform3(T3,T(),r); - mstack.push(T3); - } - void pop() - { - if(!mstack.empty()) - mstack.pop(); - } - -}; - -const char *texpathmessage() { - ostringstream buf; - buf << "the directory containing your " << getSetting<string>("tex") - << " engine (" << texcommand() << ")"; - return Strdup(buf.str()); -} - -picture::~picture() -{ -} - -void picture::enclose(drawElement *begin, drawElement *end) -{ - assert(begin); - assert(end); - nodes.push_front(begin); - lastnumber=0; - lastnumber3=0; - - for(nodelist::iterator p=nodes.begin(); p != nodes.end(); ++p) { - assert(*p); - if((*p)->islayer()) { - nodes.insert(p,end); - ++p; - while(p != nodes.end() && (*p)->islayer()) ++p; - if(p == nodes.end()) return; - nodes.insert(p,begin); - } - } - nodes.push_back(end); -} - -// Insert at beginning of picture. -void picture::prepend(drawElement *p) -{ - assert(p); - nodes.push_front(p); - lastnumber=0; - lastnumber3=0; -} - -void picture::append(drawElement *p) -{ - assert(p); - nodes.push_back(p); -} - -void picture::add(picture &pic) -{ - if (&pic == this) return; - - // STL's funny way of copying one list into another. - copy(pic.nodes.begin(), pic.nodes.end(), back_inserter(nodes)); -} - -// Insert picture pic at beginning of picture. -void picture::prepend(picture &pic) -{ - if (&pic == this) return; - - copy(pic.nodes.begin(), pic.nodes.end(), inserter(nodes, nodes.begin())); - lastnumber=0; - lastnumber3=0; -} - -bool picture::havelabels() -{ - size_t n=nodes.size(); - if(n > lastnumber && !labels && getSetting<string>("tex") != "none") { - // Check to see if there are any labels yet - nodelist::iterator p=nodes.begin(); - for(size_t i=0; i < lastnumber; ++i) ++p; - for(; p != nodes.end(); ++p) { - assert(*p); - if((*p)->islabel()) { - labels=true; - break; - } - } - } - return labels; -} - -bool picture::have3D() -{ - for(nodelist::iterator p=nodes.begin(); p != nodes.end(); ++p) { - assert(*p); - if((*p)->is3D()) - return true; - } - return false; -} - -bool picture::havepng() -{ - for(nodelist::iterator p=nodes.begin(); p != nodes.end(); ++p) { - assert(*p); - if((*p)->svgpng()) - return true; - } - return false; -} - -bool picture::havenewpage() -{ - for(nodelist::iterator p=nodes.begin(); p != nodes.end(); ++p) { - assert(*p); - if((*p)->isnewpage()) - return true; - } - return false; -} - -bbox picture::bounds() -{ - size_t n=nodes.size(); - if(n == lastnumber) return b_cached; - - if(lastnumber == 0) { // Maybe these should be put into a structure. - b_cached=bbox(); - labelbounds.clear(); - bboxstack.clear(); - } - - if(havelabels()) texinit(); - - nodelist::iterator p=nodes.begin(); - processDataStruct& pd=processData(); - - for(size_t i=0; i < lastnumber; ++i) ++p; - for(; p != nodes.end(); ++p) { - assert(*p); - (*p)->bounds(b_cached,pd.tex,labelbounds,bboxstack); - - // Optimization for interpreters with fixed stack limits. - if((*p)->endclip()) { - nodelist::iterator q=p; - if(q != nodes.begin()) { - --q; - assert(*q); - if((*q)->endclip()) - (*q)->save(false); - } - } - } - - lastnumber=n; - return b_cached; -} - -bbox3 picture::bounds3() -{ - size_t n=nodes.size(); - if(n == lastnumber3) return b3; - - if(lastnumber3 == 0) - b3=bbox3(); - - matrixstack ms; - size_t i=0; - for(nodelist::const_iterator p=nodes.begin(); p != nodes.end(); ++p) { - assert(*p); - if((*p)->begingroup3()) - ms.push((*p)->transf3()); - else if((*p)->endgroup3()) - ms.pop(); - else - (*p)->bounds(ms.T(),b3); - i++; - } - - lastnumber3=n; - return b3; -} - -pair picture::ratio(double (*m)(double, double)) -{ - bool first=true; - pair b; - bounds3(); - double fuzz=Fuzz*(b3.Max()-b3.Min()).length(); - matrixstack ms; - for(nodelist::const_iterator p=nodes.begin(); p != nodes.end(); ++p) { - assert(*p); - if((*p)->begingroup3()) - ms.push((*p)->transf3()); - else if((*p)->endgroup3()) - ms.pop(); - else - (*p)->ratio(ms.T(),b,m,fuzz,first); - } - return b; -} - -void texinit() -{ - drawElement::lastpen=pen(initialpen); - processDataStruct &pd=processData(); - // Output any new texpreamble commands - if(pd.tex.isopen()) { - if(pd.TeXpipepreamble.empty()) return; - texpreamble(pd.tex,pd.TeXpipepreamble,true); - pd.TeXpipepreamble.clear(); - return; - } - - bool context=settings::context(getSetting<string>("tex")); - string dir=stripFile(outname()); - string logname; - if(!context) logname=dir; - logname += "texput.log"; - const char *cname=logname.c_str(); - ofstream writeable(cname); - if(!writeable) - reportError("Cannot write to "+logname); - else - writeable.close(); - unlink(cname); - - mem::vector<string> cmd; - cmd.push_back(texprogram()); - if(context) { - cmd.push_back("--pipe"); - } else { - if(!dir.empty()) - cmd.push_back("-output-directory="+dir.substr(0,dir.length()-1)); - string jobname="texput"; - if(getSetting<bool>("inlineimage") || getSetting<bool>("inlinetex")) { - string name=stripDir(stripExt((outname()))); - size_t pos=name.rfind("-"); - if(pos < string::npos) { - name=stripExt(name).substr(0,pos); - unlink((name+".aux").c_str()); - jobname=name.substr(0,pos); - cmd.push_back("-jobname="+jobname); -#ifdef __MSDOS__ - cmd.push_back("NUL"); // For MikTeX -#endif - } - } - cmd.push_back("\\scrollmode"); - } - - pd.tex.open(cmd,"texpath"); - pd.tex.wait("\n*"); - pd.tex << "\n"; - texdocumentclass(pd.tex,true); - - texdefines(pd.tex,pd.TeXpreamble,true); - pd.TeXpipepreamble.clear(); -} - -int opentex(const string& texname, const string& prefix, bool dvi) -{ - string aux=auxname(prefix,"aux"); - unlink(aux.c_str()); - bool context=settings::context(getSetting<string>("tex")); - mem::vector<string> cmd; - cmd.push_back(texprogram()); - if(dvi) - cmd.push_back("-output-format=dvi"); - if(context) { - cmd.push_back("--nonstopmode"); - cmd.push_back(texname); - } else { - string dir=stripFile(texname); - if(!dir.empty()) - cmd.push_back("-output-directory="+dir.substr(0,dir.length()-1)); - cmd.push_back("\\nonstopmode\\input"); - cmd.push_back(stripDir(texname)); - } - - bool quiet=verbose <= 1; - int status=System(cmd,quiet ? 1 : 0,true,"texpath",texpathmessage()); - if(!status && getSetting<bool>("twice")) - status=System(cmd,quiet ? 1 : 0,true,"texpath",texpathmessage()); - if(status) { - if(quiet) { - cmd[1]=context ? "--scrollmode" : "\\scrollmode\\input"; - System(cmd,0); - } - } - return status; -} - -char *dvisvgmCommand(mem::vector<string>& cmd, const string &in, const string& out) -{ - cmd.push_back(getSetting<string>("dvisvgm")); - cmd.push_back("-n"); - cmd.push_back("-v3"); - string libgs=getSetting<string>("libgs"); - if(!libgs.empty()) - cmd.push_back("--libgs="+libgs); -// cmd.push_back("--optimize"); // Requires dvisvgm > 2.9.1 - push_split(cmd,getSetting<string>("dvisvgmOptions")); - char *tmpdir=mkdtemp(StrdupMalloc(tempdir+"/dvisvgmXXXXXX")); - if(tmpdir) - cmd.push_back("--tmpdir="+string(tmpdir)); - cmd.push_back("-o"+out); - cmd.push_back(in); - return tmpdir; -} - -void rmtmpdir(char *tmpdir) -{ - if(tmpdir) { - recursive_delete(tmpdir); - free(tmpdir); - } -} - -bool picture::texprocess(const string& texname, const string& outname, - const string& prefix, const pair& bboxshift, - bool svg) -{ - int status=1; - ifstream outfile; - - outfile.open(texname.c_str()); - bool keep=getSetting<bool>("keep"); - - if(outfile) { - outfile.close(); - - status=opentex(texname,prefix); - string texengine=getSetting<string>("tex"); - - if(status == 0) { - string dviname=auxname(prefix,"dvi"); - mem::vector<string> cmd; - - if(svg) { - char *tmpdir=dvisvgmCommand(cmd,dviname,outname); - ostringstream buf; - bbox B=svgbbox(b,bboxshift); - buf << "--bbox=" - << B.left << "bp " - << B.bottom << "bp " - << B.right << "bp " - << B.top << "bp"; - cmd.push_back(buf.str()); - status=System(cmd,0,true,"dvisvgm"); - rmtmpdir(tmpdir); - if(!keep) - unlink(dviname.c_str()); - } else { - if(!settings::pdf(texengine)) { - string psname=auxname(prefix,"ps"); - double height=b.top-b.bottom+1.0; - - // Magic dvips offsets: - double hoffset=-128.4; - double vertical=height; - if(!latex(texengine)) vertical += 2.0; - double voffset=(vertical < 13.0) ? -137.8+vertical : -124.8; - double paperHeight=getSetting<double>("paperheight"); - - hoffset += b.left+bboxshift.getx(); - voffset += paperHeight-height-b.bottom-bboxshift.gety(); - - string dvipsrc=getSetting<string>("dir"); - if(dvipsrc.empty()) dvipsrc=systemDir; - dvipsrc += dirsep+"nopapersize.ps"; - setenv("DVIPSRC",dvipsrc.c_str(),1); - string papertype=getSetting<string>("papertype") == "letter" ? - "letterSize" : "a4size"; - cmd.push_back(getSetting<string>("dvips")); - cmd.push_back("-R"); - cmd.push_back("-Pdownload35"); - cmd.push_back("-D600"); - cmd.push_back("-O"+String(hoffset)+"bp,"+String(voffset)+"bp"); - bool ps=havenewpage(); - if(ps) - cmd.push_back("-T"+String(getSetting<double>("paperwidth"))+"bp,"+ - String(paperHeight)+"bp"); - else - cmd.push_back("-E"); - push_split(cmd,getSetting<string>("dvipsOptions")); - if(ps && getSetting<string>("papertype") != "") - cmd.push_back("-t"+papertype); - if(verbose <= 1) cmd.push_back("-q"); - cmd.push_back("-o"+psname); - cmd.push_back(dviname); - status=System(cmd,0,true,"dvips"); - if(status == 0) { - ifstream fin(psname.c_str()); - psfile fout(outname,false); - - string s; - bool first=true; - transform t=shift(bboxshift)*T; - bool shift=!t.isIdentity(); - - const string beginspecial="TeXDict begin @defspecial"; - const size_t beginlength=beginspecial.size(); - const string endspecial="@fedspecial end"; - const size_t endlength=endspecial.size(); - - while(getline(fin,s)) { - if (s[0] == '%') { - if (s.find("%%DocumentPaperSizes:") == 0) - continue; - - if(s.find("%!PS-Adobe-") == 0) { - fout.header(!ps); - continue; - } - - if (first && s.find("%%BoundingBox:") == 0) { - bbox box=b; - box.shift(bboxshift); - if(verbose > 2) BoundingBox(cout,box); - fout.BoundingBox(box); - first=false; - continue; - } - } - - if (shift) { - if (s.compare(0, beginlength, beginspecial) == 0) { - fout.verbatimline(s); - fout.gsave(); - fout.concat(t); - continue; - } - if (s.compare(0, endlength, endspecial) == 0) { - fout.grestore(); - fout.verbatimline(s); - continue; - } - } - - // For the default line, output it unchanged. - fout.verbatimline(s); - } - } - if(!keep) { - unlink(dviname.c_str()); - unlink(psname.c_str()); - } - } - } - } - - if(!keep) { - unlink(texname.c_str()); - if(!getSetting<bool>("keepaux")) - unlink(auxname(prefix,"aux").c_str()); - unlink(auxname(prefix,"log").c_str()); - unlink(auxname(prefix,"out").c_str()); - if(settings::context(texengine)) { - unlink(auxname(prefix,"top").c_str()); - unlink(auxname(prefix,"tua").c_str()); - unlink(auxname(prefix,"tuc").c_str()); - unlink(auxname(prefix,"tui").c_str()); - unlink(auxname(prefix,"tuo").c_str()); - } - } - if(status == 0) return true; - } - return false; -} - -int picture::epstopdf(const string& epsname, const string& pdfname) -{ - string compress=getSetting<bool>("compress") ? "true" : "false"; - mem::vector<string> cmd; - cmd.push_back(getSetting<string>("gs")); - cmd.push_back("-q"); - cmd.push_back("-dNOPAUSE"); - cmd.push_back("-dBATCH"); - cmd.push_back("-P"); - if(safe) - cmd.push_back("-dSAFER"); - cmd.push_back("-dALLOWPSTRANSPARENCY"); // Support transparency extensions. - cmd.push_back("-sDEVICE=pdfwrite"); - cmd.push_back("-dEPSCrop"); - cmd.push_back("-dSubsetFonts=true"); - cmd.push_back("-dEmbedAllFonts=true"); - cmd.push_back("-dMaxSubsetPct=100"); - cmd.push_back("-dEncodeColorImages="+compress); - cmd.push_back("-dEncodeGrayImages="+compress); - cmd.push_back("-dCompatibilityLevel=1.4"); - if(!getSetting<bool>("autorotate")) - cmd.push_back("-dAutoRotatePages=/None"); - cmd.push_back("-g"+String(max(ceil(getSetting<double>("paperwidth")),1.0)) - +"x"+String(max(ceil(getSetting<double>("paperheight")),1.0))); - cmd.push_back("-dDEVICEWIDTHPOINTS="+String(max(b.right-b.left,3.0))); - cmd.push_back("-dDEVICEHEIGHTPOINTS="+String(max(b.top-b.bottom,3.0))); - push_split(cmd,getSetting<string>("gsOptions")); - cmd.push_back("-sOutputFile="+stripDir(pdfname)); - if(safe) { - cmd.push_back("-c"); - cmd.push_back(".setsafe"); - cmd.push_back("-f"); - } - cmd.push_back(stripDir(epsname)); - - char *oldPath=NULL; - string dir=stripFile(pdfname); - if(!dir.empty()) { - oldPath=getPath(); - setPath(dir.c_str()); - } - int status=System(cmd,0,true,"gs","Ghostscript"); - if(oldPath != NULL) - setPath(oldPath); - return status; -} - -int picture::pdftoeps(const string& pdfname, const string& epsname, bool eps) -{ - mem::vector<string> cmd; - cmd.push_back(getSetting<string>("gs")); - cmd.push_back("-q"); - cmd.push_back("-dNOCACHE"); - cmd.push_back("-dNOPAUSE"); - cmd.push_back("-dBATCH"); - cmd.push_back("-P"); - if(safe) - cmd.push_back("-dSAFER"); - string texengine=getSetting<string>("tex"); - cmd.push_back("-sDEVICE="+getSetting<string>(eps ? "epsdriver": "psdriver")); - cmd.push_back("-sOutputFile="+stripDir(epsname)); - cmd.push_back(stripDir(pdfname)); - - char *oldPath=NULL; - string dir=stripFile(epsname); - if(!dir.empty()) { - oldPath=getPath(); - setPath(dir.c_str()); - } - int status=System(cmd,0,true,"gs","Ghostscript"); - if(oldPath != NULL) - setPath(oldPath); - return status; -} - -bool picture::reloadPDF(const string& Viewer, const string& outname) const -{ - static bool needReload=true; - static bool haveReload=false; - - string reloadprefix="reload"; - if(needReload) { - needReload=false; - string name=getPath()+string("/")+outname; - // Write javascript code to redraw picture. - runString("settings.tex='pdflatex'; tex('\\ \\pdfannot width 0pt height 0pt { /AA << /PO << /S /JavaScript /JS (try{reload(\""+name+"\");} catch(e) {} closeDoc(this);) >> >> }'); shipout('"+reloadprefix+"',wait=false,view=false);erase();exit();",false); - haveReload=true; - } - - if(haveReload) { - mem::vector<string> cmd; - push_command(cmd,Viewer); - string pdfreloadOptions=getSetting<string>("pdfreloadOptions"); - if(!pdfreloadOptions.empty()) - cmd.push_back(pdfreloadOptions); - cmd.push_back(reloadprefix+".pdf"); - System(cmd,0,false); - } - return true; -} - -int picture::epstosvg(const string& epsname, const string& outname) -{ - mem::vector<string> cmd; - char *tmpdir=dvisvgmCommand(cmd,epsname,outname); - cmd.push_back("-E"); - int status=System(cmd,0,true,"dvisvgm"); - rmtmpdir(tmpdir); - if(!getSetting<bool>("keep")) - unlink(epsname.c_str()); - return status; -} - -int picture::pdftosvg(const string& pdfname, const string& outname) -{ - mem::vector<string> cmd; - char *tmpdir=dvisvgmCommand(cmd,pdfname,outname); - cmd.push_back("--pdf"); - int status=System(cmd,0,true,"dvisvgm"); - rmtmpdir(tmpdir); - if(status == 0 && !getSetting<bool>("keep")) - unlink(pdfname.c_str()); - return status; -} - -void htmlView(string name) -{ - mem::vector<string> cmd; - push_command(cmd,getSetting<string>("htmlviewer")); -#ifdef __MSDOS__ - ssize_t size=cygwin_conv_path(CCP_POSIX_TO_WIN_A, - locateFile(name,true).c_str(),NULL,0); - if(size <= 0) return; - char filename[size]; - size=cygwin_conv_path(CCP_POSIX_TO_WIN_A,locateFile(name,true).c_str(), - filename,size); - cmd.push_back("file://"+string(filename)); -#else - cmd.push_back(locateFile(name,true)); -#endif - push_split(cmd,getSetting<string>("htmlviewerOptions")); - System(cmd,2,false); -} - -bool picture::postprocess(const string& prename, const string& outname, - const string& outputformat, - bool wait, bool view, bool pdftex, - bool epsformat, bool svg) -{ - int status=0; - bool pdf=settings::pdf(getSetting<string>("tex")); - bool pdfformat=(pdf && outputformat == "") || outputformat == "pdf"; - - mem::vector<string> cmd; - if(pdftex || !epsformat) { - if(pdfformat) { - if(pdftex) { - status=rename(prename.c_str(),outname.c_str()); - if(status != 0) - reportError("Cannot rename "+prename+" to "+outname); - } else status=epstopdf(prename,outname); - } else if(epsformat) { - if(svg) { - bool haveShading=pdf && havepng(); - if(!haveShading) - status=pdftosvg(prename,outname); - if(haveShading || status != 0) { - // Dvisvgm version < 2.4 doesn't support --pdf - // Dvisvgm --pdf doesn't support shading - string psname=stripExt(prename)+".ps"; - status=pdftoeps(prename,psname,false); - if(status != 0) return false; - status=epstosvg(psname,outname); - } - epsformat=false; - } else - status=pdftoeps(prename,outname); - } else { - double render=fabs(getSetting<double>("render")); - if(render == 0) render=1.0; - double res=render*72.0; - Int antialias=getSetting<Int>("antialias"); - if(outputformat == "png" && antialias == 2) { - cmd.push_back(getSetting<string>("gs")); - cmd.push_back("-q"); - cmd.push_back("-dNOPAUSE"); - cmd.push_back("-dBATCH"); - cmd.push_back("-P"); - cmd.push_back("-sDEVICE=pngalpha"); - cmd.push_back("-dEPSCrop"); - if(safe) - cmd.push_back("-dSAFER"); - cmd.push_back("-r"+String(res)+"x"+String(res)); - push_split(cmd,getSetting<string>("gsOptions")); - cmd.push_back("-sOutputFile="+outname); - cmd.push_back(prename); - status=System(cmd,0,true,"gs","Ghostscript"); - } else if(!svg && !getSetting<bool>("xasy")) { - double expand=antialias; - if(expand < 2.0) expand=1.0; - res *= expand; - cmd.push_back(getSetting<string>("convert")); - cmd.push_back("-density"); - cmd.push_back(String(res)+"x"+String(res)); - if(expand == 1.0) - cmd.push_back("+antialias"); - push_split(cmd,getSetting<string>("convertOptions")); - cmd.push_back("-resize"); - cmd.push_back(String(100.0/expand)+"%x"); - if(outputformat == "jpg") cmd.push_back("-flatten"); - cmd.push_back(prename); - cmd.push_back(outputformat+":"+outname); - status=System(cmd,0,true,"convert"); - } - } - if(!getSetting<bool>("keep")) - unlink(prename.c_str()); - } - if(status != 0) return false; - - if(verbose > 0) - cout << "Wrote " << outname << endl; - - return display(outname,outputformat,wait,view,epsformat); -} - -bool picture::display(const string& outname, const string& outputformat, - bool wait, bool view, bool epsformat) -{ - int status=0; - static mem::map<CONST string,int> pids; - bool View=settings::view() && view; - - if(View) { - bool pdf=settings::pdf(getSetting<string>("tex")); - bool pdfformat=(pdf && outputformat == "") || outputformat == "pdf"; - - if(epsformat || pdfformat) { - // Check to see if there is an existing viewer for this outname. - mem::map<CONST string,int>::iterator p=pids.find(outname); - bool running=(p != pids.end()); - string Viewer=pdfformat ? getSetting<string>("pdfviewer") : - getSetting<string>("psviewer"); - int pid; - if(running) { - pid=p->second; - if(pid) - running=(waitpid(pid, &status, WNOHANG) != pid); - } - - bool pdfreload=pdfformat && getSetting<bool>("pdfreload"); - if(running) { - // Tell gv/acroread to reread file. - if(Viewer == "gv") kill(pid,SIGHUP); - else if(pdfreload) - reloadPDF(Viewer,outname); - } else { - mem::vector<string> cmd; - push_command(cmd,Viewer); - string viewerOptions=getSetting<string>(pdfformat ? - "pdfviewerOptions" : - "psviewerOptions"); - if(!viewerOptions.empty()) - push_split(cmd,viewerOptions); - cmd.push_back(outname); - status=System(cmd,0,wait, - pdfformat ? "pdfviewer" : "psviewer", - pdfformat ? "your PDF viewer" : "your PostScript viewer", - &pid); - if(status != 0) return false; - - if(!wait) pids[outname]=pid; - - if(pdfreload) { - // Work around race conditions in acroread initialization script - usleep(getSetting<Int>("pdfreloaddelay")); - // Only reload if pdf viewer process is already running. - if(waitpid(pid, &status, WNOHANG) == pid) - reloadPDF(Viewer,outname); - } - } - } else { - if(outputformat == "svg" || outputformat == "html") - htmlView(outname); - else { - mem::vector<string> cmd; - push_command(cmd,getSetting<string>("display")); - cmd.push_back(outname); - string application="your "+outputformat+" viewer"; - status=System(cmd,0,wait,"display",application.c_str()); - if(status != 0) return false; - } - } - } - - return true; -} - -string Outname(const string& prefix, const string& outputformat, - bool standardout, string aux="") -{ - return standardout ? "-" : buildname(prefix,outputformat,aux); -} - -bool picture::shipout(picture *preamble, const string& Prefix, - const string& format, bool wait, bool view) -{ - bool keep=getSetting<bool>("keep"); - - string aux=""; - b=bounds(); - bool empty=b.empty; - - string outputformat=format.empty() ? defaultformat() : format; - - bool htmlformat=outputformat == "html"; - if(htmlformat) { - outputformat="svg"; - aux="_"; - if(view) view=false; - else htmlformat=false; - } - - bool svgformat=outputformat == "svg"; - - string texengine=getSetting<string>("tex"); - string texengineSave; - - if(!empty && svgformat && texengine == "latex" && havepng()) { - texengineSave=texengine; - Setting("tex")=texengine="pdflatex"; - } - - bool usetex=texengine != "none"; - bool TeXmode=getSetting<bool>("inlinetex") && usetex; - bool pdf=settings::pdf(texengine); - - bool standardout=Prefix == "-"; - string prefix=standardout ? standardprefix : stripExt(Prefix); - - string preformat=nativeformat(); - bool epsformat=outputformat == "eps"; - bool pdfformat=pdf || outputformat == "pdf"; - bool dvi=false; - bool svg=svgformat && usetex && - (!have3D() || getSetting<double>("render") == 0.0); - if(svg) { - if(pdf) epsformat=true; - else dvi=true; - } - - string outname=Outname(prefix,outputformat,standardout,aux); - string epsname=epsformat ? (standardout ? "" : outname) : - auxname(prefix,"eps"); - - bool Labels=labels || TeXmode; - - if(outputformat == "png" && (b.right-b.left < 1.0 || b.top-b.bottom < 1.0)) - empty=true; - - if(empty && !Labels) { // Output a null file - bbox b; - b.left=b.bottom=0; - b.right=b.top=1; - psfile out(epsname,false); - out.prologue(b); - out.epilogue(); - out.close(); - return postprocess(epsname,outname,outputformat,wait,view,false, - epsformat,false); - } - - Labels |= svg; - - if(Labels) - prefix=cleanpath(prefix); - - string prename=((epsformat && !pdf) || !Labels) ? epsname : - auxname(prefix,preformat); - - SetPageDimensions(); - - pair aligndir=getSetting<pair>("aligndir"); - string origin=getSetting<string>("align"); - - pair bboxshift=(origin == "Z" && epsformat) ? - pair(0.0,0.0) : pair(-b.left,-b.bottom); - - if(epsformat) { - bboxshift += getSetting<pair>("offset"); - double yexcess=max(getSetting<double>("paperheight")- - (b.top-b.bottom+1.0),0.0); - double xexcess=max(getSetting<double>("paperwidth")- - (b.right-b.left+1.0),0.0); - if(aligndir == pair(0,0)) { - if(origin != "Z" && origin != "B") { - if(origin == "T") bboxshift += pair(0.0,yexcess); - else bboxshift += pair(0.5*xexcess,0.5*yexcess); - } - } else { - double scale=max(fabs(aligndir.getx()),fabs(aligndir.gety())); - if(scale != 0) aligndir *= 0.5/scale; - bboxshift += - pair((aligndir.getx()+0.5)*xexcess,(aligndir.gety()+0.5)*yexcess); - } - } else if(svg) - bboxshift += pair(-b.left,b.top); - - bool status=true; - - string texname; - texfile *tex=NULL; - - if(Labels) { - texname=TeXmode ? buildname(prefix,"tex") : auxname(prefix,"tex"); - tex=dvi ? new svgtexfile(texname,b) : new texfile(texname,b); - tex->prologue(); - } - - nodelist::iterator layerp=nodes.begin(); - nodelist::iterator p=layerp; - unsigned layer=0; - mem::list<string> files; - - bbox bshift=b; - - int svgcount=0; - - typedef mem::list<drawElement *> clipstack; - clipstack begin; - - while(p != nodes.end()) { - string psname,pdfname; - if(Labels) { - ostringstream buf; - buf << prefix << "_" << layer; - psname=buildname(buf.str(),"eps"); - if(pdf) pdfname=buildname(buf.str(),"pdf"); - } else { - psname=epsname; - bshift.shift(bboxshift); - } - files.push_back(psname); - if(pdf) files.push_back(pdfname); - psfile out(psname,pdfformat); - out.prologue(bshift); - - if(!Labels) { - out.gsave(); - out.translate(bboxshift); - } - - if(preamble) { - // Postscript preamble. - nodelist Nodes=preamble->nodes; - nodelist::iterator P=Nodes.begin(); - if(P != Nodes.end()) { - out.resetpen(); - for(; P != Nodes.end(); ++P) { - assert(*P); - (*P)->draw(&out); - } - } - } - out.resetpen(); - - bool postscript=false; - drawLabel *L=NULL; - - if(dvi) - for(nodelist::const_iterator r=begin.begin(); r != begin.end(); ++r) - (*r)->draw(&out); - - processDataStruct &pd=processData(); - - for(; p != nodes.end(); ++p) { - assert(*p); - if(Labels && (*p)->islayer()) break; - - if(dvi && (*p)->svg()) { - picture *f=(*p)->svgpng() ? new picture : NULL; - nodelist::const_iterator q=layerp; - for(;;) { - if((*q)->beginclip()) - begin.push_back(*q); - else if((*q)->endclip()) { - if(begin.size() < 1) - reportError("endclip without matching beginclip"); - begin.pop_back(); - } - if(q == p) break; - ++q; - } - - if(f) { - for(nodelist::const_iterator r=begin.begin(); r != begin.end(); ++r) - f->append(*r); - - f->append(*(q++)); - } - - while(q != nodes.end() && !(*q)->islayer()) ++q; - - clipstack end; - - for(nodelist::const_iterator r=--q;; --r) { - if((*r)->beginclip() && end.size() >= 1) - end.pop_back(); - else if((*r)->endclip()) - end.push_back(*r); - if(r == p) break; - } - - for(nodelist::reverse_iterator r=end.rbegin(); r != end.rend(); - ++r) { - (*r)->draw(&out); - if(f) - f->append(*r); - } - - if(f) { - ostringstream buf; - buf << prefix << "_" << svgcount; - ++svgcount; - string pngname=buildname(buf.str(),"png"); - f->shipout(preamble,buf.str(),"png",false,false); - pair m=f->bounds().Min(); - pair M=f->bounds().Max(); - delete f; - - pair size=M-m; - ostringstream cmd; - cmd << "\\special{dvisvgm:img " << size.getx()*ps2tex << " " - << size.gety()*ps2tex << " " << pngname << "}"; - static pen P; - static pair zero; - L=new drawLabel(cmd.str(),"",identity,pair(m.getx(),M.gety()),zero,P); - texinit(); - L->bounds(b_cached,pd.tex,labelbounds,bboxstack); - postscript=true; - } - break; - } else postscript |= (*p)->draw(&out); - } - - if(Labels) { - if(!svg || pdf) - tex->beginlayer(pdf ? pdfname : psname,postscript); - } else out.grestore(); - - out.epilogue(); - out.close(); - - if(Labels) { - tex->resetpen(); - if(pdf && !b.empty) { - status=(epstopdf(psname,pdfname) == 0); - if(!keep) unlink(psname.c_str()); - } - - if(status) { - for (p=layerp; p != nodes.end(); ++p) { - assert(*p); - bool islayer=(*p)->islayer(); - if(dvi && (*p)->svg()) { - islayer=true; - if((*p)->svgpng()) - L->write(tex,b); - else - (*p)->draw(tex); - } else - (*p)->write(tex,b); - if(islayer) { - tex->endlayer(); - layerp=++p; - layer++; - break; - } - } - } - } - } - - bool context=settings::context(texengine); - if(status) { - if(TeXmode) { - if(Labels && verbose > 0) cout << "Wrote " << texname << endl; - delete tex; - } else { - if(Labels) { - tex->epilogue(); - if(context) prefix=stripDir(prefix); - status=texprocess(texname,dvi ? outname : prename,prefix, - bboxshift,dvi); - delete tex; - if(!keep) { - for(mem::list<string>::iterator p=files.begin(); p != files.end(); - ++p) - unlink(p->c_str()); - } - } - if(status) { - if(context) prename=stripDir(prename); - status=postprocess(prename,outname,outputformat,wait, - view,pdf && Labels,epsformat,svg); - if(pdfformat && !keep) { - unlink(auxname(prefix,"m9").c_str()); - unlink(auxname(prefix,"pbsdat").c_str()); - } - } - } - } - - if(!status) reportError("shipout failed"); - - if(!texengineSave.empty()) Setting("tex")=texengineSave; - - if(htmlformat) { - jsfile out; - out.svgtohtml(prefix); - string name=buildname(prefix,"html"); - display(name,"html",wait,true,false); - if(!keep) - unlink(outname.c_str()); - } - - return true; -} - -// render viewport with width x height pixels. -void picture::render(double size2, const triple& Min, const triple& Max, - double perspective, bool remesh) const -{ - for(nodelist::const_iterator p=nodes.begin(); p != nodes.end(); ++p) { - assert(*p); - if(remesh) (*p)->meshinit(); - (*p)->render(size2,Min,Max,perspective,remesh); - } - -#ifdef HAVE_GL - drawBuffers(); -#endif -} - -struct Communicate : public gc { - string prefix; - picture* pic; - string format; - double width; - double height; - double angle; - double zoom; - triple m; - triple M; - pair shift; - pair margin; - double *t; - double *background; - size_t nlights; - triple *lights; - double *diffuse; - double *specular; - bool view; -}; - -Communicate com; - -extern bool allowRender; - -void glrenderWrapper() -{ -#ifdef HAVE_GL -#ifdef HAVE_PTHREAD - wait(initSignal,initLock); - endwait(initSignal,initLock); -#endif - if(allowRender) - glrender(com.prefix,com.pic,com.format,com.width,com.height,com.angle, - com.zoom,com.m,com.M,com.shift,com.margin,com.t,com.background, - com.nlights,com.lights,com.diffuse,com.specular,com.view); -#endif -} - -bool picture::shipout3(const string& prefix, const string& format, - double width, double height, double angle, double zoom, - const triple& m, const triple& M, const pair& shift, - const pair& margin, double *t, double *background, - size_t nlights, triple *lights, double *diffuse, - double *specular, bool view) -{ - if(getSetting<bool>("interrupt")) - return true; - - bool webgl=format == "html"; - -#ifndef HAVE_LIBGLM - if(webgl) - camp::reportError("to support WebGL rendering, please install glm header files, run ./configure, and recompile"); -#endif - - picture *pic = new picture; - - matrixstack ms; - for(nodelist::const_iterator p=nodes.begin(); p != nodes.end(); ++p) { - assert(*p); - if((*p)->begingroup3()) - ms.push((*p)->transf3()); - else if((*p)->endgroup3()) - ms.pop(); - else - pic->append((*p)->transformed(ms.T())); - } - - pic->b3=bbox3(); - for(nodelist::iterator p=pic->nodes.begin(); p != pic->nodes.end(); ++p) { - assert(*p); - (*p)->bounds(pic->b3); - } - pic->lastnumber3=pic->nodes.size(); - - for(nodelist::iterator p=pic->nodes.begin(); p != pic->nodes.end(); ++p) { - assert(*p); - (*p)->displacement(); - } - - const string outputformat=format.empty() ? - getSetting<string>("outformat") : format; - -#ifdef HAVE_LIBGLM - static int oldpid=0; - bool View=settings::view() && view; -#endif - -#ifdef HAVE_GL - bool offscreen=false; -#ifdef HAVE_LIBOSMESA - offscreen=true; -#endif -#ifdef HAVE_PTHREAD - bool animating=getSetting<bool>("animating"); - bool Wait=!interact::interactive || !View || animating; -#endif -#endif - - if(!webgl) { -#ifdef HAVE_GL - if(glthread && !offscreen) { -#ifdef HAVE_PTHREAD - if(gl::initialize) { - gl::initialize=false; - com.prefix=prefix; - com.pic=pic; - com.format=outputformat; - com.width=width; - com.height=height; - com.angle=angle; - com.zoom=zoom; - com.m=m; - com.M=M; - com.shift=shift; - com.margin=margin; - com.t=t; - com.background=background; - com.nlights=nlights; - com.lights=lights; - com.diffuse=diffuse; - com.specular=specular; - com.view=View; - if(Wait) - pthread_mutex_lock(&readyLock); - wait(initSignal,initLock); - endwait(initSignal,initLock); - static bool initialize=true; - if(initialize) { - wait(initSignal,initLock); - endwait(initSignal,initLock); - initialize=false; - } - if(Wait) { - pthread_cond_wait(&readySignal,&readyLock); - pthread_mutex_unlock(&readyLock); - } - return true; - } - if(Wait) - pthread_mutex_lock(&readyLock); -#endif - } else { - int pid=fork(); - if(pid == -1) - camp::reportError("Cannot fork process"); - if(pid != 0) { - oldpid=pid; - waitpid(pid,NULL,interact::interactive && View ? WNOHANG : 0); - return true; - } - } -#endif - } - -#if HAVE_LIBGLM - glrender(prefix,pic,outputformat,width,height,angle,zoom,m,M,shift,margin,t, - background,nlights,lights,diffuse,specular,View,oldpid); - - if(webgl) { - jsfile js; - string name=buildname(prefix,format); - js.open(name); - - for(nodelist::iterator p=pic->nodes.begin(); p != pic->nodes.end(); ++p) { - assert(*p); - (*p)->write(&js); - } - js.finish(name); - if(View) - htmlView(name); - return true; - } -#endif - -#ifdef HAVE_GL -#ifdef HAVE_PTHREAD - if(glthread && !offscreen && Wait) { - pthread_cond_wait(&readySignal,&readyLock); - pthread_mutex_unlock(&readyLock); - } - return true; -#endif -#endif - - return false; -} - -bool picture::shipout3(const string& prefix, const string format) -{ - bounds3(); - bool status; - - string name=buildname(prefix,"prc"); - prcfile prc(name); - - static const double limit=2.5*10.0/INT_MAX; - double compressionlimit=max(length(b3.Max()),length(b3.Min()))*limit; - - groups.push_back(groupmap()); - for(nodelist::iterator p=nodes.begin(); p != nodes.end(); ++p) { - assert(*p); - (*p)->write(&prc,&billboard,compressionlimit,groups); - } - groups.pop_back(); - status=prc.finish(); - - if(!status) reportError("shipout3 failed"); - - if(verbose > 0) cout << "Wrote " << name << endl; - - return true; -} - -picture *picture::transformed(const transform& t) -{ - picture *pic = new picture; - - nodelist::iterator p; - for (p = nodes.begin(); p != nodes.end(); ++p) { - assert(*p); - pic->append((*p)->transformed(t)); - } - pic->T=transform(t*T); - - return pic; -} - -picture *picture::transformed(const array& t) -{ - picture *pic = new picture; - double* T=NULL; - copyArray4x4C(T,&t); - size_t level = 0; - for (nodelist::iterator p = nodes.begin(); p != nodes.end(); ++p) { - assert(*p); - if(level==0) - pic->append((*p)->transformed(T)); - else - pic->append(*p); - if((*p)->begingroup3()) - level++; - if((*p)->endgroup3()) { - if(level==0) - reportError("endgroup3 without matching begingroup3"); - else - level--; - } - } - - return pic; -} - - -} // namespace camp |