From dddce3148a2bc785603576b18ffcf72d39adbe47 Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Mon, 19 Apr 2010 23:59:33 +0000 Subject: asy 1.93 git-svn-id: svn://tug.org/texlive/trunk@17934 c570f23f-e606-0410-a88d-b1316a301751 --- Build/source/utils/asymptote/texfile.cc | 447 +++++++++++++++++++++++++++++++- 1 file changed, 437 insertions(+), 10 deletions(-) (limited to 'Build/source/utils/asymptote/texfile.cc') diff --git a/Build/source/utils/asymptote/texfile.cc b/Build/source/utils/asymptote/texfile.cc index 075826d5ca8..15410d569cd 100644 --- a/Build/source/utils/asymptote/texfile.cc +++ b/Build/source/utils/asymptote/texfile.cc @@ -13,6 +13,8 @@ using std::ofstream; using settings::getSetting; +using vm::array; +using vm::read; namespace camp { @@ -48,12 +50,12 @@ void texfile::miniprologue() << "\\textheight=2048pt" << newl << "\\textwidth=2048pt" << newl << "\\begin{document}" << newl; + latexfontencoding(*out); } else if(settings::context(texengine)) { *out << "\\setuppagenumbering[location=]" << newl << "\\usetypescript[modern]" << newl << "\\starttext\\hbox{%" << newl; } - texfontencoding(*out); } void texfile::prologue() @@ -82,16 +84,13 @@ void texfile::prologue() if(height < 12.0) voffset=height-12.0; } else if(height < 10.0) voffset=height-10.0; - // Work around an apparent xelatex dimension bug - double xelatexBug=ps2tex; - if(width > 0) *out << "\\pdfpagewidth=" << width << "bp" << newl; *out << "\\ifx\\pdfhorigin\\undefined" << newl << "\\hoffset=-1in" << newl - << "\\voffset=" << voffset-72.0*xelatexBug << "bp" << newl; + << "\\voffset=" << voffset-72.0 << "bp" << newl; if(height > 0) - *out << "\\pdfpageheight=" << height*0.5*(1.0+xelatexBug) << "bp" + *out << "\\pdfpageheight=" << height << "bp" << newl; *out << "\\else" << newl << "\\pdfhorigin=0bp" << newl @@ -114,6 +113,7 @@ void texfile::prologue() << "\\topmargin=-37.01pt" << newl; *out << "\\begin{document}" << newl; } + latexfontencoding(*out); } else { if(!inlinetex) { if(settings::context(texengine)) { @@ -135,6 +135,7 @@ void texfile::prologue() } } } + beginpage(); } void texfile::beginlayer(const string& psname, bool postscript) @@ -144,11 +145,15 @@ void texfile::beginlayer(const string& psname, bool postscript) if(settings::context(texengine)) *out << "\\externalfigure[" << psname << "]%" << newl; else { - *out << "\\includegraphics"; - if(!settings::pdf(texengine)) + *out << "{\\catcode`\"=12%" << newl + << "\\includegraphics"; + bool pdf=settings::pdf(texengine); + if(!pdf) *out << "[bb=" << box.left << " " << box.bottom << " " << box.right << " " << box.top << "]"; - *out << "{" << psname << "}%" << newl; + if(pdf) *out << "{\"" << stripExt(psname) << "\".pdf}%" << newl; + else *out << "{\"" << psname << "\"}%" << newl; + *out << "}%" << newl; } if(!inlinetex) *out << "\\kern " << (box.left-box.right)*ps2tex << "pt%" << newl; @@ -204,7 +209,7 @@ void texfile::setfont(pen p) if(latex) setlatexfont(*out,p,lastpen); settexfont(*out,p,lastpen,latex); - lastpen=p; + lastpen.setfont(p); } void texfile::setpen(pen p) @@ -220,6 +225,30 @@ void texfile::setpen(pen p) setfont(p); } +void texfile::beginpicture(const bbox& b) +{ + verbatim(settings::beginpicture(texengine)); + if(!settings::context(texengine)) { + verbatim("("); + double width=b.right-b.left; + double height=b.top-b.bottom; + write(width*ps2tex); + verbatim(","); + write(height*ps2tex); + verbatim(")"); + } + verbatimline("%"); +} + +void texfile::endpicture(const bbox& b) +{ + verbatimline(settings::endpicture(texengine)); + verbatim("\\kern"); + double width=b.right-b.left; + write(-width*ps2tex); + verbatimline("pt%"); +} + void texfile::gsave() { *out << settings::beginspecial(texengine); @@ -278,6 +307,7 @@ void texfile::put(const string& label, const transform& T, const pair& z, void texfile::epilogue(bool pipe) { + endpage(); if(settings::latex(texengine)) *out << "\\end{document}" << newl; else if(settings::context(texengine)) @@ -287,4 +317,401 @@ void texfile::epilogue(bool pipe) out->flush(); } +string svgtexfile::nl="{?nl}%\n"; + +void svgtexfile::beginspecial() +{ + inspecial=true; + out->unsetf(std::ios::fixed); + *out << "\\catcode`\\#=11%" << newl + << "\\special{dvisvgm:raw" << nl; +} + +void svgtexfile::endspecial() +{ + inspecial=false; + *out << "}\\catcode`\\#=6%" << newl; + out->setf(std::ios::fixed); +} + +void svgtexfile::begintransform() +{ + *out << "" << nl; +} + +void svgtexfile::endtransform() +{ + *out << ""; +} + +void svgtexfile::gsave(bool tex) +{ + if(clipstack.size() < 1) + clipstack.push(0); + else + clipstack.push(clipcount); + *out << "\\special{dvisvgm:raw }%" << newl; + pens.push(lastpen); +} + +void svgtexfile::grestore(bool tex) +{ + if(pens.size() < 1 || clipstack.size() < 1) + reportError("grestore without matching gsave"); + lastpen=pens.top(); + pens.pop(); + clipstack.pop(); + *out << "\\special{dvisvgm:raw }%" << newl; +} + +void svgtexfile::clippath() +{ + if(clipstack.size() > 0) { + size_t count=clipstack.top(); + if(count > 0) + *out << "clip-path='url(#clip" << count << ")' "; + } +} + +void svgtexfile::beginpath() +{ + *out << "" << nl; + beginpath(); + if(clipstack.size() >= 0) + clipstack.pop(); + clipstack.push(clipcount); +} + +void svgtexfile::endclip0(const pen &p) +{ + *out << "'"; + fillrule(p,"clip"); + endpath(); + *out << "" << nl; +} + +void svgtexfile::endclip(const pen &p) +{ + endclip0(p); + endtransform(); + endspecial(); +} + +void svgtexfile::fillrule(const pen& p, const string& type) +{ + if(p.Fillrule() != lastpen.Fillrule()) + *out << " " << type << "-rule='" << + (p.evenodd() ? "evenodd" : "nonzero") << "'"; + lastpen.setfillrule(p); +} + +void svgtexfile::color(const pen &p, const string& type) +{ + *out << "' " << type << "='#" << rgbhex(p) << "'"; + double opacity=p.opacity(); + if(opacity != 1.0) + *out << " opacity='" << opacity << "'"; +} + +void svgtexfile::fill(const pen &p) +{ + color(p,"fill"); + fillrule(p); + endpath(); + endtransform(); + endspecial(); +} + +void svgtexfile::properties(const pen& p) +{ + if(p.cap() != lastpen.cap()) + *out << " stroke-linecap='" << PSCap[p.cap()] << "'"; + + if(p.join() != lastpen.join()) + *out << " stroke-linejoin='" << Join[p.join()] << "'"; + + if(p.miter() != lastpen.miter()) + *out << " stroke-miterlimit='" << p.miter()*ps2tex << "'"; + + if(p.width() != lastpen.width()) + *out << " stroke-width='" << p.width()*ps2tex << "'"; + + const LineType *linetype=p.linetype(); + const LineType *lastlinetype=lastpen.linetype(); + + if(!(linetype->pattern == lastlinetype->pattern)) { + size_t n=linetype->pattern.size(); + if(n > 0) { + *out << " stroke-dasharray='"; + *out << vm::read(linetype->pattern,0)*ps2tex; + for(size_t i=1; i < n; ++i) + *out << "," << vm::read(linetype->pattern,i)*ps2tex; + *out << "'"; + } + } + + if(linetype->offset != lastlinetype->offset) + *out << " stroke-dashoffset='" << linetype->offset*ps2tex << "'"; + + lastpen=p; +} + +void svgtexfile::stroke(const pen &p, bool dot) +{ + if(dot) + color(p,"fill"); + else { + color(p,"fill='none' stroke"); + properties(p); + } + endpath(); + endtransform(); + endspecial(); +} + +void svgtexfile::strokepath() +{ + reportWarning("SVG does not support strokepath"); +} + +void svgtexfile::begingradientshade(bool axial, ColorSpace colorspace, + const pen& pena, const pair& a, double ra, + const pen& penb, const pair& b, double rb) +{ + string type=axial ? "linear" : "radial"; + beginspecial(); + *out << "<" << type << "Gradient id='grad" << gradientcount; + if(axial) { + *out << "' x1='" << a.getx()*ps2tex << "' y1='" << -a.gety()*ps2tex + << "' x2='" << b.getx()*ps2tex << "' y2='" << -b.gety()*ps2tex; + } else { + *out << "' cx='" << b.getx()*ps2tex << "' cy='" << -b.gety()*ps2tex + << "' r='" << rb*ps2tex; + } + *out <<"' gradientUnits='userSpaceOnUse'>" << nl + << "" << nl + << "" << nl + << "" << nl; + begintransform(); + beginpath(); +} + +void svgtexfile::gradientshade(bool axial, ColorSpace colorspace, + const pen& pena, const pair& a, double ra, + const pen& penb, const pair& b, double rb) +{ + *out << "' fill='url(#grad" << gradientcount << ")'"; + fillrule(pena); + endpath(); + ++gradientcount; + endtransform(); + endspecial(); +} + +// Return the point on the line through p and q that is closest to z. +pair closest(pair p, pair q, pair z) +{ + pair u=q-p; + double denom=dot(u,u); + return denom == 0.0 ? p : p+dot(z-p,u)/denom*u; +} + +void svgtexfile::gouraudshade(const pen& p0, const pair& z0, + const pen& p1, const pair& z1, + const pen& p2, const pair& z2) +{ + string hex[]={rgbhex(p0),rgbhex(p1),rgbhex(p2)}; + pair Z[]={z0,z1,z2}; + + *out << "" << nl + << "" << nl + << "" << nl + << ""; + + for(size_t k=0; k < 3; ++k) { + pair z=Z[k]; + pair opp=closest(Z[(k+1) % 3],Z[(k+2) % 3],z); + *out << "" << nl + << "" << nl + << "" << nl + << "" << nl; + } + *out << "" << nl + << "" << nl; + *out << "" << nl + << "" << nl + << "" << nl; + ++gouraudcount; +} + +void svgtexfile::begingouraudshade(const vm::array& pens, + const vm::array& vertices, + const vm::array& edges) +{ + size_t size=pens.size(); + if(size == 0) return; + beginclip(); +} + +void svgtexfile::gouraudshade(const pen& pentype, + const array& pens, const array& vertices, + const array& edges) +{ + size_t size=pens.size(); + if(size == 0) return; + + endclip0(pentype); + + pen *p0=NULL,*p1=NULL,*p2=NULL; + pair z0,z1,z2; + + for(size_t i=0; i < size; i++) { + Int edge=read(edges,i); + + switch(edge) { + case 0: + p0=read(pens,i); + z0=read(vertices,i); + ++i; + if(i < size) { + p1=read(pens,i); + z1=read(vertices,i); + ++i; + if(i < size) { + p2=read(pens,i); + z2=read(vertices,i); + } + } + break; + case 1: + p0=read(pens,i); + z0=read(vertices,i); + break; + case 2: + p1=read(pens,i); + z1=read(vertices,i); + break; + default: + break; + } + if(p0 == NULL || p1 == NULL || p2 == NULL) + reportError("invalid edge flag"); + gouraudshade(*p0,z0,*p1,z1,*p2,z2); + } + endtransform(); + endspecial(); +} + +void svgtexfile::begintensorshade(const vm::array& pens, + const vm::array& boundaries, + const vm::array& z) +{ + beginspecial(); + *out << "" << nl; + + path g=read(boundaries,0); + pair Z[]={g.point((Int) 0),g.point((Int) 3),g.point((Int) 2), + g.point((Int) 1)}; + + array *pi=read(pens,0); + if(checkArray(pi) != 4) + reportError("specify 4 pens for each path"); + string hex[]={rgbhex(read(pi,0)),rgbhex(read(pi,3)), + rgbhex(read(pi,2)),rgbhex(read(pi,1))}; + + *out << "" << nl + << "" << nl + << ""; + + pair mean=0.25*(Z[0]+Z[1]+Z[2]+Z[3]); + for(size_t k=0; k < 4; ++k) { + pair opp=(k % 2 == 0) ? Z[(k+2) % 4] : mean; + *out << "" << nl + << "" << nl + << "" << nl + << "" << nl; + } + beginpath(); +} + +void svgtexfile::tensorshade(const pen& pentype, const vm::array& pens, + const vm::array& boundaries, const vm::array& z) +{ + *out << "' id='path" << tensorcount << "'"; + fillrule(pentype); + endpath(); + *out << "" << nl; + begintransform(); + *out << "" << nl + << "" << nl + << "" << nl + << "" << nl; + + ++tensorcount; + endspecial(); +} + } //namespace camp -- cgit v1.2.3