diff options
author | Karl Berry <karl@freefriends.org> | 2010-04-19 23:59:33 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2010-04-19 23:59:33 +0000 |
commit | dddce3148a2bc785603576b18ffcf72d39adbe47 (patch) | |
tree | 14f4c79ef11bcf0820a8d4ff2ab0c5ac009c365c /Build/source/utils/asymptote/picture.cc | |
parent | a01e51b01f5819b6091af48cdca581e9f2a9282e (diff) |
asy 1.93
git-svn-id: svn://tug.org/texlive/trunk@17934 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/utils/asymptote/picture.cc')
-rw-r--r-- | Build/source/utils/asymptote/picture.cc | 416 |
1 files changed, 262 insertions, 154 deletions
diff --git a/Build/source/utils/asymptote/picture.cc b/Build/source/utils/asymptote/picture.cc index b8bbbfb34f6..536a91ef3f6 100644 --- a/Build/source/utils/asymptote/picture.cc +++ b/Build/source/utils/asymptote/picture.cc @@ -12,6 +12,8 @@ #include "settings.h" #include "interact.h" #include "drawverbatim.h" +#include "drawlabel.h" +#include "drawlayer.h" using std::ifstream; using std::ofstream; @@ -53,11 +55,6 @@ picture::~picture() { } -bool picture::epsformat,picture::pdfformat, picture::svgformat; -bool picture::xobject, picture::pdf; -bool picture::Labels; -double picture::paperWidth,picture::paperHeight; - void picture::enclose(drawElement *begin, drawElement *end) { assert(begin); @@ -65,6 +62,7 @@ void picture::enclose(drawElement *begin, drawElement *end) nodes.push_front(begin); lastnumber=0; lastnumber3=0; + for(nodelist::iterator p=nodes.begin(); p != nodes.end(); ++p) { assert(*p); if((*p)->islayer()) { @@ -197,9 +195,11 @@ pair picture::ratio(double (*m)(double, double)) { bool first=true; pair b; + bbox3 B=bounds3(); + double fuzz=sqrtFuzz*(B.Max()-B.Min()).length(); for(nodelist::const_iterator p=nodes.begin(); p != nodes.end(); ++p) { assert(*p); - (*p)->ratio(b,m,first); + (*p)->ratio(b,m,fuzz,first); } return b; } @@ -240,7 +240,7 @@ void texinit() cmd.push_back(texput); } else { if(!dir.empty()) - cmd.push_back("-output-directory="+dir); + cmd.push_back("-output-directory="+dir.substr(0,dir.length()-1)); cmd.push_back("\\scrollmode"); } @@ -266,7 +266,7 @@ int opentex(const string& texname, const string& prefix) } else { string dir=stripFile(texname); if(!dir.empty()) - cmd.push_back("-output-directory="+dir); + cmd.push_back("-output-directory="+dir.substr(0,dir.length()-1)); cmd.push_back("\\nonstopmode\\input"); cmd.push_back(stripDir(texname)); } @@ -286,9 +286,10 @@ int opentex(const string& texname, const string& prefix) bool picture::texprocess(const string& texname, const string& outname, - const string& prefix, const pair& bboxshift) + const string& prefix, const pair& bboxshift, + bool svgformat) { - int status=0; + int status=1; ifstream outfile; outfile.open(texname.c_str()); @@ -297,89 +298,101 @@ bool picture::texprocess(const string& texname, const string& outname, if(outfile) { outfile.close(); - if(opentex(texname,prefix)) return false; - + status=opentex(texname,prefix); string texengine=getSetting<string>("tex"); - string dviname=auxname(prefix,"dvi"); - mem::vector<string> cmd; - - if(svgformat) { - cmd.push_back(getSetting<string>("dvisvgm")); - cmd.push_back("-n"); - cmd.push_back("--verbosity=3"); - push_split(cmd,getSetting<string>("dvisvgmOptions")); - cmd.push_back("-o"+outname); - cmd.push_back(dviname); - status=System(cmd,0,true,"dvisvgm"); - if(status != 0) return false; - if(!keep) - unlink(dviname.c_str()); - } else { - if(!pdf) { - 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; - - hoffset += b.left+bboxshift.getx(); - voffset += paperHeight-height-b.bottom-bboxshift.gety(); + if(status == 0) { + string dviname=auxname(prefix,"dvi"); + mem::vector<string> cmd; - 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"); - cmd.push_back("-T"+String(paperWidth)+"bp,"+String(paperHeight)+"bp"); - push_split(cmd,getSetting<string>("dvipsOptions")); - cmd.push_back("-t"+papertype); - if(verbose <= 1) cmd.push_back("-q"); - cmd.push_back("-o"+psname); + if(svgformat) { + cmd.push_back(getSetting<string>("dvisvgm")); + cmd.push_back("-n"); + cmd.push_back("--verbosity=3"); + push_split(cmd,getSetting<string>("dvisvgmOptions")); + cmd.push_back("-o"+outname); + ostringstream buf; + bbox B=b; + B.shift(bboxshift+pair(1.99*cm,1.9*cm)); + buf << "--bbox=" + << B.left << "bp " + << B.bottom << "bp " + << B.right << "bp " + << B.top << "bp"; + cmd.push_back(buf.str()); cmd.push_back(dviname); - status=System(cmd,0,true,"dvips"); - if(status != 0) return false; + status=System(cmd,0,true,"dvisvgm"); + if(!keep) + unlink(dviname.c_str()); + } else { + if(!settings::pdf(texengine)) { + string psname=auxname(prefix,"ps"); + double height=b.top-b.bottom+1.0; - ifstream fin(psname.c_str()); - psfile fout(outname,false); + // 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 s; - bool first=true; - transform t=shift(bboxshift)*T; - bool shift=!t.isIdentity(); - string beginspecial="TeXDict begin @defspecial"; - string endspecial="@fedspecial end"; - while(getline(fin,s)) { - if(s.find("%%DocumentPaperSizes:") == 0) continue; - if(s.find("%!PS-Adobe-") == 0) { - fout.header(); - } else if(first && s.find("%%BoundingBox:") == 0) { - bbox box=b; - box.shift(bboxshift); - if(verbose > 2) BoundingBox(cout,box); - fout.BoundingBox(box); - first=false; - } else if(shift && s.find(beginspecial) == 0) { - fout.verbatimline(s); - fout.gsave(); - fout.concat(t); - } else if(shift && s.find(endspecial) == 0) { - fout.grestore(); - fout.verbatimline(s); - } else - fout.verbatimline(s); - } - if(!keep) { - unlink(dviname.c_str()); - unlink(psname.c_str()); + 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"); + cmd.push_back("-T"+String(getSetting<double>("paperwidth"))+"bp,"+ + String(paperHeight)+"bp"); + push_split(cmd,getSetting<string>("dvipsOptions")); + 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(); + string beginspecial="TeXDict begin @defspecial"; + string endspecial="@fedspecial end"; + while(getline(fin,s)) { + if(s.find("%%DocumentPaperSizes:") == 0) continue; + if(s.find("%!PS-Adobe-") == 0) { + fout.header(); + } else if(first && s.find("%%BoundingBox:") == 0) { + bbox box=b; + box.shift(bboxshift); + if(verbose > 2) BoundingBox(cout,box); + fout.BoundingBox(box); + first=false; + } else if(shift && s.find(beginspecial) == 0) { + fout.verbatimline(s); + fout.gsave(); + fout.concat(t); + } else if(shift && s.find(endspecial) == 0) { + fout.grestore(); + fout.verbatimline(s); + } else + fout.verbatimline(s); + } + } + if(!keep) { + unlink(dviname.c_str()); + unlink(psname.c_str()); + } } } } @@ -421,8 +434,8 @@ int picture::epstopdf(const string& epsname, const string& pdfname) cmd.push_back("-dSAFER"); if(!getSetting<bool>("autorotate")) cmd.push_back("-dAutoRotatePages=/None"); - cmd.push_back("-g"+String(max(ceil(paperWidth),1.0))+"x"+ - String(max(ceil(paperHeight),1.0))); + 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")); @@ -474,38 +487,57 @@ bool picture::reloadPDF(const string& Viewer, const string& outname) const bool picture::postprocess(const string& prename, const string& outname, const string& outputformat, double magnification, - bool wait, bool view) + bool wait, bool view, bool pdftex, bool svgformat) { static mem::map<CONST string,int> pids; int status=0; + bool epsformat=outputformat == "eps"; + bool pdfformat=(settings::pdf(getSetting<string>("tex")) + && outputformat == "") || outputformat == "pdf"; - if((pdf && Labels) || !epsformat) { + if(pdftex || !epsformat) { if(pdfformat) { - if(pdf && Labels) { + 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(!svgformat) { + } else { mem::vector<string> cmd; double render=fabs(getSetting<double>("render")); if(render == 0) render=1.0; - double expand=getSetting<Int>("antialias"); - if(expand < 2.0) expand=1.0; - double res=expand*render*72.0; - cmd.push_back(getSetting<string>("convert")); - cmd.push_back("-alpha"); - cmd.push_back("Off"); - cmd.push_back("-density"); - cmd.push_back(String(res)+"x"+String(res)); - if(expand == 1.0) - cmd.push_back("+antialias"); - cmd.push_back("-geometry"); - cmd.push_back(String(100.0/expand)+"%x"); - push_split(cmd,getSetting<string>("convertOptions")); - cmd.push_back(nativeformat()+":"+prename); - cmd.push_back(outputformat+":"+outname); - status=System(cmd,0,true,"convert"); + 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("-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(!svgformat) { + 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("-geometry"); + cmd.push_back(String(100.0/expand)+"%x"); + cmd.push_back(nativeformat()+":"+prename); + cmd.push_back(outputformat+":"+outname); + status=System(cmd,0,true,"convert"); + } } if(!getSetting<bool>("keep")) unlink(prename.c_str()); } @@ -583,34 +615,28 @@ bool picture::shipout(picture *preamble, const string& Prefix, { b=bounds(); - bool TeXmode=getSetting<bool>("inlinetex") && - getSetting<string>("tex") != "none"; - string texengine=getSetting<string>("tex"); - pdf=settings::pdf(texengine); + bool usetex=texengine != "none"; + bool TeXmode=getSetting<bool>("inlinetex") && usetex; + bool pdf=settings::pdf(texengine); bool standardout=Prefix == "-"; - string prefix=standardout ? "out" : Prefix; + string prefix=standardout ? standardprefix : Prefix; string preformat=nativeformat(); string outputformat=format.empty() ? defaultformat() : format; - epsformat=outputformat == "eps"; - pdfformat=outputformat == "pdf"; - svgformat=outputformat == "svg" && !pdf && + bool epsformat=outputformat == "eps"; + bool pdfformat=pdf || outputformat == "pdf"; + bool svgformat=outputformat == "svg" && !pdf && usetex && (!have3D() || getSetting<double>("render") == 0.0); - xobject=magnification > 0; + bool xobject=magnification > 0; string outname=Outname(prefix,outputformat,standardout); string epsname=epsformat ? (standardout ? "" : outname) : auxname(prefix,"eps"); - Labels=labels || TeXmode || svgformat; + bool Labels=labels || TeXmode; - if(Labels) - spaceToUnderscore(prefix); - string prename=((epsformat && !pdf) || !Labels) ? epsname : - auxname(prefix,preformat); - - if((b.empty && !Labels)) { // Output a null file + if(b.empty && !Labels) { // Output a null file bbox b; b.left=b.bottom=0; b.right=b.top=xobject ? 18 : 1; @@ -618,11 +644,18 @@ bool picture::shipout(picture *preamble, const string& Prefix, out.prologue(b); out.epilogue(); out.close(); - return postprocess(epsname,outname,outputformat,1.0,wait,view); + return postprocess(epsname,outname,outputformat,1.0,wait,view,false,false); } + Labels |= svgformat; + + if(Labels) + prefix=cleanpath(prefix); + + string prename=((epsformat && !pdf) || !Labels) ? epsname : + auxname(prefix,preformat); + if(xobject) { - // Work around half-pixel bounding box bug in Ghostscript pngalpha driver double fuzz=0.5/magnification; b.top += fuzz; b.right += fuzz; @@ -631,19 +664,19 @@ bool picture::shipout(picture *preamble, const string& Prefix, SetPageDimensions(); - paperWidth=getSetting<double>("paperwidth"); - paperHeight=getSetting<double>("paperheight"); string origin=getSetting<string>("align"); - - pair bboxshift=(origin == "Z" && !pdfformat) ? + + pair bboxshift=(origin == "Z" && epsformat) ? pair(0.0,0.0) : pair(-b.left,-b.bottom); - if(!pdfformat) { + if(epsformat) { bboxshift += getSetting<pair>("offset"); if(origin != "Z" && origin != "B") { - double yexcess=max(paperHeight-(b.top-b.bottom+1.0),0.0); + double yexcess=max(getSetting<double>("paperheight")- + (b.top-b.bottom+1.0),0.0); if(origin == "T") bboxshift += pair(0.0,yexcess); else { - double xexcess=max(paperWidth-(b.right-b.left+1.0),0.0); + double xexcess=max(getSetting<double>("paperwidth")- + (b.right-b.left+1.0),0.0); bboxshift += pair(0.5*xexcess,0.5*yexcess); } } @@ -656,18 +689,22 @@ bool picture::shipout(picture *preamble, const string& Prefix, if(Labels) { texname=auxname(prefix,"tex"); - tex=new texfile(texname,b); + tex=svgformat ? 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> psnameStack; + mem::list<string> files; bbox bshift=b; transparency=false; + int svgcount=0; + + typedef mem::list<drawElement *> clipstack; + clipstack begin; while(p != nodes.end()) { string psname,pdfname; @@ -680,8 +717,8 @@ bool picture::shipout(picture *preamble, const string& Prefix, psname=epsname; bshift.shift(bboxshift); } - psnameStack.push_back(psname); - if(pdf) psnameStack.push_back(pdfname); + files.push_back(psname); + if(pdf) files.push_back(pdfname); psfile out(psname,pdfformat); out.prologue(bshift); @@ -705,10 +742,80 @@ bool picture::shipout(picture *preamble, const string& Prefix, out.resetpen(); bool postscript=false; + drawLabel *L=NULL; + + if(svgformat) + for(nodelist::const_iterator r=begin.begin(); r != begin.end(); ++r) + (*r)->draw(&out); + for(; p != nodes.end(); ++p) { assert(*p); if(Labels && (*p)->islayer()) break; - postscript |= (*p)->draw(&out); + + if(svgformat && (*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",0.0,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,processData().tex,labelbounds,bboxstack); + postscript=true; + } + break; + } else postscript |= (*p)->draw(&out); } if(Labels) { @@ -731,8 +838,16 @@ bool picture::shipout(picture *preamble, const string& Prefix, if(status) { for (p=layerp; p != nodes.end(); ++p) { assert(*p); - (*p)->write(tex,b); - if((*p)->islayer()) { + bool islayer=(*p)->islayer(); + if(svgformat && (*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++; @@ -753,11 +868,11 @@ bool picture::shipout(picture *preamble, const string& Prefix, tex->epilogue(); if(context) prefix=stripDir(prefix); status=texprocess(texname,svgformat ? outname : prename,prefix, - bboxshift); + bboxshift,svgformat); delete tex; if(!getSetting<bool>("keep")) { - for(mem::list<string>::iterator p=psnameStack.begin(); - p != psnameStack.end(); ++p) + for(mem::list<string>::iterator p=files.begin(); p != files.end(); + ++p) unlink(p->c_str()); } } @@ -768,7 +883,7 @@ bool picture::shipout(picture *preamble, const string& Prefix, } else { if(context) prename=stripDir(prename); status=postprocess(prename,outname,outputformat,magnification,wait, - view); + view,pdf && Labels,svgformat); } } } @@ -816,7 +931,7 @@ Communicate com; void glrenderWrapper() { -#ifdef HAVE_LIBGL +#ifdef HAVE_GL #ifdef HAVE_LIBPTHREAD wait(initSignal,initLock); endwait(initSignal,initLock); @@ -837,7 +952,7 @@ bool picture::shipout3(const string& prefix, const string& format, { if(getSetting<bool>("interrupt")) return true; -#ifdef HAVE_LIBGL +#ifdef HAVE_GL bounds3(); for(nodelist::const_iterator p=nodes.begin(); p != nodes.end(); ++p) { @@ -917,13 +1032,6 @@ bool picture::shipout3(const string& prefix, const string& format, pthread_cond_wait(&readySignal,&readyLock); pthread_mutex_unlock(&readyLock); } - if(!glthread || (Wait && !animating)) { - delete[] specular; - delete[] ambient; - delete[] diffuse; - delete[] lights; - } - return true; #endif #else |