NEURON
idraw.cpp
Go to the documentation of this file.
1 #include <../../nrnconf.h>
2 #if HAVE_IV // to end of file
3 
4 #include <stdio.h>
5 #include <ivstream.h>
6 #include <InterViews/color.h>
7 #include <InterViews/brush.h>
8 #include <InterViews/font.h>
9 #include <IV-look/kit.h>
10 #include <InterViews/transformer.h>
11 #include <InterViews/session.h>
12 #include <InterViews/style.h>
13 #include <OS/string.h>
14 
15 #include "scenevie.h"
16 #include "mymath.h"
17 #include "idraw.h"
18 
19 #define out *OcIdraw::idraw_stream
20 
21 extern "C" {
22 extern const char* expand_env_var(const char*);
23 } // extern "C"
24 
25 bool OcIdraw::closed_ = false;
26 bool OcIdraw::curved_ = false;
27 int OcIdraw::ipath_ = 0;
28 int OcIdraw::capacity_ = 0;
31 
32 void OcIdraw::prologue() {
33  filebuf ibuf;
34  Style* s = Session::instance()->style();
36  if (!s->find_attribute("pwm_idraw_prologue", name)) {
37  printf("can't find the \"pwm_idraw_prologue\" attribute\n");
38  printf("will have to prepend the prologue by hand before reading with idraw.\n");
39  return;
40  }
41  name = expand_env_var(name.string());
42 #if defined(WIN32) || defined(MAC)
43  if (!ibuf.open(name.string(), ios::in)) {
44 #else
45  if (!ibuf.open(name.string(), IOS_IN)) {
46 #endif
47  printf("can't open the idraw prologue in %s\n", name.string());
48  return;
49  }
50  out << &ibuf << endl;
51  ibuf.close();
52  if (!xpath_) {
53  capacity_ = 10;
54  xpath_ = new Coord[capacity_];
55  ypath_ = new Coord[capacity_];
56  }
57 }
58 
59 void OcIdraw::epilog() {
60  out << "\
61 End %I eop\n\
62 showpage\n\n\
63 %%Trailer\n\n\
64 end\
65 " << endl;
66 }
67 
68 static void transformer(const Transformer& t) {
69  float a00, a01, a10, a11, a20, a21;
70  t.matrix(a00, a01, a10, a11, a20, a21);
71  char buf[200];
72  sprintf(buf, "[ %g %g %g %g %g %g ] concat", a00, a01, a10, a11, a20, a21);
73  out << buf << endl;
74 }
75 
76 static char* hidepar(const char* s) {
77  static char buf[256];
78  const char* ps;
79  char* pbuf;
80  for (ps = s, pbuf = buf; *ps;) {
81  if (*ps == '(' || *ps == ')') {
82  *pbuf++ = '\\';
83  }
84  *pbuf++ = *ps++;
85  }
86  *pbuf = '\0';
87  return buf;
88 }
89 
90 static void rgbcolor(const Color* c, ColorIntensity& r, ColorIntensity& g, ColorIntensity& b) {
91  // always use black for default_foreground.
92  if (c == Scene::default_foreground()) {
93  r = 0;
94  g = 0;
95  b = 0;
96  } else {
97  c->intensities(r, g, b);
98  }
99 }
100 
101 static void common_pict() {
102  out << "\n\
103 Begin %I Pict\n\
104 %I b u\n\
105 %I cfg u\n\
106 %I cbg u\n\
107 %I f u\n\
108 %I p u\
109 " << endl;
110 }
111 
112 void OcIdraw::pict() {
113  common_pict();
114  out << "%I t u" << endl;
115 }
116 
117 void OcIdraw::pict(const Transformer& t) {
118  common_pict();
119  out << "%I t" << endl;
120  transformer(t);
121 }
122 
123 void OcIdraw::end() {
124  out << "End %I eop" << endl;
125 }
126 
127 void OcIdraw::text(Canvas*,
128  const char* s,
129  const Transformer& t,
130  const Font* font,
131  const Color* color) {
132 #if 1
133  // ZFM tried to allow colors and fonts, but doesn't seem to work
134  // 3/12/95
135  char buf[100];
136  ColorIntensity r = 0, g = 0, b = 0;
137  if (color) {
138  rgbcolor(color, r, g, b);
139  }
140 
141  // idraw needs hex
142  sprintf(buf,
143  "%%I cfg %x%x%x\n%f %f %f SetCFg\n",
144  int(r * 256),
145  int(g * 256),
146  int(b * 256),
147  r,
148  g,
149  b);
150  out << "Begin %I Text\n";
151  out << buf;
152  if (font) {
153  out << "%I f " << font->encoding() << "\n";
154  out << font->name() << font->size() << "SetF\n";
155  } else {
156  out << "\
157 %I f -*-helvetica-medium-r-normal-*-12-*-*-*-*-*-*-*\n\
158 Helvetica 12 SetF\n\
159 ";
160  };
161  out << "%I t" << endl;
162 #else
163  out << "\n\
164 Begin %I Text\n\
165 %I cfg Black\n\
166 0 0 0 SetCFg\n\
167 %I f -*-helvetica-medium-r-normal-*-12-*-*-*-*-*-*-*\n\
168 Helvetica 12 SetF\n\
169 %I t\
170 " << endl;
171 #endif
172  Glyph* l = WidgetKit::instance()->label(s);
173  Requisition req;
174  l->request(req);
175  l->unref();
176  Requirement& ry = req.y_requirement();
177  float y = (1. - ry.alignment()) * ry.natural();
178  float x = 0;
179  Transformer tr(t);
180  tr.translate(x, y);
181  transformer(tr);
182  out << "%I\n[" << endl;
183  out << "(" << hidepar(s) << ")" << endl;
184  out << "] Text\nEnd" << endl;
185 }
186 
187 void OcIdraw::mline(Canvas*,
188  int count,
189  const Coord* x,
190  const Coord* y,
191  const Color* color,
192  const Brush* b) {
193 #define cnt_group 200
194  int ixd[cnt_group], iyd[cnt_group];
195  int i, size;
196  float xmax = x[0], xmin = x[0], ymax = y[0], ymin = y[0];
197 #if 0
198  for (i = 1; i < count; ++i) {
199  if (x[i] > xmax) xmax = x[i];
200  if (x[i] < xmin) xmin = x[i];
201  if (y[i] > ymax) ymax = y[i];
202  if (y[i] < ymin) ymin = y[i];
203  }
204 #endif
206  xmax = v->right();
207  xmin = v->left();
208  ymax = v->top();
209  ymin = v->bottom();
210 
211  float scalex, scaley;
212  if (xmax != xmin) {
213  scalex = 10000 / (xmax - xmin);
214  } else {
215  scalex = 1;
216  }
217  if (ymax != ymin) {
218  scaley = 10000 / (ymax - ymin);
219  } else {
220  scaley = 1;
221  }
222  Transformer t;
223  t.translate(-xmin, -ymin);
224  t.scale(scalex, scaley);
225  t.invert();
226  if (count > cnt_group) {
227  pict();
228  }
229  for (i = 0; i < count;) {
230  int ixold, iyold;
231  ixold = iyold = -20000;
232  for (; i < count; ++i) {
233  if (MyMath::inside(x[i], y[i], xmin, ymin, xmax, ymax)) {
234  break;
235  }
236  }
237  for (size = 0; i < count;) {
238  float x1, y1;
239  int ix, iy;
240  t.inverse_transform(x[i], y[i], x1, y1);
241  if (x1 > 20000.)
242  x1 = 20000.;
243  if (x1 < -20000.)
244  x1 = -20000.;
245  if (y1 > 20000.)
246  y1 = 20000.;
247  if (y1 < -20000.)
248  y1 = -20000.;
249  ix = int(x1);
250  iy = int(y1);
251  if (ix != ixold || iy != iyold) {
252  ixd[size] = ix;
253  iyd[size] = iy;
254  ++size;
255  }
256  if (size >= cnt_group) {
257  break;
258  }
259  ixold = ix;
260  iyold = iy;
261  ++i;
262  }
263  if (size < 2) {
264  break;
265  }
266 #if 1
267  out << "\nBegin %I MLine\n";
268  brush(b);
269  ifill(color, false);
270  out << "%I t" << endl;
271 #else
272  out << "\n\
273 Begin %I MLine\n\
274 %I b 65535\n\
275 0 0 0 [] 0 SetB\n\
276 %I cfg Black\n\
277 0 0 0 SetCFg\n\
278 %I cbg White\n\
279 1 1 1 SetCBg\n\
280 none SetP %I p n\n\
281 %I t\
282 " << endl;
283 #endif
284  transformer(t);
285  out << "%I " << size << endl;
286 
287  for (int j = 0; j < size; ++j) {
288  out << ixd[j] << " " << iyd[j] << endl;
289  }
290 
291  out << size << " MLine\n%I 1\nEnd" << endl;
292  }
293 
294  if (count > cnt_group) {
295  end();
296  }
297 }
298 
299 void OcIdraw::rect(Canvas* c,
300  Coord x1,
301  Coord y1,
302  Coord x2,
303  Coord y2,
304  const Color* color,
305  const Brush* b,
306  bool f) {
307  Coord x[4], y[4];
308  x[0] = x1;
309  y[0] = y1;
310  x[1] = x2;
311  y[1] = y1;
312  x[2] = x2;
313  y[2] = y2;
314  x[3] = x1;
315  y[3] = y2;
316  polygon(c, 4, x, y, color, b, f);
317 }
318 
320  int count,
321  const Coord* x,
322  const Coord* y,
323  const Color* color,
324  const Brush* b,
325  bool f) {
326  char buf[100];
327  out << "\nBegin %I Poly\n";
328  poly(count, x, y, color, b, f);
329  sprintf(buf, "%d Poly\nEnd", count);
330  out << buf << endl;
331 }
332 
333 void OcIdraw::bspl(Canvas*,
334  int count,
335  const Coord* x,
336  const Coord* y,
337  const Color* color,
338  const Brush* b) {
339  char buf[100];
340  out << "\nBegin %I BSpl\n";
341  poly(count, x, y, color, b, false);
342  sprintf(buf, "%d BSpl\n%%I 1\nEnd", count);
343  out << buf << endl;
344 }
345 
346 void OcIdraw::cbspl(Canvas*,
347  int count,
348  const Coord* x,
349  const Coord* y,
350  const Color* color,
351  const Brush* b,
352  bool f) {
353  char buf[100];
354  out << "\nBegin %I CBSpl\n";
355  poly(count, x, y, color, b, f);
356  sprintf(buf, "%d CBSpl\nEnd", count);
357  out << buf << endl;
358 }
359 
360 void OcIdraw::poly(int count,
361  const Coord* x,
362  const Coord* y,
363  const Color* color,
364  const Brush* b,
365  bool f) {
366  brush(b);
367  ifill(color, f);
368  out << "%I t" << endl;
369 
370 
371  float x1, x2, y1, y2;
372  x1 = MyMath::min(count, x);
373  x2 = MyMath::max(count, x);
374  y1 = MyMath::min(count, y);
375  y2 = MyMath::max(count, y);
376  float scalex, scaley;
377  if (Math::equal(x1, x2, float(.0001))) {
378  scalex = 1;
379  } else {
380  scalex = (x2 - x1) / 10000.;
381  }
382  if (Math::equal(y1, y2, float(.0001))) {
383  scaley = 1;
384  } else {
385  scaley = (y2 - y1) / 10000.;
386  }
387  Transformer t;
388  t.scale(scalex, scaley);
389  t.translate(x1, y1);
390  transformer(t);
391  out << "%I " << count << endl;
392  char buf[100];
393  for (int i = 0; i < count; ++i) {
394  float a, b;
395  t.inverse_transform(x[i], y[i], a, b);
396  sprintf(buf, "%d %d\n", int(a), int(b));
397  out << buf;
398  }
399 }
400 
401 void OcIdraw::line(Canvas*,
402  Coord x1,
403  Coord y1,
404  Coord x2,
405  Coord y2,
406  const Color* color,
407  const Brush* b) {
408 #if 1
409  out << "\nBegin %I Line\n";
410  brush(b);
411  ifill(color, false);
412  out << "%I t" << endl;
413 #else
414  out << "\n\
415 Begin %I Line\n\
416 %I b 65535\n\
417 0 0 0 [] 0 SetB\n\
418 %I cfg Black\n\
419 0 0 0 SetCFg\n\
420 %I cbg White\n\
421 1 1 1 SetCBg\n\
422 none SetP %I p n\n\
423 %I t\
424 " << endl;
425 #endif
426 
427  float scalex, scaley;
428  if (Math::equal(x1, x2, float(.0001))) {
429  scalex = 1;
430  } else {
431  scalex = (x2 - x1) / 10000;
432  }
433  if (Math::equal(y1, y2, float(.0001))) {
434  scaley = 1;
435  } else {
436  scaley = (y2 - y1) / 10000;
437  }
438  Transformer t;
439  t.scale(scalex, scaley);
440  t.translate(x1, y1);
441  transformer(t);
442  out << "%I" << endl;
443  float a, bb, x, y;
444  t.inverse_transform(x1, y1, a, bb);
445  t.inverse_transform(x2, y2, x, y);
446  out << int(a) << " " << int(bb) << " " << int(x) << " " << int(y);
447 
448  out << " Line\n%I 1\nEnd" << endl;
449 }
450 
452  Coord x1,
453  Coord y1,
454  Coord width,
455  Coord height,
456  const Color* color,
457  const Brush* b,
458  bool f) {
459  out << "\nBegin %I Elli\n";
460  brush(b);
461  ifill(color, f);
462  out << "%I t" << endl;
463 
464  float y = y1;
465  float x = x1;
466  Transformer tr;
467  tr.scale(.01, .01);
468  tr.translate(x, y);
469  transformer(tr);
470  char buf[100];
471  sprintf(buf, "%%I\n0 0 %d %d Elli\nEnd", int(width * 100), int(height * 100));
472  out << buf << endl;
473 }
474 
475 void OcIdraw::brush(const Brush* b) {
476  char buf[100];
477  Coord w = b ? b->width() : 0;
478  int i, p;
479 
480  p = 0;
481 #if !MAC
482  if (b)
483  for (i = 0; i < b->dash_count(); ++i) {
484  int nbit = b->dash_list(i);
485  for (int j = 0; j < nbit; ++j) {
486  p = ((p << 1) | ((i + 1) % 2));
487  }
488  }
489 #endif
490  sprintf(buf, "%%I b %d\n%d 0 0 [", p, int(w));
491  out << buf;
492 #if !MAC
493  if (b)
494  for (i = 0; i < b->dash_count(); ++i) {
495  out << b->dash_list(i) << " ";
496  }
497 #endif
498  sprintf(buf, "] 0 SetB");
499  out << buf << endl;
500 }
501 
502 void OcIdraw::ifill(const Color* color, bool f) {
503  char buf[100];
504  ColorIntensity r = 0, g = 0, b = 0;
505  if (color) {
506  rgbcolor(color, r, g, b);
507  }
508  // sprintf(buf, "%%I cfg %s\n%d %d %d SetCFg", "Black", 0,0,0);
509  // idraw needs hex
510  sprintf(
511  buf, "%%I cfg %x%x%x\n%f %f %f SetCFg", int(r * 256), int(g * 256), int(b * 256), r, g, b);
512  out << buf << endl;
513  if (f) {
514  // sprintf(buf, "%%I cbg %s\n%d %d %d SetCBg\n%%I p\n1 SetP",
515  // "Black", 0,0,0);
516  sprintf(buf,
517  "%%I cbg %x%x%x\n%f %f %f SetCBg\n%%I p\n1 SetP",
518  int(r * 256),
519  int(g * 256),
520  int(b * 256),
521  r,
522  g,
523  b);
524  } else {
525  sprintf(buf, "%%I cbg %s\n%d %d %d SetCBg\nnone SetP %%I p n", "White", 1, 1, 1);
526  }
527  out << buf << endl;
528 }
529 
530 // only implemented for continuous lines, polygons, and curves.
531 // i.e. only one move_to at beginning and cannot mix line_to and curve_to
532 
533 void OcIdraw::new_path() {
534  curved_ = false;
535  closed_ = false;
536  ipath_ = 0;
537 }
538 
539 void OcIdraw::move_to(Coord x, Coord y) {
540  add(x, y);
541 }
542 
543 void OcIdraw::line_to(Coord x, Coord y) {
544  add(x, y);
545 }
546 
547 void OcIdraw::curve_to(Coord x, Coord y, Coord x1, Coord y1, Coord x2, Coord y2) {
548  curved_ = true;
549 #if 0
550  add(x1, y1);
551  add(x2, y2);
552  add(x, y);
553 #else // http://www.timotheegroleau.com/Flash/articles/cubic_bezier_in_flash.htm
554  rcurve(0, x, y, x1, y1, x2, y2); // first arg is recursion level
555 #endif
556 }
557 
558 void OcIdraw::rcurve(int r, Coord x, Coord y, Coord x1, Coord y1, Coord x2, Coord y2) {
559  if (r < 2) {
560  // split into two bezier
561  Coord m01x = (xpath_[ipath_ - 1] + x1) / 2;
562  Coord m01y = (ypath_[ipath_ - 1] + y1) / 2;
563  Coord m12x = (x1 + x2) / 2;
564  Coord m12y = (y1 + y2) / 2;
565  Coord m23x = (x2 + x) / 2;
566  Coord m23y = (y2 + y) / 2;
567  Coord ax = (m01x + m12x) / 2;
568  Coord ay = (m01y + m12y) / 2;
569  Coord bx = (m12x + m23x) / 2;
570  Coord by = (m12y + m23y) / 2;
571  Coord cx = (ax + bx) / 2;
572  Coord cy = (ay + by) / 2;
573  rcurve(r + 1, cx, cy, m01x, m01y, ax, ay);
574  rcurve(r + 1, x, y, bx, by, m23x, m23y);
575  } else {
576  add((x1 + x2) / 2, (y1 + y2) / 2);
577  add(x, y);
578  }
579 }
580 
581 void OcIdraw::close_path() {
582  closed_ = true;
583  if (curved_) {
584  curve_to(
585  xpath_[0], ypath_[0], xpath_[ipath_ - 1], ypath_[ipath_ - 1], xpath_[0], ypath_[0]);
586  }
587 }
588 
589 void OcIdraw::stroke(Canvas* can, const Color* c, const Brush* b) {
590  if (closed_) {
591  if (curved_) {
592  cbspl(can, ipath_, xpath_, ypath_, c, b, false);
593  } else {
594  polygon(can, ipath_, xpath_, ypath_, c, b, false);
595  }
596  } else {
597  if (curved_) {
598  bspl(can, ipath_, xpath_, ypath_, c, b);
599  } else {
600  mline(can, ipath_, xpath_, ypath_, c, b);
601  }
602  }
603 }
604 
605 void OcIdraw::fill(Canvas* can, const Color* c) {
606  if (curved_) {
607  cbspl(can, ipath_, xpath_, ypath_, c, NULL, true);
608  } else {
609  polygon(can, ipath_, xpath_, ypath_, c, NULL, true);
610  }
611 }
612 
613 void OcIdraw::add(Coord a, Coord b) {
614  if (ipath_ >= capacity_) {
615  capacity_ *= 2;
616  Coord* x = new Coord[capacity_];
617  Coord* y = new Coord[capacity_];
618  for (int i = 0; i < ipath_; ++i) {
619  x[i] = xpath_[i];
620  y[i] = ypath_[i];
621  }
622  delete[] xpath_;
623  delete[] ypath_;
624  xpath_ = x;
625  ypath_ = y;
626  }
627  xpath_[ipath_] = a;
628  ypath_[ipath_] = b;
629  ++ipath_;
630 }
631 
632 #endif
#define Color
Definition: _defines.h:74
#define ColorIntensity
Definition: _defines.h:17
#define Transformer
Definition: _defines.h:316
#define Canvas
Definition: _defines.h:65
#define Style
Definition: _defines.h:281
#define Coord
Definition: _defines.h:19
#define Brush
Definition: _defines.h:59
#define Font
Definition: _defines.h:120
#define Glyph
Definition: _defines.h:132
static bool equal(float x, float y, float e)
Definition: math.h:108
static float max(int count, const float *)
Definition: mymath.cpp:104
static bool inside(Coord x, Coord min, Coord max)
Definition: mymath.h:94
static float min(int count, const float *)
Definition: mymath.cpp:94
static void curve_to(Coord x, Coord y, Coord x1, Coord y1, Coord x2, Coord y2)
static int ipath_
Definition: idraw.h:101
static void mline(Canvas *, int count, const Coord *x, const Coord *y, const Color *c=NULL, const Brush *b=NULL)
static void poly(int count, const Coord *x, const Coord *y, const Color *c=NULL, const Brush *b=NULL, bool fill=false)
static void bspl(Canvas *, int count, const Coord *x, const Coord *y, const Color *c=NULL, const Brush *b=NULL)
static void rcurve(int level, Coord x, Coord y, Coord x1, Coord y1, Coord x2, Coord y2)
static int capacity_
Definition: idraw.h:101
static void close_path()
static void add(Coord, Coord)
static void move_to(Coord x, Coord y)
static bool curved_
Definition: idraw.h:99
static Coord * ypath_
Definition: idraw.h:100
static void pict()
static bool closed_
Definition: idraw.h:98
static void line(Canvas *, Coord x1, Coord y1, Coord x2, Coord y2, const Color *c=NULL, const Brush *b=NULL)
static void polygon(Canvas *, int count, const Coord *x, const Coord *y, const Color *c=NULL, const Brush *b=NULL, bool fill=false)
static void text(Canvas *, const char *, const Transformer &, const Font *f=NULL, const Color *c=NULL)
static void brush(const Brush *)
static void prologue()
static void line_to(Coord x, Coord y)
static void stroke(Canvas *, const Color *, const Brush *)
static void new_path()
static void rect(Canvas *, Coord x1, Coord y1, Coord x2, Coord y2, const Color *c=NULL, const Brush *b=NULL, bool fill=false)
static void cbspl(Canvas *, int count, const Coord *x, const Coord *y, const Color *c=NULL, const Brush *b=NULL, bool fill=false)
static void end()
static void ellipse(Canvas *, Coord x1, Coord y1, Coord width, Coord height, const Color *c=NULL, const Brush *b=NULL, bool fill=false)
static Coord * xpath_
Definition: idraw.h:100
static void ifill(const Color *, bool)
static void epilog()
static void fill(Canvas *, const Color *)
void alignment(float)
Definition: geometry.h:241
void natural(Coord)
Definition: geometry.h:235
const Requirement & y_requirement() const
Definition: geometry.h:250
static const Color * default_foreground()
static XYView * current_draw_view()
double t
Definition: cvodeobj.cpp:59
sprintf(buf, " if (secondorder) {\n" " int _i;\n" " for (_i = 0; _i < %d; ++_i) {\n" " _p[_slist%d[_i]] += dt*_p[_dlist%d[_i]];\n" " }}\n", numeqn, listnum, listnum)
#define c
char buf[512]
Definition: init.cpp:13
const char * expand_env_var(const char *s)
Definition: fileio.cpp:122
#define IOS_IN
Definition: ivstream.h:9
#define v
Definition: md1redef.h:4
#define i
Definition: md1redef.h:12
char * name
Definition: init.cpp:16
#define printf
Definition: mwprefix.h:26
size_t p
size_t j
#define g
Definition: passive0.cpp:21
#define color
Definition: rbtqueue.cpp:50
#define NULL
Definition: sptree.h:16