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,
92  // always use black for default_foreground.
93  if (c == Scene::default_foreground()) {
94  r = 0; g = 0; 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 " << endl;
109 }
110 
111 void OcIdraw::pict() {
112  common_pict();
113  out << "%I t u" << endl;
114 }
115 
116 void OcIdraw::pict(const Transformer& t) {
117  common_pict();
118  out << "%I t" << endl;
119  transformer(t);
120 }
121 
122 void OcIdraw::end() {
123  out << "End %I eop" << endl;
124 }
125 
126 void OcIdraw::text(Canvas*, const char* s, const Transformer& t,
127  const Font* font, const Color* color) {
128 #if 1
129 // ZFM tried to allow colors and fonts, but doesn't seem to work
130 // 3/12/95
131  char buf[100];
132  ColorIntensity r=0,g=0,b=0;
133  if (color) {
134  rgbcolor(color, r,g,b);
135  }
136 
137  // idraw needs hex
138  sprintf(buf, "%%I cfg %x%x%x\n%f %f %f SetCFg\n",
139  int(r*256),int(g*256),int(b*256), r, g, b);
140  out << "Begin %I Text\n";
141  out << buf;
142  if (font) {
143  out << "%I f " << font->encoding() << "\n";
144  out << font->name() << font->size() << "SetF\n";
145  }else{
146 out << "\
147 %I f -*-helvetica-medium-r-normal-*-12-*-*-*-*-*-*-*\n\
148 Helvetica 12 SetF\n\
149 ";
150  };
151  out << "%I t" << endl;
152 #else
153 out << "\n\
154 Begin %I Text\n\
155 %I cfg Black\n\
156 0 0 0 SetCFg\n\
157 %I f -*-helvetica-medium-r-normal-*-12-*-*-*-*-*-*-*\n\
158 Helvetica 12 SetF\n\
159 %I t\
160 " << endl;
161 #endif
162  Glyph* l = WidgetKit::instance()->label(s);
163  Requisition req;
164  l->request(req);
165  l->unref();
166  Requirement& ry = req.y_requirement();
167  float y = (1. - ry.alignment())*ry.natural();
168  float x = 0;
169  Transformer tr(t);
170  tr.translate(x, y);
171  transformer(tr);
172  out << "%I\n[" << endl;
173  out << "(" << hidepar(s) << ")" << endl;
174  out << "] Text\nEnd" << endl;
175 }
176 
177 void OcIdraw::mline(Canvas*, int count, const Coord* x, const Coord* y,
178  const Color* color, const Brush* b) {
179 #define cnt_group 200
180  int ixd[cnt_group], iyd[cnt_group];
181  int i, size;
182  float xmax = x[0], xmin = x[0], ymax = y[0], ymin = y[0];
183 #if 0
184  for (i = 1; i < count; ++i) {
185  if (x[i] > xmax) xmax = x[i];
186  if (x[i] < xmin) xmin = x[i];
187  if (y[i] > ymax) ymax = y[i];
188  if (y[i] < ymin) ymin = y[i];
189  }
190 #endif
192  xmax = v->right();
193  xmin = v->left();
194  ymax = v->top();
195  ymin = v->bottom();
196 
197  float scalex, scaley;
198  if (xmax != xmin) {
199  scalex = 10000/(xmax - xmin);
200  }else{
201  scalex = 1;
202  }
203  if (ymax != ymin) {
204  scaley = 10000/(ymax - ymin);
205  }else{
206  scaley = 1;
207  }
208  Transformer t;
209  t.translate(-xmin, -ymin);
210  t.scale(scalex, scaley);
211  t.invert();
212  if (count > cnt_group) {
213  pict();
214  }
215  for (i = 0; i < count;) {
216  int ixold, iyold;
217  ixold = iyold = -20000;
218  for (; i < count; ++i) {
219  if (MyMath::inside(x[i], y[i], xmin, ymin, xmax, ymax)) {
220  break;
221  }
222  }
223  for (size = 0; i < count;) {
224  float x1, y1;
225  int ix, iy;
226  t.inverse_transform(x[i], y[i], x1, y1);
227  if (x1 > 20000.) x1 = 20000.;
228  if (x1 < -20000.) x1 = -20000.;
229  if (y1 > 20000.) y1 = 20000.;
230  if (y1 < -20000.) y1 = -20000.;
231  ix = int(x1);
232  iy = int(y1);
233  if (ix != ixold || iy != iyold) {
234  ixd[size] = ix;
235  iyd[size] = iy;
236  ++size;
237  }
238  if (size >= cnt_group) {
239  break;
240  }
241  ixold = ix;
242  iyold = iy;
243  ++i;
244  }
245  if (size < 2) {
246  break;
247  }
248 #if 1
249  out << "\nBegin %I MLine\n";
250  brush(b);
251  ifill(color, false);
252  out << "%I t" << endl;
253 #else
254 out << "\n\
255 Begin %I MLine\n\
256 %I b 65535\n\
257 0 0 0 [] 0 SetB\n\
258 %I cfg Black\n\
259 0 0 0 SetCFg\n\
260 %I cbg White\n\
261 1 1 1 SetCBg\n\
262 none SetP %I p n\n\
263 %I t\
264 " << endl;
265 #endif
266  transformer(t);
267  out << "%I " << size << endl;
268 
269  for (int j=0; j < size; ++j ) {
270  out << ixd[j] << " " << iyd[j]<< endl;
271  }
272 
273  out << size << " MLine\n%I 1\nEnd" << endl;
274  }
275 
276  if (count > cnt_group) {
277  end();
278  }
279 }
280 
281 void OcIdraw::rect(Canvas* c, Coord x1, Coord y1, Coord x2, Coord y2,
282  const Color* color, const Brush* b, bool f)
283 {
284  Coord x[4], y[4];
285  x[0] = x1; y[0] = y1;
286  x[1] = x2; y[1] = y1;
287  x[2] = x2; y[2] = y2;
288  x[3] = x1; y[3] = y2;
289  polygon(c, 4, x, y, color, b, f);
290 }
291 
292 void OcIdraw::polygon(Canvas*, int count, const Coord* x, const Coord* y,
293  const Color* color, const Brush* b, bool f) {
294  char buf[100];
295  out << "\nBegin %I Poly\n";
296  poly(count, x, y, color, b, f);
297  sprintf(buf, "%d Poly\nEnd", count);
298  out << buf << endl;
299 }
300 
301 void OcIdraw::bspl(Canvas*, int count, const Coord* x, const Coord* y,
302  const Color* color, const Brush* b) {
303  char buf[100];
304  out << "\nBegin %I BSpl\n";
305  poly(count, x, y, color, b, false);
306  sprintf(buf, "%d BSpl\n%%I 1\nEnd", count);
307  out << buf << endl;
308 }
309 
310 void OcIdraw::cbspl(Canvas*, int count, const Coord* x, const Coord* y,
311  const Color* color, const Brush* b, bool f) {
312  char buf[100];
313  out << "\nBegin %I CBSpl\n";
314  poly(count, x, y, color, b, f);
315  sprintf(buf, "%d CBSpl\nEnd", count);
316  out << buf << endl;
317 }
318 
319 void OcIdraw::poly(int count, const Coord* x, const Coord* y,
320  const Color* color, const Brush* b, bool f) {
321  brush(b);
322  ifill(color, f);
323  out << "%I t" << endl;
324 
325 
326  float x1, x2, y1, y2;
327  x1 = MyMath::min(count, x);
328  x2 = MyMath::max(count, x);
329  y1 = MyMath::min(count, y);
330  y2 = MyMath::max(count, y);
331  float scalex, scaley;
332  if (Math::equal(x1, x2, float(.0001))) {
333  scalex = 1;
334  }else{
335  scalex = (x2 - x1)/10000.;
336  }
337  if (Math::equal(y1, y2, float(.0001))) {
338  scaley = 1;
339  }else{
340  scaley = (y2 - y1)/10000.;
341  }
342  Transformer t;
343  t.scale(scalex, scaley);
344  t.translate(x1, y1);
345  transformer(t);
346  out << "%I " << count << endl;
347  char buf[100];
348  for (int i=0; i < count; ++i) {
349  float a, b;
350  t.inverse_transform(x[i], y[i], a, b);
351  sprintf(buf, "%d %d\n", int(a), int(b));
352  out << buf;
353  }
354 }
355 
356 void OcIdraw::line(Canvas*, Coord x1, Coord y1, Coord x2, Coord y2,
357  const Color* color, const Brush* b) {
358 #if 1
359  out << "\nBegin %I Line\n";
360  brush(b);
361  ifill(color, false);
362  out << "%I t" << endl;
363 #else
364 out << "\n\
365 Begin %I Line\n\
366 %I b 65535\n\
367 0 0 0 [] 0 SetB\n\
368 %I cfg Black\n\
369 0 0 0 SetCFg\n\
370 %I cbg White\n\
371 1 1 1 SetCBg\n\
372 none SetP %I p n\n\
373 %I t\
374 " << endl;
375 #endif
376 
377  float scalex, scaley;
378  if (Math::equal(x1, x2, float(.0001))) {
379  scalex = 1;
380  }else{
381  scalex = (x2 - x1)/10000;
382  }
383  if (Math::equal(y1, y2, float(.0001))) {
384  scaley = 1;
385  }else{
386  scaley = (y2 - y1)/10000;
387  }
388  Transformer t;
389  t.scale(scalex, scaley);
390  t.translate(x1, y1);
391  transformer(t);
392  out << "%I"<< endl;
393  float a, bb, x, y;
394  t.inverse_transform(x1, y1, a, bb);
395  t.inverse_transform(x2, y2, x, y);
396  out << int(a) << " " << int(bb) << " " << int(x) << " " << int(y);
397 
398  out << " Line\n%I 1\nEnd" << endl;
399 }
400 
401 void OcIdraw::ellipse(Canvas*, Coord x1, Coord y1,
402  Coord width, Coord height,
403  const Color* color, const Brush* b, bool f)
404 {
405 
406  out << "\nBegin %I Elli\n";
407  brush(b);
408  ifill(color, f);
409  out << "%I t" << endl;
410 
411  float y = y1;
412  float x = x1;
413  Transformer tr;
414  tr.scale(.01,.01);
415  tr.translate(x, y);
416  transformer(tr);
417  char buf[100];
418  sprintf(buf, "%%I\n0 0 %d %d Elli\nEnd", int(width*100), int(height*100));
419  out << buf << endl;
420 
421 }
422 
423 void OcIdraw::brush(const Brush* b) {
424  char buf[100];
425  Coord w = b?b->width():0;
426  int i, p;
427 
428  p = 0;
429 #if !MAC
430  if(b) for (i=0; i < b->dash_count(); ++i) {
431  int nbit = b->dash_list(i);
432  for (int j = 0; j < nbit; ++j) {
433  p = ((p << 1) | ((i+1)%2));
434  }
435  }
436 #endif
437  sprintf(buf, "%%I b %d\n%d 0 0 [", p, int(w));
438  out << buf;
439 #if !MAC
440  if (b) for (i=0; i < b->dash_count(); ++i) {
441  out << b->dash_list(i) << " ";
442  }
443 #endif
444  sprintf(buf, "] 0 SetB");
445  out << buf << endl;
446 }
447 
448 void OcIdraw::ifill(const Color* color, bool f) {
449  char buf[100];
450  ColorIntensity r=0,g=0,b=0;
451  if (color) {
452  rgbcolor(color,r,g,b);
453  }
454 // sprintf(buf, "%%I cfg %s\n%d %d %d SetCFg", "Black", 0,0,0);
455  // idraw needs hex
456  sprintf(buf, "%%I cfg %x%x%x\n%f %f %f SetCFg",
457  int(r*256),int(g*256),int(b*256),r,g,b);
458  out << buf << endl;
459  if (f) {
460 // sprintf(buf, "%%I cbg %s\n%d %d %d SetCBg\n%%I p\n1 SetP",
461 // "Black", 0,0,0);
462  sprintf(buf, "%%I cbg %x%x%x\n%f %f %f SetCBg\n%%I p\n1 SetP",
463  int(r*256),int(g*256),int(b*256), r,g,b);
464  }else{
465  sprintf(buf, "%%I cbg %s\n%d %d %d SetCBg\nnone SetP %%I p n",
466  "White", 1,1,1);
467  }
468  out << buf << endl;
469 }
470 
471 // only implemented for continuous lines, polygons, and curves.
472 // i.e. only one move_to at beginning and cannot mix line_to and curve_to
473 
474 void OcIdraw::new_path() {
475  curved_ = false;
476  closed_ = false;
477  ipath_ = 0;
478 }
479 
480 void OcIdraw::move_to(Coord x, Coord y) {
481  add(x, y);
482 }
483 
484 void OcIdraw::line_to(Coord x, Coord y) {
485  add(x, y);
486 }
487 
488 void OcIdraw::curve_to(Coord x, Coord y, Coord x1, Coord y1, Coord x2, Coord y2) {
489  curved_ = true;
490 #if 0
491  add(x1, y1);
492  add(x2, y2);
493  add(x, y);
494 #else //http://www.timotheegroleau.com/Flash/articles/cubic_bezier_in_flash.htm
495  rcurve(0, x,y, x1,y1, x2,y2); // first arg is recursion level
496 #endif
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(xpath_[0], ypath_[0], xpath_[ipath_-1], ypath_[ipath_-1], xpath_[0], ypath_[0]);
526  }
527 }
528 
529 void OcIdraw::stroke(Canvas* can, const Color* c, const Brush* b) {
530  if (closed_) {
531  if (curved_) {
532  cbspl(can, ipath_, xpath_, ypath_, c, b, false);
533  }else{
534  polygon(can, ipath_, xpath_, ypath_, c, b, false);
535  }
536  }else{
537  if (curved_) {
538  bspl(can, ipath_, xpath_, ypath_, c, b);
539  }else{
540  mline(can, ipath_, xpath_, ypath_, c, b);
541  }
542  }
543 }
544 
545 void OcIdraw::fill(Canvas* can, const Color* c) {
546  if (curved_) {
547  cbspl(can, ipath_, xpath_, ypath_, c, NULL, true);
548  }else{
549  polygon(can, ipath_, xpath_, ypath_, c, NULL, true);
550  }
551 }
552 
553 void OcIdraw::add(Coord a, Coord b) {
554  if (ipath_ >= capacity_) {
555  capacity_ *= 2;
556  Coord* x = new Coord[capacity_];
557  Coord* y = new Coord[capacity_];
558  for (int i=0; i < ipath_; ++i) {
559  x[i] = xpath_[i];
560  y[i] = ypath_[i];
561  }
562  delete[] xpath_;
563  delete[] ypath_;
564  xpath_ = x;
565  ypath_ = y;
566  }
567  xpath_[ipath_] = a;
568  ypath_[ipath_] = b;
569  ++ipath_;
570 }
571 
572 #endif
virtual Coord bottom() const
static void fill(Canvas *, const Color *)
static void curve_to(Coord x, Coord y, Coord x1, Coord y1, Coord x2, Coord y2)
static void bspl(Canvas *, int count, const Coord *x, const Coord *y, const Color *c=NULL, const Brush *b=NULL)
#define g
Definition: passive0.cpp:23
#define Glyph
Definition: _defines.h:132
#define Coord
Definition: _defines.h:19
#define Brush
Definition: _defines.h:59
static bool equal(float x, float y, float e)
Definition: math.h:108
size_t p
#define Color
Definition: _defines.h:74
const char * expand_env_var(const char *s)
Definition: fileio.cpp:146
virtual Coord top() const
static Coord * ypath_
Definition: idraw.h:57
#define v
Definition: md1redef.h:4
static int ipath_
Definition: idraw.h:58
static void brush(const Brush *)
sprintf(buf," if (secondorder) {\ " int _i;\" " for(_i=0;_i< %d;++_i) {\" " _p[_slist%d[_i]]+=dt *_p[_dlist%d[_i]];\" " }}\", numeqn, listnum, listnum)
static bool inside(Coord x, Coord min, Coord max)
Definition: mymath.h:97
#define IOS_IN
Definition: ivstream.h:9
const char * string() const
Definition: string.h:139
static float min(int count, const float *)
Definition: mymath.cpp:93
static const Color * default_foreground()
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 poly(int count, const Coord *x, const Coord *y, const Color *c=NULL, const Brush *b=NULL, bool fill=false)
#define Font
Definition: _defines.h:120
#define color
Definition: rbtqueue.cpp:50
static Coord * xpath_
Definition: idraw.h:57
const Requirement & y_requirement() const
Definition: geometry.h:250
_CONST char * s
Definition: system.cpp:74
virtual Coord left() const
#define printf
Definition: mwprefix.h:26
void alignment(float)
Definition: geometry.h:241
int
Definition: nrnmusic.cpp:71
static XYView * current_draw_view()
#define Canvas
Definition: _defines.h:65
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 ifill(const Color *, bool)
size_t j
static void close_path()
static void new_path()
char * name
Definition: init.cpp:16
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 line_to(Coord x, Coord y)
static int capacity_
Definition: idraw.h:58
#define ColorIntensity
Definition: _defines.h:17
static void prologue()
static void line(Canvas *, Coord x1, Coord y1, Coord x2, Coord y2, const Color *c=NULL, const Brush *b=NULL)
static void mline(Canvas *, int count, const Coord *x, const Coord *y, const Color *c=NULL, const Brush *b=NULL)
static void move_to(Coord x, Coord y)
#define Transformer
Definition: _defines.h:316
static void pict()
static float max(int count, const float *)
Definition: mymath.cpp:103
static bool closed_
Definition: idraw.h:55
static void add(Coord, Coord)
#define i
Definition: md1redef.h:12
#define c
static void rcurve(int level, Coord x, Coord y, Coord x1, Coord y1, Coord x2, Coord y2)
char buf[512]
Definition: init.cpp:13
#define Style
Definition: _defines.h:281
static void text(Canvas *, const char *, const Transformer &, const Font *f=NULL, const Color *c=NULL)
double t
Definition: init.cpp:123
static void end()
static bool curved_
Definition: idraw.h:56
virtual Coord right() const
return NULL
Definition: cabcode.cpp:461
static void epilog()
static void stroke(Canvas *, const Color *, const Brush *)
void natural(Coord)
Definition: geometry.h:235
static void ellipse(Canvas *, Coord x1, Coord y1, Coord width, Coord height, const Color *c=NULL, const Brush *b=NULL, bool fill=false)