diff options
Diffstat (limited to 'Build/source/utils/asymptote/runpicture.in')
-rw-r--r-- | Build/source/utils/asymptote/runpicture.in | 605 |
1 files changed, 605 insertions, 0 deletions
diff --git a/Build/source/utils/asymptote/runpicture.in b/Build/source/utils/asymptote/runpicture.in new file mode 100644 index 00000000000..20686c1b6b7 --- /dev/null +++ b/Build/source/utils/asymptote/runpicture.in @@ -0,0 +1,605 @@ +/***** + * runpicture.in + * + * Runtime functions for picture operations. + * + *****/ + +pen => primPen() +pair => primPair() +triple => primTriple() +path => primPath() +path3 => primPath3() +picture* => primPicture() +Intarray* => IntArray() +realarray* => realArray() +realarray2* => realArray2() +patharray* => pathArray() +penarray* => penArray() +penarray2* => penArray2() +pairarray* => pairArray() +pairarray2* => pairArray2() +triplearray* => tripleArray() +triplearray2* => tripleArray2() +transform => primTransform() +callableTransform* => transformFunction() + +#include "picture.h" +#include "drawelement.h" +#include "path.h" +#include "array.h" +#include "arrayop.h" +#include "drawpath.h" +#include "drawfill.h" +#include "drawclipbegin.h" +#include "drawclipend.h" +#include "drawgsave.h" +#include "drawgrestore.h" +#include "drawgroup.h" +#include "drawverbatim.h" +#include "drawlabel.h" +#include "drawlayer.h" +#include "drawimage.h" +#include "drawpath3.h" +#include "drawsurface.h" + +using namespace camp; +using namespace settings; +using namespace vm; + +typedef array Intarray; +typedef array realarray; +typedef array realarray2; +typedef array pairarray; +typedef array pairarray2; +typedef array triplearray; +typedef array triplearray2; +typedef array patharray; +typedef array penarray; +typedef array penarray2; + +typedef callable callableTransform; + +using types::IntArray; +using types::realArray; +using types::realArray2; +using types::pairArray; +using types::pairArray2; +using types::tripleArray; +using types::tripleArray2; +using types::pathArray; +using types::penArray; +using types::penArray2; + +function *transformFunction() +{ + return new function(primTransform()); +} + +// Ignore unclosed begingroups but not spurious endgroups. +const char *nobegin="endgroup without matching begingroup"; + +array *emptyarray=new array(0); + +array *nop(array *a) +{ + return a; +} + +// Autogenerated routines: + + +picture* :newPicture() +{ + return new picture(); +} + +bool empty(picture *f) +{ + return f->null(); +} + +void erase(picture *f) +{ + f->nodes.clear(); +} + +pair min(picture *f) +{ + return f->bounds().Min(); +} + +pair max(picture *f) +{ + return f->bounds().Max(); +} + +void _draw(picture *f, path g, pen p) +{ + f->append(new drawPath(g,p)); +} + +void fill(picture *f, patharray *g, pen p=CURRENTPEN, bool copy=true) +{ + array *(*copyarray)(array *a)=copy ? copyArray: nop; + f->append(new drawFill(*copyarray(g),false,p)); +} + +void latticeshade(picture *f, patharray *g, bool stroke=false, + pen fillrule=CURRENTPEN, penarray2 *p, bool copy=true) +{ + array *(*copyarray)(array *a)=copy ? copyArray: nop; + f->append(new drawLatticeShade(*copyarray(g),stroke,fillrule,*copyarray(p))); +} + +void axialshade(picture *f, patharray *g, bool stroke=false, pen pena, pair a, + pen penb, pair b, bool copy=true) +{ + array *(*copyarray)(array *a)=copy ? copyArray: nop; + f->append(new drawAxialShade(*copyarray(g),stroke,pena,a,penb,b)); +} + +void radialshade(picture *f, patharray *g, bool stroke=false, pen pena, + pair a, real ra, pen penb, pair b, real rb, bool copy=true) +{ + array *(*copyarray)(array *a)=copy ? copyArray: nop; + f->append(new drawRadialShade(*copyarray(g),stroke,pena,a,ra,penb,b,rb)); +} + +void gouraudshade(picture *f, patharray *g, bool stroke=false, + pen fillrule=CURRENTPEN, penarray *p, pairarray *z, + Intarray *edges, bool copy=true) +{ + array *(*copyarray)(array *a)=copy ? copyArray: nop; + checkArrays(p,z); + checkArrays(z,edges); + f->append(new drawGouraudShade(*copyarray(g),stroke,fillrule,*copyarray(p), + *copyarray(z),*copyarray(edges))); +} + +void gouraudshade(picture *f, patharray *g, bool stroke=false, + pen fillrule=CURRENTPEN, penarray *p, Intarray *edges, + bool copy=true) +{ + array *(*copyarray)(array *a)=copy ? copyArray: nop; + size_t n=checkArrays(p,edges); + size_t m=checkArray(g); + array *z=new array(n); + Int k=0; + Int in=(Int) n; + for(size_t j=0; j < m; ++j) { + path *P=read<path *>(g,j); + assert(P); + Int stop=Min(P->size(),in-k); + mem::vector<solvedKnot>& nodes=P->Nodes(); + for(Int i=0; i < stop; ++i) + (*z)[k++]=nodes[i].point; + } + checkArrays(p,z); + + f->append(new drawGouraudShade(*copyarray(g),stroke,fillrule,*copyarray(p), + *z,*copyarray(edges))); +} + +void tensorshade(picture *f, patharray *g, bool stroke=false, + pen fillrule=CURRENTPEN, penarray2 *p, patharray *b=NULL, + pairarray2 *z=emptyarray, bool copy=true) +{ + array *(*copyarray)(array *a)=copy ? copyArray: nop; + array *(*copyarray2)(array *a)=copy ? copyArray2: nop; + if(b == NULL) b=g; + size_t n=checkArrays(p,b); + size_t nz=checkArray(z); + if(nz != 0) + checkEqual(nz,n); + f->append(new drawTensorShade(*copyarray(g),stroke,fillrule,*copyarray2(p), + *copyarray(b),*copyarray2(z))); +} + +void functionshade(picture *f, patharray *g, bool stroke=false, + pen fillrule=CURRENTPEN, string shader=emptystring, + bool copy=true) +{ + array *(*copyarray)(array *a)=copy ? copyArray: nop; + f->append(new drawFunctionShade(*copyarray(g),stroke,fillrule,shader)); +} + +// Clip a picture to a superpath using the given fill rule. +// Subsequent additions to the picture will not be affected by the clipping. +void clip(picture *f, patharray *g, bool stroke=false, + pen fillrule=CURRENTPEN, bool copy=true) +{ + array *(*copyarray)(array *a)=copy ? copyArray: nop; + drawClipBegin *begin=new drawClipBegin(*copyarray(g),stroke,fillrule,true); + f->enclose(begin,new drawClipEnd(true,begin)); +} + +void beginclip(picture *f, patharray *g, bool stroke=false, + pen fillrule=CURRENTPEN, bool copy=true) +{ + array *(*copyarray)(array *a)=copy ? copyArray: nop; + f->append(new drawClipBegin(*copyarray(g),stroke,fillrule,false)); +} + +void endclip(picture *f) +{ + f->append(new drawClipEnd(false)); +} + +void gsave(picture *f) +{ + f->append(new drawGsave()); +} + +void grestore(picture *f) +{ + f->append(new drawGrestore()); +} + +void begingroup(picture *f, string name=emptystring) +{ + f->append(new drawBegin(name)); +} + +void endgroup(picture *f) +{ + f->append(new drawEnd()); +} + +void add(picture *dest, picture *src) +{ + dest->add(*src); +} + +void prepend(picture *dest, picture *src) +{ + dest->prepend(*src); +} + +void postscript(picture *f, string s) +{ + f->append(new drawVerbatim(PostScript,s)); +} + +void tex(picture *f, string s) +{ + f->append(new drawVerbatim(TeX,s)); +} + +void postscript(picture *f, string s, pair min, pair max) +{ + f->append(new drawVerbatim(PostScript,s,min,max)); +} + +void tex(picture *f, string s, pair min, pair max) +{ + f->append(new drawVerbatim(TeX,s,min,max)); +} + +void texpreamble(string s) +{ + string t=s+"\n"; + processDataStruct &pd=processData(); + pd.TeXpipepreamble.push_back(t); + pd.TeXpreamble.push_back(t); +} + +void deletepreamble() +{ + if(getSetting<bool>("inlinetex")) { + unlink(auxname(outname(),"pre").c_str()); + } +} + +void _labelpath(picture *f, string s, string size, path g, string justify, + pair offset, pen p) +{ + f->append(new drawLabelPath(s,size,g,justify,offset,p)); +} + +void texreset() +{ + processDataStruct &pd=processData(); + pd.TeXpipepreamble.clear(); + pd.TeXpreamble.clear(); + pd.tex.pipeclose(); +} + +void layer(picture *f) +{ + f->append(new drawLayer()); +} + +void newpage(picture *f) +{ + f->append(new drawNewPage()); +} + +void _image(picture *f, realarray2 *data, pair initial, pair final, + penarray *palette=NULL, transform t=identity, bool copy=true, + bool antialias=false) +{ + array *(*copyarray)(array *a)=copy ? copyArray: nop; + array *(*copyarray2)(array *a)=copy ? copyArray2: nop; + f->append(new drawImage(*copyarray2(data),*copyarray(palette), + t*matrix(initial,final),antialias)); +} + +void _image(picture *f, penarray2 *data, pair initial, pair final, + transform t=identity, bool copy=true, bool antialias=false) +{ + array *(*copyarray2)(array *a)=copy ? copyArray2: nop; + f->append(new drawImage(*copyarray2(data),t*matrix(initial,final),antialias)); +} + +string nativeformat() +{ + return nativeformat(); +} + +bool latex() +{ + return latex(getSetting<string>("tex")); +} + +bool pdf() +{ + return pdf(getSetting<string>("tex")); +} + +void shipout(string prefix=emptystring, picture *f, picture *preamble=NULL, + string format=emptystring, bool wait=false, bool view=true, + callableTransform *xform) +{ + if(prefix.empty()) prefix=outname(); + + picture *result=new picture; + unsigned level=0; + picture::nodelist::iterator p; + for(p = f->nodes.begin(); p != f->nodes.end(); ++p) { + xform->call(Stack); + transform t=pop<transform>(Stack); + static transform Zero=transform(0.0,0.0,0.0,0.0,0.0,0.0); + bool Delete=(t == Zero); + picture *group=new picture; + assert(*p); + if((*p)->endgroup()) error(nobegin); + if((*p)->begingroup()) { + ++level; + while(p != f->nodes.end() && level) { + if(!Delete) { + drawElement *e=t.isIdentity() ? *p : (*p)->transformed(t); + group->append(e); + } + ++p; + if(p == f->nodes.end()) break; + assert(*p); + if((*p)->begingroup()) ++level; + if((*p)->endgroup()) { + if(level) --level; + else error(nobegin); + } + } + } + if(p == f->nodes.end()) break; + assert(*p); + if(!Delete) { + drawElement *e=t.isIdentity() ? *p : (*p)->transformed(t); + group->append(e); + result->add(*group); + } + } + + result->shipout(preamble,prefix,format,0.0,wait,view); +} + +void shipout3(string prefix, picture *f, string format=emptystring, + real width, real height, real angle, real zoom, + triple m, triple M, pair shift, realarray2 *t, + realarray *background, triplearray *lights, realarray2 *diffuse, + realarray2 *ambient, realarray2 *specular, + bool viewportlighting, bool view=true) +{ + size_t n=checkArrays(lights,diffuse); + checkEqual(n,checkArray(ambient)); + checkEqual(n,checkArray(specular)); + + real *T=copyArray2C(t,true,4); + triple *Lights=copyTripleArrayC(lights); + real* Background=copyArrayC(background); + real *Diffuse=copyArray2C(diffuse,false,4); + real *Ambient=copyArray2C(ambient,false,4); + real *Specular=copyArray2C(specular,false,4); + + f->shipout3(prefix,format,width,height,angle,zoom,m,M,shift,T,Background,n, + Lights,Diffuse,Ambient,Specular,viewportlighting,view); + + delete[] Specular; + delete[] Ambient; + delete[] Diffuse; + delete[] Background; + delete[] Lights; + delete[] T; +} + +void shipout3(string prefix, picture *f) +{ + f->shipout3(prefix); +} + +void deconstruct(picture *f, picture *preamble=NULL, real magnification=1, + callableTransform *xform) +{ + unsigned level=0; + unsigned n=0; + + string prefix=outname(); + const string xformat="png"; + + static long arg_max=sysconf(_SC_ARG_MAX); + const unsigned maxargs=::min(arg_max/(prefix.size()+xformat.size()+25ul), + 256ul); + + cout << maxargs << newl; + + string preformat=nativeformat(); + const string Done="Done"; + const string Error="Error"; + + mem::vector<string> cmd; + + // Enforce ghostscript limitations. + magnification=::max(magnification,0.0001); + real res=::min(::max(magnification*72.0,2.0),8192.0); + + const char *converter=NULL, *hint=NULL; + + if(magnification > 0.0) { + mem::list<string> nameStack; + string outname; + unsigned arg=0; + unsigned batch=0; + for(picture::nodelist::iterator p=f->nodes.begin();;) { + if(p == f->nodes.end()) break; + if(arg == 0) { + cmd.clear(); + ostringstream buf; + buf << batch << "_"; + outname=buildname(prefix+buf.str()+"%d",xformat,""); + converter="gs"; + hint="Ghostscript"; + cmd.push_back(getSetting<string>(converter)); + cmd.push_back("-q"); + cmd.push_back("-dNOPAUSE"); + cmd.push_back("-dBATCH"); + cmd.push_back("-sDEVICE=pngalpha"); + cmd.push_back("-dEPSCrop"); + if(safe) + cmd.push_back("-dSAFER"); + cmd.push_back("-r"+String(res)+"x"+String(res)); + cmd.push_back("-sOutputFile="+outname); + } + + picture *group=new picture; + xform->call(Stack); + transform t=pop<transform>(Stack); + assert(*p); + if((*p)->endgroup()) { + cout << Error << endl; + error(nobegin); + } + if((*p)->begingroup()) { + ++level; + while(p != f->nodes.end() && level) { + drawElement *e=t.isIdentity() ? *p : (*p)->transformed(t); + group->append(e); + ++p; + if(p == f->nodes.end()) break; + assert(*p); + if((*p)->begingroup()) ++level; + if((*p)->endgroup()) { + if(level) --level; + else { + cout << Error << endl; + error(nobegin); + } + } + } + } + if(p != f->nodes.end()) { + assert(*p); + drawElement *e=t.isIdentity() ? *p : (*p)->transformed(t); + group->append(e); + bbox b; + ostringstream buf; + buf << prefix << "_" << n; + group->shipout(preamble,buf.str(),preformat,magnification,false,false); + string Preformat=group->Transparency() ? "pdf" : preformat; + string name=buildname(buf.str(),Preformat); + nameStack.push_back(name); + cmd.push_back(name); + b=group->bounds(); + b *= magnification; + + cout << b << newl; + ++n; + ++p; + ++arg; + } + + if(p == f->nodes.end() || arg >= maxargs) { + arg=0; + ++batch; + cout.flush(); + + int status=System(cmd,0,true,converter,hint); + if(status) { + cout << Error << endl; + error("deconstruct failed"); + } + } + } + + if(!getSetting<bool>("keep")) { + for(mem::list<string>::iterator p=nameStack.begin(); + p != nameStack.end(); ++p) + unlink(p->c_str()); + } + + cout << Done << endl; + } +} + + +// Three-dimensional picture and surface operations + +// Bezier curve +void _draw(picture *f, path3 g, pen p, string name=emptystring) +{ + if(g.size() > 0) + f->append(new drawPath3(g,p,name)); +} + +// Bezier patch +void draw(picture *f, triplearray2 *P, bool straight, penarray *p, real opacity, + real shininess, real PRCshininess, real granularity, triple normal, + penarray *colors, bool lighton, string name=emptystring) +{ + f->append(new drawSurface(*P,straight,*p,opacity,shininess,PRCshininess, + granularity,normal,*colors,lighton,name)); +} + +// General NURBS surface +void draw(picture *f, triplearray2 *P, realarray *uknot, realarray *vknot, + realarray2 *weights=emptyarray, penarray *p, + real opacity, real shininess, real PRCshininess, real granularity, + penarray *colors, bool lighton, string name=emptystring) +{ + f->append(new drawNurbs(*P,uknot,vknot,weights,*p,opacity,shininess, + PRCshininess,granularity,*colors,lighton,name)); +} + +triple min3(picture *f) +{ + return f->bounds3().Min(); +} + +triple max3(picture *f) +{ + return f->bounds3().Max(); +} + +pair minratio(picture *f) +{ + return f->ratio(::min); +} + +pair maxratio(picture *f) +{ + return f->ratio(::max); +} + +bool is3D(picture *f) +{ + return f->have3D(); +} |