diff options
author | Karl Berry <karl@freefriends.org> | 2013-04-02 23:03:22 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2013-04-02 23:03:22 +0000 |
commit | 324efbd652f973cd70f42fe08c665c518995bcbe (patch) | |
tree | 818ae382dfa133f3dcceec8e12e4cbd42be8bcf4 /Build/source/utils/asymptote/picture.cc | |
parent | bbf699abe485e707133ff3ba502119f261f27269 (diff) |
asy 2.21 sources (no runtime update)
git-svn-id: svn://tug.org/texlive/trunk@29618 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/utils/asymptote/picture.cc')
-rw-r--r-- | Build/source/utils/asymptote/picture.cc | 369 |
1 files changed, 342 insertions, 27 deletions
diff --git a/Build/source/utils/asymptote/picture.cc b/Build/source/utils/asymptote/picture.cc index 9a77cd4d592..6ac8be8dcfc 100644 --- a/Build/source/utils/asymptote/picture.cc +++ b/Build/source/utils/asymptote/picture.cc @@ -1,4 +1,4 @@ - /***** +/***** * picture.cc * Andy Hammerlindl 2002/06/06 * @@ -32,6 +32,7 @@ texstream::~texstream() { unlink((name+"aux").c_str()); unlink((name+"log").c_str()); unlink((name+"out").c_str()); + unlink((name+"m9").c_str()); if(settings::pdf(texengine)) unlink((name+"pdf").c_str()); if(context) { @@ -44,6 +45,276 @@ texstream::~texstream() { namespace camp { +bool isIdTransform3(const double* t) +{ + return (t == NULL || (t[0]==1 && t[4]==0 && t[ 8]==0 && t[12]==0 && + t[1]==0 && t[5]==1 && t[ 9]==0 && t[13]==0 && + t[2]==0 && t[6]==0 && t[10]==1 && t[14]==0 && + t[3]==0 && t[7]==0 && t[11]==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); + if(aisize == 4) { + for(size_t j=0; j < 4; j++) + tt[i+j*4]=vm::read<double>(ai,j); + } else reportError(fourbyfour); + } + + copyTransform3(dest,tt); +} + +void copyTransform3(double*& d, const double* s) +{ + if(isIdTransform3(s)) { + d=NULL; + } + else { + if (d == NULL) + d=new(UseGC) 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 { + double tt[16]; + for(size_t i=0; i < 4; i++) { + const double& s0=s[i+0]; + const double& s1=s[i+4]; + const double& s2=s[i+8]; + const double& s3=s[i+12]; + tt[i]=s0*r[0]+s1*r[1]+s2*r[2]+s3*r[3]; + tt[i+4]=s0*r[4]+s1*r[5]+s2*r[6]+s3*r[7]; + tt[i+8]=s0*r[8]+s1*r[9]+s2*r[10]+s3*r[11]; + tt[i+12]=s0*r[12]+s1*r[13]+s2*r[14]+s3*r[15]; + } + copyTransform3(t,tt); + } +} + +void transformTriples(const double* t, size_t n, Triple* d, const Triple* s) +{ + if(n == 0 || s == NULL || d == NULL) + return; + + if(isIdTransform3(t)) { + copyTriples(n, d, s); + return; + } + for(size_t i=0; i < n; i++) { + const double& x = s[i][0]; + const double& y = s[i][1]; + const double& z = s[i][2]; + double f=t[3]*x+t[7]*y+t[11]*z+t[15]; + if(f == 0.0) + reportError("division by 0 in transformTriples"); + f=1.0/f; + d[i][0]=(t[0]*x+t[4]*y+t[8]*z+t[12])*f; + d[i][1]=(t[1]*x+t[5]*y+t[9]*z+t[13])*f; + d[i][2]=(t[2]*x+t[6]*y+t[10]*z+t[14])*f; + } +} + +void transformshiftlessTriples(const double* t, size_t n, Triple* d, + const Triple* s) +{ + if(n == 0 || s == NULL || d == NULL) + return; + + if(isIdTransform3(t)) { + copyTriples(n, d, s); + return; + } + for(size_t i=0; i < n; i++) { + const double& x=s[i][0]; + const double& y=s[i][1]; + const double& z=s[i][2]; + double f=t[3]*x+t[7]*y+t[11]*z+t[15]; + if(f == 0.0) + reportError("division by 0 in transformshiftlessTriples"); + f=1.0/f; + d[i][0]=(t[0]*x+t[4]*y+t[8]*z)*f; + d[i][1]=(t[1]*x+t[5]*y+t[9]*z)*f; + d[i][2]=(t[2]*x+t[6]*y+t[10]*z)*f; + } +} + +void transformNormalsTriples(const double* t, size_t n, Triple* d, + const Triple* s) +{ + if(n==0 || s==NULL || d==NULL) + return; + + if(isIdTransform3(t)) { + copyTriples(n, d, s); + return; + } + for(size_t i=0; i < n; i++) { + const double& x = s[i][0]; + const double& y = s[i][1]; + const double& z = s[i][2]; + double& X = d[i][0]; + double& Y = d[i][1]; + double& Z = d[i][2]; + double f=t[3]*x+t[7]*y+t[11]*z+t[15]; + if(f == 0.0) + reportError("division by 0 in transformNormalsTriples"); + f=1.0/f; + X=(t[0]*x+t[4]*y+t[8]*z)*f; + Y=(t[1]*x+t[5]*y+t[9]*z)*f; + Z=(t[2]*x+t[6]*y+t[10]*z)*f; + const double scale=sqrt(X*X+Y*Y+Z*Z); + if(scale != 0.0) { + X /= scale; + Y /= scale; + Z /= scale; + } + } +} + +void unitTriples(size_t n, Triple* d) +{ + for (size_t i=0; i < n; i++) { + double& x = d[i][0]; + double& y = d[i][1]; + double& z = d[i][2]; + const double scale=sqrt(x*x+y*y+z*z); + if(scale != 0.0) { + x /= scale; + y /= scale; + z /= scale; + } + } +} + +void copyTriples(size_t n, Triple* d, const Triple* s) +{ + if(n == 0 || s == NULL || d == NULL) + return; + + memcpy(d, s, sizeof(double)*3*n); +} + +void boundsTriples(double& x, double& y, double& z, double& X, double& Y, + double& Z, size_t n, const Triple* v) +{ + if(n == 0 || v == NULL) + return; + + X=x=v[0][0]; + Y=y=v[0][1]; + Z=z=v[0][2]; + + for(size_t i=1; i < n; ++i) { + const double* const vi=v[i]; + const double vx=vi[0]; + x=min(x,vx); + X=max(X,vx); + const double vy=vi[1]; + y=min(y,vy); + Y=max(Y,vy); + const double vz=vi[2]; + z=min(z,vz); + Z=max(Z,vz); + } + +} + +inline double xratioTriple(const Triple v) +{ + return v[0]/v[2]; +} + +inline double yratioTriple(const Triple v) +{ + return v[1]/v[2]; +} + +void ratioTriples(pair &b, double (*m)(double, double), bool &first, size_t n, + const Triple* v) +{ + if(n == 0 || v == NULL) + return; + + if(first) { + first=false; + const double* const v0=v[0]; + b=pair(xratioTriple(v0),yratioTriple(v0)); + } + + double x=b.getx(); + double y=b.gety(); + for(size_t i=0; i < n; ++i) { + const double* const vi=v[i]; + x=m(x,xratioTriple(vi)); + y=m(y,yratioTriple(vi)); + } + b=pair(x,y); +} + +void normalizeTriple(Triple v) +{ + const double length = sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]); + if(length > 0) { + v[0] /= length; + v[1] /= length; + v[2] /= length; + } +} + +void crossTriple(Triple n, const Triple u, const Triple v) +{ + n[0]=u[1]*v[2]-u[2]*v[1]; + n[1]=u[2]*v[0]-u[0]*v[2]; + n[2]=u[0]*v[1]-u[1]*v[0]; +} + +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") @@ -180,11 +451,17 @@ bbox3 picture::bounds3() if(lastnumber3 == 0) b3=bbox3(); - nodelist::iterator p=nodes.begin(); - for(size_t i=0; i < lastnumber3; ++i) ++p; - for(; p != nodes.end(); ++p) { + matrixstack ms; + size_t i=0; + for(nodelist::const_iterator p=nodes.begin(); p != nodes.end(); ++p) { assert(*p); - (*p)->bounds(b3); + if((*p)->begingroup3()) + ms.push((*p)->transf3()); + else if((*p)->endgroup3()) + ms.pop(); + else + (*p)->bounds(ms.T(),b3); + i++; } lastnumber3=n; @@ -197,9 +474,15 @@ pair picture::ratio(double (*m)(double, double)) pair b; bounds3(); double fuzz=sqrtFuzz*(b3.Max()-b3.Min()).length(); + matrixstack ms; for(nodelist::const_iterator p=nodes.begin(); p != nodes.end(); ++p) { assert(*p); - (*p)->ratio(b,m,fuzz,first); + if((*p)->begingroup3()) + ms.push((*p)->transf3()); + else if((*p)->endgroup3()) + ms.pop(); + else + (*p)->ratio(ms.T(),b,m,fuzz,first); } return b; } @@ -241,7 +524,7 @@ void texinit() } else { if(!dir.empty()) cmd.push_back("-output-directory="+dir.substr(0,dir.length()-1)); - if(getSetting<bool>("inlinetex")) { + if(getSetting<bool>("inlineimage") || getSetting<bool>("inlinetex")) { string name=stripDir(stripExt((outname()))); size_t pos=name.rfind("-"); if(pos < string::npos) { @@ -456,6 +739,9 @@ int picture::epstopdf(const string& epsname, const string& pdfname) 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("-sDEVICE=pdfwrite"); cmd.push_back("-dEPSCrop"); cmd.push_back("-dSubsetFonts=true"); @@ -463,9 +749,6 @@ int picture::epstopdf(const string& epsname, const string& pdfname) cmd.push_back("-dMaxSubsetPct=100"); cmd.push_back("-dPDFSETTINGS=/prepress"); cmd.push_back("-dCompatibilityLevel=1.4"); - cmd.push_back("-P"); - if(safe) - cmd.push_back("-dSAFER"); if(!getSetting<bool>("autorotate")) cmd.push_back("-dAutoRotatePages=/None"); cmd.push_back("-g"+String(max(ceil(getSetting<double>("paperwidth")),1.0)) @@ -527,7 +810,7 @@ bool picture::postprocess(const string& prename, const string& outname, int status=0; bool epsformat=outputformat == "eps"; bool pdfformat=(settings::pdf(getSetting<string>("tex")) - && outputformat == "") || outputformat == "pdf"; + && outputformat == "") || outputformat == "pdf"; if(pdftex || !epsformat) { if(pdfformat) { @@ -573,7 +856,8 @@ bool picture::postprocess(const string& prename, const string& outname, status=System(cmd,0,true,"convert"); } } - if(!getSetting<bool>("keep")) unlink(prename.c_str()); + if(!getSetting<bool>("keep")) + unlink(prename.c_str()); } if(status != 0) return false; @@ -918,6 +1202,8 @@ bool picture::shipout(picture *preamble, const string& Prefix, if(context) prename=stripDir(prename); status=postprocess(prename,outname,outputformat,magnification,wait, view,pdf && Labels,svgformat); + if(pdfformat && !getSetting<bool>("keep")) + unlink(auxname(prefix,"m9").c_str()); } } } @@ -931,11 +1217,11 @@ bool picture::shipout(picture *preamble, const string& Prefix, // render viewport with width x height pixels. void picture::render(GLUnurbs *nurb, double size2, const triple& Min, const triple& Max, - double perspective, bool transparent) const + double perspective, bool lighton, bool transparent) const { for(nodelist::const_iterator p=nodes.begin(); p != nodes.end(); ++p) { assert(*p); - (*p)->render(nurb,size2,Min,Max,perspective,transparent); + (*p)->render(nurb,size2,Min,Max,perspective,lighton,transparent); } } @@ -987,22 +1273,38 @@ bool picture::shipout3(const string& prefix, const string& format, if(getSetting<bool>("interrupt")) return true; - bool offscreen=getSetting<bool>("offscreen"); - #ifndef HAVE_LIBGLUT - if(!offscreen) + if(!getSetting<bool>("offscreen")) camp::reportError("to support onscreen rendering, please install glut library, run ./configure, and recompile"); #endif #ifndef HAVE_LIBOSMESA - if(offscreen) + if(getSetting<bool>("offscreen")) camp::reportError("to support offscreen rendering; please install OSMesa library, run ./configure --enable-offscreen, and recompile"); #endif - bounds3(); + 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(); } @@ -1012,6 +1314,7 @@ bool picture::shipout3(const string& prefix, const string& format, #ifdef HAVE_GL bool View=settings::view() && view; static int oldpid=0; + bool offscreen=getSetting<bool>("offscreen"); #ifdef HAVE_PTHREAD bool animating=getSetting<bool>("animating"); bool Wait=!interact::interactive || !View || animating; @@ -1024,7 +1327,7 @@ bool picture::shipout3(const string& prefix, const string& format, if(gl::initialize) { gl::initialize=false; com.prefix=prefix; - com.pic=this; + com.pic=pic; com.format=outputformat; com.width=width; com.height=height; @@ -1073,7 +1376,7 @@ bool picture::shipout3(const string& prefix, const string& format, } #endif #ifdef HAVE_GL - glrender(prefix,this,outputformat,width,height,angle,zoom,m,M,shift,t, + glrender(prefix,pic,outputformat,width,height,angle,zoom,m,M,shift,t, background,nlights,lights,diffuse,ambient,specular,viewportlighting, View,oldpid); #ifdef HAVE_PTHREAD @@ -1088,7 +1391,7 @@ bool picture::shipout3(const string& prefix, const string& format, return false; } -bool picture::shipout3(const string& prefix, array *index, array *center) +bool picture::shipout3(const string& prefix) { bounds3(); bool status = true; @@ -1102,7 +1405,7 @@ bool picture::shipout3(const string& prefix, array *index, array *center) groups.push_back(groupmap()); for(nodelist::iterator p=nodes.begin(); p != nodes.end(); ++p) { assert(*p); - (*p)->write(&prc,&billboard,index,center,compressionlimit,groups); + (*p)->write(&prc,&billboard,compressionlimit,groups); } groups.pop_back(); if(status) @@ -1132,11 +1435,23 @@ picture *picture::transformed(const transform& t) picture *picture::transformed(const array& t) { picture *pic = new picture; - - nodelist::iterator p; - for (p = nodes.begin(); p != nodes.end(); ++p) { + double* T=NULL; + copyArray4x4C(T, &t); + size_t level = 0; + for (nodelist::iterator p = nodes.begin(); p != nodes.end(); ++p) { assert(*p); - pic->append((*p)->transformed(t)); + 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; |