1 /***** Autogenerated from runlabel.in; changes will be overwritten *****/
2
3 #line 1 "runtimebase.in"
4 /*****
5 * runtimebase.in
6 * Andy Hammerlindl 2009/07/28
7 *
8 * Common declarations needed for all code-generating .in files.
9 *
10 *****/
11
12
13 #line 1 "runlabel.in"
14 /*****
15 * runlabel.in
16 *
17 * Runtime functions for label operations.
18 *
19 *****/
20
21 #line 1 "runtimebase.in"
22 #include "stack.h"
23 #include "types.h"
24 #include "builtin.h"
25 #include "entry.h"
26 #include "errormsg.h"
27 #include "array.h"
28 #include "triple.h"
29 #include "callable.h"
30 #include "opsymbols.h"
31
32 using vm::stack;
33 using vm::error;
34 using vm::array;
35 using vm::read;
36 using vm::callable;
37 using types::formal;
38 using types::function;
39 using camp::triple;
40
41 #define PRIMITIVE(name,Name,asyName) using types::prim##Name;
42 #include <primitives.h>
43 #undef PRIMITIVE
44
45 typedef double real;
46
47 void unused(void *);
48
49 namespace run {
50 array *copyArray(array *a);
51 array *copyArray2(array *a);
52 array *copyArray3(array *a);
53
54 double *copyTripleArray2Components(array *a, bool square=true, size_t dim2=0,
55 GCPlacement placement=NoGC);
56 }
57
58 function *realRealFunction();
59
60 #define CURRENTPEN processData().currentpen
61
62 #line 19 "runlabel.in"
63 #include "picture.h"
64 #include "drawlabel.h"
65 #include "locate.h"
66
67 using namespace camp;
68 using namespace vm;
69 using namespace settings;
70
71 typedef array realarray;
72 typedef array stringarray;
73 typedef array penarray;
74 typedef array patharray;
75 typedef array patharray2;
76
77 using types::realArray;
78 using types::stringArray;
79 using types::penArray;
80 using types::pathArray;
81 using types::pathArray2;
82
cannotread(const string & s)83 void cannotread(const string& s)
84 {
85 ostringstream buf;
86 buf << "Cannot read from " << s;
87 error(buf);
88 }
89
cannotwrite(const string & s)90 void cannotwrite(const string& s)
91 {
92 ostringstream buf;
93 buf << "Cannot write to " << s;
94 error(buf);
95 }
96
readpair(stringstream & s,double hscale=1.0,double vscale=1.0)97 pair readpair(stringstream& s, double hscale=1.0, double vscale=1.0)
98 {
99 double x,y;
100 s >> y;
101 s >> x;
102 return pair(hscale*x,vscale*y);
103 }
104
105 string ASYx="/ASYx {( ) print ASYX sub 12 string cvs print} bind def";
106 string ASYy="/ASYy {( ) print ASYY sub 12 string cvs print} bind def";
107 string pathforall="{(M) print ASYy ASYx} {(L) print ASYy ASYx} {(C) print ASYy ASYx ASYy ASYx ASYy ASYx} {(c) print} pathforall";
108 string currentpoint="print currentpoint ASYy ASYx ";
109 string ASYinit="/ASYX currentpoint pop def /ASYY currentpoint exch pop def ";
110 string ASY1="ASY1 {"+ASYinit+"/ASY1 false def} if ";
111
endpath(std::ostream & ps)112 void endpath(std::ostream& ps)
113 {
114 ps << ASY1 << pathforall << " (M) " << currentpoint
115 << "currentpoint newpath moveto} bind def" << endl;
116 }
117
fillpath(std::ostream & ps)118 void fillpath(std::ostream& ps)
119 {
120 ps << "/fill {closepath ";
121 endpath(ps);
122 }
123
showpath(std::ostream & ps)124 void showpath(std::ostream& ps)
125 {
126 ps << ASYx << newl
127 << ASYy << newl
128 << "/ASY1 true def" << newl
129 << "/stroke {strokepath ";
130 endpath(ps);
131 fillpath(ps);
132 }
133
readpath(const string & psname,bool keep,bool pdf=false,double hscale=1.0,double vsign=1.0)134 array *readpath(const string& psname, bool keep, bool pdf=false,
135 double hscale=1.0, double vsign=1.0)
136 {
137 double vscale=vsign*hscale;
138 array *PP=new array(0);
139
140 char *oldPath=NULL;
141 string dir=stripFile(outname());
142 if(!dir.empty()) {
143 oldPath=getPath();
144 setPath(dir.c_str());
145 }
146
147 mem::vector<string> cmd;
148 cmd.push_back(getSetting<string>("gs"));
149 cmd.push_back("-q");
150 cmd.push_back("-dBATCH");
151 cmd.push_back("-P");
152 if(safe) cmd.push_back("-dSAFER");
153 #ifdef __MSDOS__
154 const string null="NUL";
155 #else
156 const string null="/dev/null";
157 #endif
158 cmd.push_back("-sDEVICE=eps2write");
159 cmd.push_back("-sOutputFile="+null);
160 cmd.push_back(stripDir(psname));
161 iopipestream gs(cmd,"gs","Ghostscript");
162 while(gs.running()) {
163 stringstream buf;
164 string s=gs.readline();
165 if(s.empty()) break;
166 if(!pdf) gs << newl;
167
168 // Workaround broken stringstream container in MacOS 10.9 libc++.
169 #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__ )
170 for(string::iterator i=s.begin(); i != s.end(); ++i) {
171 if(isalpha(*i) && *i != 'e') {buf << " ";}
172 buf << *i;
173 }
174 #else
175 buf << s;
176 #endif
177
178 if(verbose > 2) cout << endl;
179
180 mem::vector<solvedKnot> nodes;
181 solvedKnot node;
182 bool cyclic=false;
183 bool active=false;
184
185 array *P=new array(0);
186 PP->push(P);
187
188 while(!buf.eof()) {
189 char c;
190 buf >> c;
191 if(c == '>') break;
192
193 switch(c) {
194 case 'M':
195 {
196 if(active) {
197 if(cyclic) {
198 if(node.point == nodes[0].point)
199 nodes[0].pre=node.pre;
200 else {
201 pair delta=(nodes[0].point-node.point)*third;
202 node.post=node.point+delta;
203 nodes[0].pre=nodes[0].point-delta;
204 node.straight=true;
205 nodes.push_back(node);
206 }
207 } else {
208 node.post=node.point;
209 node.straight=false;
210 nodes.push_back(node);
211 }
212 if(cyclic) // Discard noncyclic paths.
213 P->push(path(nodes,nodes.size(),cyclic));
214 nodes.clear();
215 }
216 active=false;
217 cyclic=false;
218 node.pre=node.point=readpair(buf,hscale,vscale);
219 node.straight=false;
220 break;
221 }
222 case 'L':
223 {
224 pair point=readpair(buf,hscale,vscale);
225 pair delta=(point-node.point)*third;
226 node.post=node.point+delta;
227 node.straight=true;
228 nodes.push_back(node);
229 active=true;
230 node.pre=point-delta;
231 node.point=point;
232 break;
233 }
234 case 'C':
235 {
236 pair point=readpair(buf,hscale,vscale);
237 pair pre=readpair(buf,hscale,vscale);
238 node.post=readpair(buf,hscale,vscale);
239 node.straight=false;
240 nodes.push_back(node);
241 active=true;
242 node.pre=pre;
243 node.point=point;
244 break;
245 }
246 case 'c':
247 {
248 cyclic=true;
249 break;
250 }
251 }
252 }
253 }
254
255 if(oldPath != NULL)
256 setPath(oldPath);
257
258 if(!keep)
259 unlink(psname.c_str());
260 return PP;
261 }
262
263 // Autogenerated routines:
264
265
266
267 #ifndef NOSYM
268 #include "runlabel.symbols.h"
269
270 #endif
271 namespace run {
272 #line 222 "runlabel.in"
273 // void label(picture *f, string *s, string *size, transform t, pair position, pair align, pen p);
gen_runlabel0(stack * Stack)274 void gen_runlabel0(stack *Stack)
275 {
276 pen p=vm::pop<pen>(Stack);
277 pair align=vm::pop<pair>(Stack);
278 pair position=vm::pop<pair>(Stack);
279 transform t=vm::pop<transform>(Stack);
280 string * size=vm::pop<string *>(Stack);
281 string * s=vm::pop<string *>(Stack);
282 picture * f=vm::pop<picture *>(Stack);
283 #line 224 "runlabel.in"
284 f->append(new drawLabel(*s,*size,t,position,align,p));
285 }
286
287 #line 228 "runlabel.in"
288 // bool labels(picture *f);
gen_runlabel1(stack * Stack)289 void gen_runlabel1(stack *Stack)
290 {
291 picture * f=vm::pop<picture *>(Stack);
292 #line 229 "runlabel.in"
293 {Stack->push<bool>(f->havelabels()); return;}
294 }
295
296 #line 233 "runlabel.in"
297 // realarray* texsize(string *s, pen p=CURRENTPEN);
gen_runlabel2(stack * Stack)298 void gen_runlabel2(stack *Stack)
299 {
300 pen p=vm::pop<pen>(Stack,CURRENTPEN);
301 string * s=vm::pop<string *>(Stack);
302 #line 234 "runlabel.in"
303 texinit();
304 processDataStruct &pd=processData();
305
306 string texengine=getSetting<string>("tex");
307 setpen(pd.tex,texengine,p);
308
309 double width,height,depth;
310 texbounds(width,height,depth,pd.tex,*s);
311
312 array *t=new array(3);
313 (*t)[0]=width;
314 (*t)[1]=height;
315 (*t)[2]=depth;
316 {Stack->push<realarray*>(t); return;}
317 }
318
319 #line 251 "runlabel.in"
320 // patharray2* _texpath(stringarray *s, penarray *p);
gen_runlabel3(stack * Stack)321 void gen_runlabel3(stack *Stack)
322 {
323 penarray * p=vm::pop<penarray *>(Stack);
324 stringarray * s=vm::pop<stringarray *>(Stack);
325 #line 252 "runlabel.in"
326 size_t n=checkArrays(s,p);
327 if(n == 0) {Stack->push<patharray2*>(new array(0)); return;}
328
329 string prefix=cleanpath(outname());
330 string psname=auxname(prefix,"ps");
331 string texname=auxname(prefix,"tex");
332 string dviname=auxname(prefix,"dvi");
333 bbox b;
334 string texengine=getSetting<string>("tex");
335 bool xe=settings::xe(texengine) || settings::context(texengine);
336 texfile tex(texname,b,true);
337 tex.miniprologue();
338
339 for(size_t i=0; i < n; ++i) {
340 tex.setfont(read<pen>(p,i));
341 if(i != 0) {
342 if(texengine == "context")
343 tex.verbatimline("}\\page\\hbox{%");
344 else if(texengine == "luatex" || texengine == "tex" ||
345 texengine == "pdftex")
346 tex.verbatimline("\\eject");
347 else
348 tex.verbatimline("\\newpage");
349 }
350 if(!xe) {
351 tex.verbatimline("\\special{ps:");
352 tex.verbatimline(ASYx);
353 tex.verbatimline(ASYy);
354 tex.verbatimline("/ASY1 true def");
355 tex.verbatimline("/show {"+ASY1+
356 "currentpoint newpath moveto false charpath "+pathforall+
357 "} bind def");
358 tex.verbatimline("/V {"+ASY1+"Ry neg Rx 4 copy 4 2 roll 2 copy 6 2 roll 2 copy (M) print ASYy ASYx (L) print ASYy add ASYx (L) print add ASYy add ASYx (L) print add ASYy ASYx (c) print} bind def}");
359 }
360 tex.verbatimline(read<string>(s,i)+"\\ %");
361 }
362
363 tex.epilogue(true);
364 tex.close();
365
366 int status=opentex(texname,prefix,!xe);
367
368 string pdfname,pdfname2,psname2;
369 bool keep=getSetting<bool>("keep");
370
371 if(!status) {
372 if(xe) {
373 pdfname=auxname(prefix,"pdf");
374 pdfname2=auxname(prefix+"_","pdf");
375 psname2=auxname(prefix+"_","ps");
376 if(!fs::exists(pdfname)) {Stack->push<patharray2*>(new array(n)); return;}
377 std::ofstream ps(psname.c_str(),std::ios::binary);
378 if(!ps) cannotwrite(psname);
379
380 showpath(ps);
381
382 mem::vector<string> pcmd;
383 pcmd.push_back(getSetting<string>("gs"));
384 pcmd.push_back("-q");
385 pcmd.push_back("-dNOCACHE");
386 pcmd.push_back("-dNOPAUSE");
387 pcmd.push_back("-dBATCH");
388 if(safe) pcmd.push_back("-dSAFER");
389 pcmd.push_back("-sDEVICE=pdfwrite");
390 pcmd.push_back("-sOutputFile="+pdfname2);
391 pcmd.push_back(pdfname);
392 status=System(pcmd,0,true,"gs");
393 if(status == 0) {
394 mem::vector<string> cmd;
395 cmd.push_back(getSetting<string>("gs"));
396 cmd.push_back("-q");
397 cmd.push_back("-dNOCACHE");
398 cmd.push_back("-dNOPAUSE");
399 cmd.push_back("-dBATCH");
400 if(safe) cmd.push_back("-dSAFER");
401 cmd.push_back("-sDEVICE=eps2write");
402 // Work around eps2write bug that forces all postscript to first page.
403 cmd.push_back("-sOutputFile="+psname2+"%d");
404 cmd.push_back(pdfname2);
405 status=System(cmd,0,true,"gs");
406
407 for(unsigned int i=1; i <= n ; ++i) {
408 ostringstream buf;
409 buf << psname2.c_str() << i;
410 const char *name=buf.str().c_str();
411 std::ifstream in(name,std::ios::binary);
412 ps << in.rdbuf();
413 ps << "(>\n) print flush\n";
414 if(!keep) unlink(name);
415 }
416 ps.close();
417 }
418 } else {
419 if(!fs::exists(dviname)) {Stack->push<patharray2*>(new array(n)); return;}
420 mem::vector<string> dcmd;
421 dcmd.push_back(getSetting<string>("dvips"));
422 dcmd.push_back("-R");
423 dcmd.push_back("-Pdownload35");
424 dcmd.push_back("-D600");
425 push_split(dcmd,getSetting<string>("dvipsOptions"));
426 if(verbose <= 2) dcmd.push_back("-q");
427 dcmd.push_back("-o"+psname);
428 dcmd.push_back(dviname);
429 status=System(dcmd,0,true,"dvips");
430 }
431 }
432
433 if(status != 0)
434 error("texpath failed");
435
436 if(!keep) { // Delete temporary files.
437 unlink(texname.c_str());
438 if(!getSetting<bool>("keepaux"))
439 unlink(auxname(prefix,"aux").c_str());
440 unlink(auxname(prefix,"log").c_str());
441 if(xe) {
442 unlink(pdfname.c_str());
443 unlink(pdfname2.c_str());
444 } else
445 unlink(dviname.c_str());
446 if(settings::context(texengine)) {
447 unlink(auxname(prefix,"top").c_str());
448 unlink(auxname(prefix,"tua").c_str());
449 unlink(auxname(prefix,"tuc").c_str());
450 unlink(auxname(prefix,"tui").c_str());
451 }
452 }
453 {Stack->push<patharray2*>(xe ? readpath(psname,keep,true,0.1) :
454 readpath(psname,keep,false,0.12,-1.0)); return;}
455 }
456
457 #line 384 "runlabel.in"
458 // patharray2* textpath(stringarray *s, penarray *p);
gen_runlabel4(stack * Stack)459 void gen_runlabel4(stack *Stack)
460 {
461 penarray * p=vm::pop<penarray *>(Stack);
462 stringarray * s=vm::pop<stringarray *>(Stack);
463 #line 385 "runlabel.in"
464 size_t n=checkArrays(s,p);
465 if(n == 0) {Stack->push<patharray2*>(new array(0)); return;}
466
467 string prefix=cleanpath(outname());
468 string outputname=auxname(prefix,getSetting<string>("textoutformat"));
469
470 string textname=auxname(prefix,getSetting<string>("textextension"));
471 std::ofstream text(textname.c_str());
472
473 if(!text) cannotwrite(textname);
474
475 for(size_t i=0; i < n; ++i) {
476 text << getSetting<string>("textprologue") << newl
477 << read<pen>(p,i).Font() << newl
478 << read<string>(s,i) << newl
479 << getSetting<string>("textepilogue") << endl;
480 }
481 text.close();
482
483 string psname=auxname(prefix,"ps");
484 std::ofstream ps(psname.c_str());
485 if(!ps) cannotwrite(psname);
486
487 showpath(ps);
488
489 mem::vector<string> cmd;
490 cmd.push_back(getSetting<string>("textcommand"));
491 push_split(cmd,getSetting<string>("textcommandOptions"));
492 cmd.push_back(textname);
493 iopipestream typesetter(cmd);
494 typesetter.block(true,false);
495
496 mem::vector<string> cmd2;
497 cmd2.push_back(getSetting<string>("gs"));
498 cmd2.push_back("-q");
499 cmd2.push_back("-dNOCACHE");
500 cmd2.push_back("-dNOPAUSE");
501 cmd2.push_back("-dBATCH");
502 cmd2.push_back("-P");
503 if(safe) cmd2.push_back("-dSAFER");
504 cmd2.push_back("-sDEVICE=eps2write");
505 cmd2.push_back("-sOutputFile=-");
506 cmd2.push_back("-");
507 iopipestream gs(cmd2,"gs","Ghostscript");
508 gs.block(false,false);
509
510 // TODO: Simplify by connecting the pipes directly.
511 while(true) {
512 string out;
513 if(typesetter.isopen()) {
514 typesetter >> out;
515 if(!out.empty()) gs << out;
516 else if(!typesetter.running()) {
517 typesetter.pipeclose();
518 gs.eof();
519 }
520 }
521 string out2;
522 gs >> out2;
523 if(out2.empty() && !gs.running()) break;
524 ps << out2;
525 }
526 ps.close();
527
528 if(verbose > 2) cout << endl;
529
530 bool keep=getSetting<bool>("keep");
531 if(!keep) // Delete temporary files.
532 unlink(textname.c_str());
533 {Stack->push<patharray2*>(readpath(psname,keep,false,0.1)); return;}
534 }
535
536 #line 458 "runlabel.in"
537 // patharray* _strokepath(path g, pen p=CURRENTPEN);
gen_runlabel5(stack * Stack)538 void gen_runlabel5(stack *Stack)
539 {
540 pen p=vm::pop<pen>(Stack,CURRENTPEN);
541 path g=vm::pop<path>(Stack);
542 #line 459 "runlabel.in"
543 array *P=new array(0);
544 if(g.size() == 0) {Stack->push<patharray*>(P); return;}
545
546 string prefix=cleanpath(outname());
547 string psname=auxname(prefix,"ps");
548 bbox b;
549 psfile ps(psname,false);
550 ps.prologue(b);
551 ps.verbatimline(ASYx);
552 ps.verbatimline(ASYy);
553 ps.verbatimline("/stroke {"+ASYinit+pathforall+"} bind def");
554 ps.resetpen();
555 ps.setpen(p);
556 ps.write(g);
557 ps.strokepath();
558 ps.stroke(p);
559 ps.verbatimline("(M) "+currentpoint);
560 ps.epilogue();
561 ps.close();
562 array *a=readpath(psname,getSetting<bool>("keep"));
563 {Stack->push<patharray*>(a->size() > 0 ? read<array *>(a,0) : a); return;}
564 }
565
566 } // namespace run
567
568 namespace trans {
569
gen_runlabel_venv(venv & ve)570 void gen_runlabel_venv(venv &ve)
571 {
572 #line 222 "runlabel.in"
573 addFunc(ve, run::gen_runlabel0, primVoid(), SYM(label), formal(primPicture(), SYM(f), false, false), formal(primString(), SYM(s), false, false), formal(primString(), SYM(size), false, false), formal(primTransform(), SYM(t), false, false), formal(primPair(), SYM(position), false, false), formal(primPair(), SYM(align), false, false), formal(primPen(), SYM(p), false, false));
574 #line 228 "runlabel.in"
575 addFunc(ve, run::gen_runlabel1, primBoolean(), SYM(labels), formal(primPicture(), SYM(f), false, false));
576 #line 233 "runlabel.in"
577 addFunc(ve, run::gen_runlabel2, realArray(), SYM(texsize), formal(primString(), SYM(s), false, false), formal(primPen(), SYM(p), true, false));
578 #line 251 "runlabel.in"
579 addFunc(ve, run::gen_runlabel3, pathArray2() , SYM(_texpath), formal(stringArray() , SYM(s), false, false), formal(penArray() , SYM(p), false, false));
580 #line 384 "runlabel.in"
581 addFunc(ve, run::gen_runlabel4, pathArray2() , SYM(textpath), formal(stringArray() , SYM(s), false, false), formal(penArray() , SYM(p), false, false));
582 #line 458 "runlabel.in"
583 addFunc(ve, run::gen_runlabel5, pathArray() , SYM(_strokepath), formal(primPath(), SYM(g), false, false), formal(primPen(), SYM(p), true, false));
584 }
585
586 } // namespace trans
587