summaryrefslogtreecommitdiff
path: root/Build/source/utils/asymptote/drawpath.cc
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2009-05-16 00:19:13 +0000
committerKarl Berry <karl@freefriends.org>2009-05-16 00:19:13 +0000
commitbab45528d65eaafe68a705dbb2a57075c7b7cbd8 (patch)
tree10b4ae2b5195c8dede153ab89359ec00f55f325f /Build/source/utils/asymptote/drawpath.cc
parent8643d90372e9c31e0f461c15c596b60a545bd7d3 (diff)
asymptote 1.72 sources (not integrated into build yet)
git-svn-id: svn://tug.org/texlive/trunk@13110 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/utils/asymptote/drawpath.cc')
-rw-r--r--Build/source/utils/asymptote/drawpath.cc173
1 files changed, 173 insertions, 0 deletions
diff --git a/Build/source/utils/asymptote/drawpath.cc b/Build/source/utils/asymptote/drawpath.cc
new file mode 100644
index 00000000000..c1d2c85efc0
--- /dev/null
+++ b/Build/source/utils/asymptote/drawpath.cc
@@ -0,0 +1,173 @@
+/*****
+ * drawpath.cc
+ * Andy Hammerlindl 2002/06/06
+ *
+ * Stores a path that has been added to a picture.
+ *****/
+
+#include <sstream>
+#include <vector>
+#include <cfloat>
+
+#include "drawpath.h"
+#include "psfile.h"
+#include "util.h"
+
+namespace camp {
+
+
+double PatternLength(double arclength, const std::vector<double>& pat,
+ bool cyclic, double penwidth)
+{
+ double sum=0.0;
+
+ size_t n=pat.size();
+ for(unsigned i=0; i < n; i ++)
+ sum += pat[i]*penwidth;
+
+ if(sum == 0.0) return 0.0;
+
+ if(n % 2 == 1) sum *= 2.0; // On/off pattern repeats after 2 cycles.
+
+ // Fix bounding box resolution problem. Example:
+ // asy -f pdf testlinetype; gv -scale -2 testlinetype.pdf
+ if(!cyclic && pat[0] == 0) sum += 1.0e-3*penwidth;
+
+ double terminator=(cyclic && arclength >= 0.5*sum) ? 0.0 : pat[0]*penwidth;
+ int ncycle=(int)((arclength-terminator)/sum+0.5);
+
+ return (ncycle >= 1 || terminator >= 0.75*arclength) ?
+ ncycle*sum+terminator : 0.0;
+}
+
+pen adjustdash(pen& p, double arclength, bool cyclic)
+{
+ pen q=p;
+ // Adjust dash sizes to fit arclength; also compensate for linewidth.
+ string stroke=q.stroke();
+
+ if(!stroke.empty()) {
+ double penwidth=q.linetype().scale ? q.width() : 1.0;
+ double factor=penwidth;
+
+ std::vector<double> pat;
+
+ istringstream ibuf(stroke);
+ double l;
+ while(ibuf >> l) {
+ if(l < 0) l=0;
+ pat.push_back(l);
+ }
+
+ size_t n=pat.size();
+
+ if(q.linetype().adjust) {
+ if(arclength) {
+ if(n == 0) return q;
+
+ double denom=PatternLength(arclength,pat,cyclic,penwidth);
+ if(denom != 0.0) factor *= arclength/denom;
+ }
+ }
+
+ factor=max(factor,0.1);
+
+ ostringstream buf;
+ buf.setf(std::ios::fixed);
+ if(n > 0) {
+ for(size_t i=0; i < n-1; i++)
+ buf << pat[i]*factor << " ";
+ buf << pat[n-1]*factor;
+ }
+ q.setstroke(buf.str());
+ q.setoffset(q.linetype().offset*factor);
+ }
+ return q;
+}
+
+// Account for square or extended pen cap contributions to bounding box.
+void cap(bbox& b, double t, path p, pen pentype) {
+ transform T=pentype.getTransform();
+
+ double h=0.5*pentype.width();
+ pair v=p.dir(t);
+ transform S=rotate(conj(v))*shiftless(T);
+ double xx=S.getxx(), xy=S.getxy();
+ double yx=S.getyx(), yy=S.getyy();
+ double y=hypot(yx,yy);
+ if(y == 0) return;
+ double numer=xx*yx+xy*yy;
+ double x=numer/y;
+ pair z=shift(T)*p.point(t);
+
+ switch(pentype.cap()) {
+ case 0:
+ {
+ pair d=rotate(v)*pair(x,y)*h;
+ b += z+d;
+ b += z-d;
+ break;
+ }
+ case 2:
+ {
+ transform R=rotate(v);
+ double w=(xx*yy-xy*yx)/y;
+ pair dp=R*pair(x+w,y)*h;
+ pair dm=R*pair(x-w,y)*h;
+ b += z+dp;
+ b += z+dm;
+ b += z-dp;
+ b += z-dm;
+ break;
+ }
+ }
+}
+
+void drawPathPenBase::strokebounds(bbox& b, const path& p)
+{
+ Int l=p.length();
+ if(l < 0) return;
+
+ bbox penbounds=pentype.bounds();
+
+ if(cyclic() || pentype.cap() == 1) {
+ b += pad(p.bounds(),penbounds);
+ return;
+ }
+
+ b += p.internalbounds(penbounds);
+
+ cap(b,0,p,pentype);
+ cap(b,l,p,pentype);
+}
+
+bool drawPath::draw(psfile *out)
+{
+ Int n = p.size();
+ if (n == 0 || pentype.invisible())
+ return true;
+
+ pen pen0=adjustdash(pentype,p.arclength(),p.cyclic());
+
+ penSave(out);
+ penTranslate(out);
+
+ out->write(p);
+
+ penConcat(out);
+
+ out->setpen(pen0);
+
+ out->stroke();
+
+ penRestore(out);
+
+ return true;
+}
+
+drawElement *drawPath::transformed(const transform& t)
+{
+ return new drawPath(transpath(t), transpen(t));
+}
+
+} //namespace camp