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