1 /*----------------------------------------------------------------------------
2 * SciPlot A generalized plotting widget
3 *
4 * Copyright (c) 1996 Robert W. McMullen
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the Free
18 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 *
20 *
21 * Author: Rob McMullen <rwmcm@mail.ae.utexas.edu>
22 * http://www.ae.utexas.edu/~rwmcm
23 */
24
25 #include <X11/IntrinsicP.h>
26 #include <X11/StringDefs.h>
27
28 #include <stdio.h>
29
30 #include "SciPlotP.h"
31
32 #define offset(field) XtOffsetOf(SciPlotRec, plot.field)
33 static XtResource resources[] =
34 {
35 {XtNchartType, XtCMargin, XtRInt, sizeof(int),
36 offset(ChartType), XtRImmediate, (XtPointer) XtCARTESIAN},
37 {XtNdegrees, XtCBoolean, XtRBoolean, sizeof(Boolean),
38 offset(Degrees), XtRImmediate, (XtPointer) True},
39 {XtNdrawMajor, XtCBoolean, XtRBoolean, sizeof(Boolean),
40 offset(DrawMajor), XtRImmediate, (XtPointer) True},
41 {XtNdrawMajorTics, XtCBoolean, XtRBoolean, sizeof(Boolean),
42 offset(DrawMajorTics), XtRImmediate, (XtPointer) True},
43 {XtNdrawMinor, XtCBoolean, XtRBoolean, sizeof(Boolean),
44 offset(DrawMinor), XtRImmediate, (XtPointer) True},
45 {XtNdrawMinorTics, XtCBoolean, XtRBoolean, sizeof(Boolean),
46 offset(DrawMinorTics), XtRImmediate, (XtPointer) True},
47 {XtNmonochrome, XtCBoolean, XtRBoolean, sizeof(Boolean),
48 offset(Monochrome), XtRImmediate, (XtPointer) False},
49 {XtNshowLegend, XtCBoolean, XtRBoolean, sizeof(Boolean),
50 offset(ShowLegend), XtRImmediate, (XtPointer) True},
51 {XtNshowTitle, XtCBoolean, XtRBoolean, sizeof(Boolean),
52 offset(ShowTitle), XtRImmediate, (XtPointer) True},
53 {XtNshowXLabel, XtCBoolean, XtRBoolean, sizeof(Boolean),
54 offset(ShowXLabel), XtRImmediate, (XtPointer) True},
55 {XtNshowYLabel, XtCBoolean, XtRBoolean, sizeof(Boolean),
56 offset(ShowYLabel), XtRImmediate, (XtPointer) True},
57 {XtNxLabel, XtCString, XtRString, sizeof(String),
58 offset(TransientXLabel), XtRString, "X Axis"},
59 {XtNyLabel, XtCString, XtRString, sizeof(String),
60 offset(TransientYLabel), XtRString, "Y Axis"},
61 {XtNplotTitle, XtCString, XtRString, sizeof(String),
62 offset(TransientPlotTitle), XtRString, "Plot"},
63 {XtNmargin, XtCMargin, XtRInt, sizeof(int),
64 offset(Margin), XtRImmediate, (XtPointer) 5},
65 {XtNtitleMargin, XtCMargin, XtRInt, sizeof(int),
66 offset(TitleMargin), XtRImmediate, (XtPointer) 16},
67 {XtNlegendLineSize, XtCMargin, XtRInt, sizeof(int),
68 offset(LegendLineSize), XtRImmediate, (XtPointer) 16},
69 {XtNdefaultMarkerSize, XtCMargin, XtRInt, sizeof(int),
70 offset(DefaultMarkerSize), XtRImmediate, (XtPointer) 3},
71 {XtNlegendMargin, XtCMargin, XtRInt, sizeof(int),
72 offset(LegendMargin), XtRImmediate, (XtPointer) 3},
73 {XtNlegendThroughPlot, XtCBoolean, XtRBoolean, sizeof(Boolean),
74 offset(LegendThroughPlot), XtRImmediate, (XtPointer) False},
75 {XtNtitleFont, XtCMargin, XtRInt, sizeof(int),
76 offset(TitleFont), XtRImmediate, (XtPointer) (XtFONT_HELVETICA | 24)},
77 {XtNlabelFont, XtCMargin, XtRInt, sizeof(int),
78 offset(LabelFont), XtRImmediate, (XtPointer) (XtFONT_TIMES | 18)},
79 {XtNaxisFont, XtCMargin, XtRInt, sizeof(int),
80 offset(AxisFont), XtRImmediate, (XtPointer) (XtFONT_TIMES | 10)},
81 {XtNxAutoScale, XtCBoolean, XtRBoolean, sizeof(Boolean),
82 offset(XAutoScale), XtRImmediate, (XtPointer) True},
83 {XtNyAutoScale, XtCBoolean, XtRBoolean, sizeof(Boolean),
84 offset(YAutoScale), XtRImmediate, (XtPointer) True},
85 {XtNxAxisNumbers, XtCBoolean, XtRBoolean, sizeof(Boolean),
86 offset(XAxisNumbers), XtRImmediate, (XtPointer) True},
87 {XtNyAxisNumbers, XtCBoolean, XtRBoolean, sizeof(Boolean),
88 offset(YAxisNumbers), XtRImmediate, (XtPointer) True},
89 {XtNxLog, XtCBoolean, XtRBoolean, sizeof(Boolean),
90 offset(XLog), XtRImmediate, (XtPointer) False},
91 {XtNyLog, XtCBoolean, XtRBoolean, sizeof(Boolean),
92 offset(YLog), XtRImmediate, (XtPointer) False},
93 {XtNxOrigin, XtCBoolean, XtRBoolean, sizeof(Boolean),
94 offset(XOrigin), XtRImmediate, (XtPointer) False},
95 {XtNyOrigin, XtCBoolean, XtRBoolean, sizeof(Boolean),
96 offset(YOrigin), XtRImmediate, (XtPointer) False},
97 {XtNyNumbersHorizontal, XtCBoolean, XtRBoolean, sizeof(Boolean),
98 offset(YNumHorz), XtRImmediate, (XtPointer) True},
99 };
100
101 static SciPlotFontDesc font_desc_table[] =
102 {
103 {XtFONT_TIMES, "Times", "times", False, True},
104 {XtFONT_COURIER, "Courier", "courier", True, False},
105 {XtFONT_HELVETICA, "Helvetica", "helvetica", True, False},
106 {XtFONT_LUCIDA, "Lucida", "lucidabright", False, False},
107 {XtFONT_LUCIDASANS, "LucidaSans", "lucida", False, False},
108 {XtFONT_NCSCHOOLBOOK, "NewCenturySchlbk",
109 "new century schoolbook", False, True},
110 {-1, NULL, NULL, False, False},
111 };
112
113 /*
114 * Private function declarations
115 */
116
117 static void Redisplay();
118 static void Resize();
119 static Boolean SetValues();
120 static void GetValuesHook();
121 static void Initialize();
122 static void Realize();
123 static void Destroy();
124
125 static void ComputeAll();
126 static void ComputeAllDimensions();
127 static void DrawAll();
128 static void ItemDrawAll();
129 static void ItemDraw();
130 static void EraseAll();
131 static void FontInit();
132 static int ColorStore();
133 static int FontStore();
134 static int FontnumReplace();
135
136
137
138 SciPlotClassRec sciplotClassRec =
139 {
140 {
141 /* core_class fields */
142 #ifdef MOTIF
143 /* superclass */ (WidgetClass) & xmPrimitiveClassRec,
144 #else
145 /* superclass */ (WidgetClass) & widgetClassRec,
146 #endif
147 /* class_name */ "SciPlot",
148 /* widget_size */ sizeof(SciPlotRec),
149 /* class_initialize */ NULL,
150 /* class_part_initialize */ NULL,
151 /* class_inited */ False,
152 /* initialize */ Initialize,
153 /* initialize_hook */ NULL,
154 /* realize */ Realize,
155 /* actions */ NULL,
156 /* num_actions */ 0,
157 /* resources */ resources,
158 /* num_resources */ XtNumber(resources),
159 /* xrm_class */ NULLQUARK,
160 /* compress_motion */ True,
161 /* compress_exposure */ XtExposeCompressMultiple,
162 /* compress_enterleave */ True,
163 /* visible_interest */ True,
164 /* destroy */ Destroy,
165 /* resize */ Resize,
166 /* expose */ Redisplay,
167 /* set_values */ SetValues,
168 /* set_values_hook */ NULL,
169 /* set_values_almost */ XtInheritSetValuesAlmost,
170 /* get_values_hook */ GetValuesHook,
171 /* accept_focus */ NULL,
172 /* version */ XtVersion,
173 /* callback_private */ NULL,
174 /* tm_table */ NULL,
175 /* query_geometry */ NULL,
176 /* display_accelerator */ XtInheritDisplayAccelerator,
177 /* extension */ NULL
178 },
179 #ifdef MOTIF
180 {
181 /* primitive_class fields */
182 /* border_highlight */ (XtWidgetProc) _XtInherit,
183 /* border_unhighligh */ (XtWidgetProc) _XtInherit,
184 /* translations */ XtInheritTranslations,
185 /* arm_and_activate */ (XtWidgetProc) _XtInherit,
186 /* syn_resources */ NULL,
187 /* num_syn_resources */ 0,
188 /* extension */ NULL
189 },
190 #endif
191 {
192 /* plot_class fields */
193 /* dummy */ 0
194 /* (some stupid compilers barf on empty structures) */
195 }
196 };
197
198 WidgetClass sciplotWidgetClass = (WidgetClass) & sciplotClassRec;
199
200
201 static void
Initialize(Widget treq,Widget tnew,ArgList args,Cardinal * num)202 Initialize(Widget treq, Widget tnew, ArgList args, Cardinal *num)
203 {
204 SciPlotWidget new;
205
206 new = (SciPlotWidget) tnew;
207
208 new->plot.plotlist = NULL;
209 new->plot.alloc_plotlist = 0;
210 new->plot.num_plotlist = 0;
211
212 new->plot.alloc_drawlist = NUMPLOTITEMALLOC;
213 new->plot.drawlist = (SciPlotItem *) XtCalloc(new->plot.alloc_drawlist,
214 sizeof(SciPlotItem));
215 new->plot.num_drawlist = 0;
216
217 new->plot.cmap = DefaultColormap(XtDisplay(new),
218 DefaultScreen(XtDisplay(new)));
219
220 new->plot.xlabel = (char *) XtMalloc(strlen(new->plot.TransientXLabel) + 1);
221 strcpy(new->plot.xlabel, new->plot.TransientXLabel);
222 new->plot.ylabel = (char *) XtMalloc(strlen(new->plot.TransientYLabel) + 1);
223 strcpy(new->plot.ylabel, new->plot.TransientYLabel);
224 new->plot.plotTitle = (char *) XtMalloc(strlen(new->plot.TransientPlotTitle) + 1);
225 strcpy(new->plot.plotTitle, new->plot.TransientPlotTitle);
226 new->plot.TransientXLabel=NULL;
227 new->plot.TransientYLabel=NULL;
228 new->plot.TransientPlotTitle=NULL;
229
230 new->plot.colors = NULL;
231 new->plot.num_colors = 0;
232 new->plot.fonts = NULL;
233 new->plot.num_fonts = 0;
234
235 new->plot.update = FALSE;
236 new->plot.UserMin.x = new->plot.UserMin.y = 0.0;
237 new->plot.UserMax.x = new->plot.UserMax.y = 10.0;
238
239 new->plot.titleFont = FontStore(new, new->plot.TitleFont);
240 new->plot.labelFont = FontStore(new, new->plot.LabelFont);
241 new->plot.axisFont = FontStore(new, new->plot.AxisFont);
242 }
243
244 static void
GCInitialize(SciPlotWidget new)245 GCInitialize(SciPlotWidget new)
246 {
247 XGCValues values;
248 XtGCMask mask;
249 long colorsave;
250
251 values.line_style = LineSolid;
252 values.line_width = 0;
253 values.fill_style = FillSolid;
254 values.background = WhitePixelOfScreen(XtScreen(new));
255 values.background = new->core.background_pixel;
256 new->plot.BackgroundColor = ColorStore(new, values.background);
257 #ifdef MOTIF
258 new->core.background_pixel = values.background;
259 #endif
260 values.foreground = colorsave = BlackPixelOfScreen(XtScreen(new));
261 new->plot.ForegroundColor = ColorStore(new, values.foreground);
262
263 mask = GCLineStyle | GCLineWidth | GCFillStyle | GCForeground | GCBackground;
264 new->plot.defaultGC = XCreateGC(XtDisplay(new),XtWindow(new), mask, &values);
265
266 values.foreground = colorsave;
267 values.line_style = LineOnOffDash;
268 new->plot.dashGC = XCreateGC(XtDisplay(new),XtWindow(new), mask, &values);
269 }
270
271 static void
Realize(Widget aw,XtValueMask * value_mask,XSetWindowAttributes * attributes)272 Realize(Widget aw, XtValueMask * value_mask, XSetWindowAttributes * attributes)
273 {
274 SciPlotWidget w = (SciPlotWidget) aw;
275
276 #define superclass (&widgetClassRec)
277 (*superclass->core_class.realize) (aw, value_mask, attributes);
278 #undef superclass
279
280 GCInitialize(w);
281 }
282
283 static void
Destroy(SciPlotWidget w)284 Destroy(SciPlotWidget w)
285 {
286 int i;
287 SciPlotFont *pf;
288 SciPlotList *p;
289
290 XFreeGC(XtDisplay(w), w->plot.defaultGC);
291 XFreeGC(XtDisplay(w), w->plot.dashGC);
292 XtFree((char *) w->plot.xlabel);
293 XtFree((char *) w->plot.ylabel);
294 XtFree((char *) w->plot.plotTitle);
295
296 for (i = 0; i < w->plot.num_fonts; i++) {
297 pf = &w->plot.fonts[i];
298 XFreeFont(XtDisplay((Widget) w), pf->font);
299 }
300 XtFree((char *) w->plot.fonts);
301
302 XtFree((char *) w->plot.colors);
303
304 for (i = 0; i < w->plot.alloc_plotlist; i++) {
305 p = w->plot.plotlist + i;
306 if (p->allocated > 0)
307 XtFree((char *) p->data);
308 if (p->legend)
309 XtFree(p->legend);
310 }
311 if (w->plot.alloc_plotlist > 0)
312 XtFree((char *) w->plot.plotlist);
313
314 EraseAll(w);
315 XtFree((char *) w->plot.drawlist);
316 }
317
318 static Boolean
SetValues(SciPlotWidget current,SciPlotWidget request,SciPlotWidget new,ArgList args,Cardinal nargs)319 SetValues(SciPlotWidget current, SciPlotWidget request, SciPlotWidget new,
320 ArgList args, Cardinal nargs)
321 {
322 Boolean redisplay = FALSE;
323
324 if (current->plot.XLog != new->plot.XLog)
325 redisplay = TRUE;
326 else if (current->plot.YLog != new->plot.YLog)
327 redisplay = TRUE;
328 else if (current->plot.XOrigin != new->plot.XOrigin)
329 redisplay = TRUE;
330 else if (current->plot.YOrigin != new->plot.YOrigin)
331 redisplay = TRUE;
332 else if (current->plot.XAxisNumbers != new->plot.XAxisNumbers)
333 redisplay = TRUE;
334 else if (current->plot.YAxisNumbers != new->plot.YAxisNumbers)
335 redisplay = TRUE;
336 else if (current->plot.DrawMajor != new->plot.DrawMajor)
337 redisplay = TRUE;
338 else if (current->plot.DrawMajorTics != new->plot.DrawMajorTics)
339 redisplay = TRUE;
340 else if (current->plot.DrawMinor != new->plot.DrawMinor)
341 redisplay = TRUE;
342 else if (current->plot.DrawMinorTics != new->plot.DrawMinorTics)
343 redisplay = TRUE;
344 else if (current->plot.ChartType != new->plot.ChartType)
345 redisplay = TRUE;
346 else if (current->plot.Degrees != new->plot.Degrees)
347 redisplay = TRUE;
348 else if (current->plot.ShowLegend != new->plot.ShowLegend)
349 redisplay = TRUE;
350 else if (current->plot.ShowTitle != new->plot.ShowTitle)
351 redisplay = TRUE;
352 else if (current->plot.ShowXLabel != new->plot.ShowXLabel)
353 redisplay = TRUE;
354 else if (current->plot.ShowYLabel != new->plot.ShowYLabel)
355 redisplay = TRUE;
356 else if (current->plot.ShowTitle != new->plot.ShowTitle)
357 redisplay = TRUE;
358 else if (current->plot.Monochrome != new->plot.Monochrome)
359 redisplay = TRUE;
360
361 if (new->plot.TransientXLabel) {
362 if (current->plot.TransientXLabel != new->plot.TransientXLabel ||
363 strcmp(new->plot.TransientXLabel,current->plot.xlabel)!=0) {
364 redisplay = TRUE;
365 XtFree(current->plot.xlabel);
366 new->plot.xlabel = (char *) XtMalloc(strlen(new->plot.TransientXLabel) + 1);
367 strcpy(new->plot.xlabel, new->plot.TransientXLabel);
368 new->plot.TransientXLabel=NULL;
369 }
370 }
371 if (new->plot.TransientYLabel) {
372 if (current->plot.TransientYLabel != new->plot.TransientYLabel ||
373 strcmp(new->plot.TransientYLabel,current->plot.ylabel)!=0) {
374 redisplay = TRUE;
375 XtFree(current->plot.ylabel);
376 new->plot.ylabel = (char *) XtMalloc(strlen(new->plot.TransientYLabel) + 1);
377 strcpy(new->plot.ylabel, new->plot.TransientYLabel);
378 new->plot.TransientYLabel=NULL;
379 }
380 }
381 if (new->plot.TransientPlotTitle) {
382 if (current->plot.TransientPlotTitle != new->plot.TransientPlotTitle ||
383 strcmp(new->plot.TransientPlotTitle,current->plot.plotTitle)!=0) {
384 redisplay = TRUE;
385 XtFree(current->plot.plotTitle);
386 new->plot.plotTitle = (char *) XtMalloc(strlen(new->plot.TransientPlotTitle) + 1);
387 strcpy(new->plot.plotTitle, new->plot.TransientPlotTitle);
388 new->plot.TransientPlotTitle=NULL;
389 }
390 }
391
392 if (current->plot.AxisFont != new->plot.AxisFont) {
393 redisplay = TRUE;
394 FontnumReplace(new, new->plot.axisFont, new->plot.AxisFont);
395 }
396 if (current->plot.TitleFont != new->plot.TitleFont) {
397 redisplay = TRUE;
398 FontnumReplace(new, new->plot.titleFont, new->plot.TitleFont);
399 }
400 if (current->plot.LabelFont != new->plot.LabelFont) {
401 redisplay = TRUE;
402 FontnumReplace(new, new->plot.labelFont, new->plot.LabelFont);
403 }
404
405 new->plot.update = redisplay;
406
407 return redisplay;
408 }
409
410 static void
GetValuesHook(SciPlotWidget w,ArgList args,Cardinal * num_args)411 GetValuesHook(SciPlotWidget w, ArgList args, Cardinal *num_args)
412 {
413 int i;
414 char **loc;
415
416 for (i=0; i<*num_args; i++) {
417 loc=(char **)args[i].value;
418 if (strcmp(args[i].name,XtNplotTitle)==0)
419 *loc=w->plot.plotTitle;
420 else if (strcmp(args[i].name,XtNxLabel)==0)
421 *loc=w->plot.xlabel;
422 else if (strcmp(args[i].name,XtNyLabel)==0)
423 *loc=w->plot.ylabel;
424
425 }
426 }
427
428
429 static void
Redisplay(SciPlotWidget w)430 Redisplay(SciPlotWidget w)
431 {
432 if (!XtIsRealized((Widget)w))
433 return;
434
435 if (w->plot.update) {
436 Resize(w);
437 w->plot.update = FALSE;
438 }
439 else {
440 ItemDrawAll(w);
441 }
442 }
443
444 static void
Resize(SciPlotWidget w)445 Resize(SciPlotWidget w)
446 {
447 if (!XtIsRealized((Widget)w))
448 return;
449
450 EraseAll(w);
451 ComputeAll(w);
452 DrawAll(w);
453 }
454
455
456 /*
457 * Private SciPlot utility functions
458 */
459
460
461 static int
ColorStore(SciPlotWidget w,Pixel color)462 ColorStore (SciPlotWidget w, Pixel color)
463 {
464 w->plot.num_colors++;
465 w->plot.colors = (Pixel *) XtRealloc((char *) w->plot.colors,
466 sizeof(Pixel) * w->plot.num_colors);
467 w->plot.colors[w->plot.num_colors - 1] = color;
468 return w->plot.num_colors - 1;
469 }
470
471 static void
FontnumStore(SciPlotWidget w,int fontnum,int flag)472 FontnumStore (SciPlotWidget w, int fontnum, int flag)
473 {
474 SciPlotFont *pf;
475 int fontflag, sizeflag, attrflag;
476
477 pf = &w->plot.fonts[fontnum];
478
479 fontflag = flag & XtFONT_NAME_MASK;
480 sizeflag = flag & XtFONT_SIZE_MASK;
481 attrflag = flag & XtFONT_ATTRIBUTE_MASK;
482
483 switch (fontflag) {
484 case XtFONT_TIMES:
485 case XtFONT_COURIER:
486 case XtFONT_HELVETICA:
487 case XtFONT_LUCIDA:
488 case XtFONT_LUCIDASANS:
489 case XtFONT_NCSCHOOLBOOK:
490 break;
491 default:
492 fontflag = XtFONT_NAME_DEFAULT;
493 break;
494 }
495
496 if (sizeflag < 1)
497 sizeflag = XtFONT_SIZE_DEFAULT;
498
499 switch (attrflag) {
500 case XtFONT_BOLD:
501 case XtFONT_ITALIC:
502 case XtFONT_BOLD_ITALIC:
503 break;
504 default:
505 attrflag = XtFONT_ATTRIBUTE_DEFAULT;
506 break;
507 }
508 pf->id = flag;
509 FontInit(w, pf);
510 }
511
512 static int
FontnumReplace(SciPlotWidget w,int fontnum,int flag)513 FontnumReplace (SciPlotWidget w, int fontnum, int flag)
514 {
515 SciPlotFont *pf;
516
517 pf = &w->plot.fonts[fontnum];
518 XFreeFont(XtDisplay(w), pf->font);
519
520 FontnumStore(w, fontnum, flag);
521
522 return fontnum;
523 }
524
525 static int
FontStore(SciPlotWidget w,int flag)526 FontStore (SciPlotWidget w, int flag)
527 {
528 int fontnum;
529
530 w->plot.num_fonts++;
531 w->plot.fonts = (SciPlotFont *) XtRealloc((char *) w->plot.fonts,
532 sizeof(SciPlotFont) * w->plot.num_fonts);
533 fontnum = w->plot.num_fonts - 1;
534
535 FontnumStore(w, fontnum, flag);
536
537 return fontnum;
538 }
539
540 static SciPlotFontDesc *
FontDescLookup(int flag)541 FontDescLookup (int flag)
542 {
543 SciPlotFontDesc *pfd;
544
545 pfd = font_desc_table;
546 while (pfd->flag >= 0) {
547 #ifdef DEBUG_SCIPLOT
548 printf("checking if %d == %d (font %s)\n",
549 flag & XtFONT_NAME_MASK, pfd->flag, pfd->PostScript);
550 #endif
551 if ((flag & XtFONT_NAME_MASK) == pfd->flag)
552 return pfd;
553 pfd++;
554 }
555 return NULL;
556 }
557
558
559 static void
FontnumPostScriptString(SciPlotWidget w,int fontnum,char * str)560 FontnumPostScriptString (SciPlotWidget w, int fontnum, char *str)
561 {
562 char temp[128];
563 int flag, bold, italic;
564 SciPlotFontDesc *pfd;
565
566 flag = w->plot.fonts[fontnum].id;
567 pfd = FontDescLookup(flag);
568 if (pfd) {
569 strcpy(temp, pfd->PostScript);
570 bold = False;
571 italic = False;
572 if (flag & XtFONT_BOLD) {
573 bold = True;
574 strcat(temp, "-Bold");
575 }
576 if (flag & XtFONT_ITALIC) {
577 italic = True;
578 if (!bold)
579 strcat(temp, "-");
580 if (pfd->PSUsesOblique)
581 strcat(temp, "Oblique");
582 else
583 strcat(temp, "Italic");
584 }
585 if (!bold && !italic && pfd->PSUsesRoman) {
586 strcat(temp, "-Roman");
587 }
588
589 sprintf(str, "/%s findfont %d scalefont",
590 temp,
591 (flag & XtFONT_SIZE_MASK));
592 }
593 else
594 sprintf(str, "/Courier findfond 10 scalefont");
595 }
596
597 static void
FontX11String(int flag,char * str)598 FontX11String (int flag, char *str)
599 {
600 SciPlotFontDesc *pfd;
601
602 pfd = FontDescLookup(flag);
603 if (pfd) {
604 sprintf(str, "-*-%s-%s-%s-*-*-%d-*-*-*-*-*-*-*",
605 pfd->X11,
606 (flag & XtFONT_BOLD ? "bold" : "medium"),
607 (flag & XtFONT_ITALIC ? (pfd->PSUsesOblique ? "o" : "i") : "r"),
608 (flag & XtFONT_SIZE_MASK));
609 }
610 else
611 sprintf(str, "fixed");
612 #ifdef DEBUG_SCIPLOT
613 printf("font string=%s\n", str);
614 #endif
615 }
616
617 static void
FontInit(SciPlotWidget w,SciPlotFont * pf)618 FontInit (SciPlotWidget w, SciPlotFont *pf)
619 {
620 char str[256], **list;
621 int num;
622
623 FontX11String(pf->id, str);
624 list = XListFonts(XtDisplay(w), str, 100, &num);
625 #ifdef DEBUG_SCIPLOT
626 if (1) {
627 int i;
628
629 i = 0;
630 while (i < num) {
631 printf("Found font: %s\n", list[i]);
632 i++;
633 }
634 }
635 #endif
636 if (num <= 0) {
637 pf->id &= ~XtFONT_ATTRIBUTE_MASK;
638 pf->id |= XtFONT_ATTRIBUTE_DEFAULT;
639 FontX11String(pf->id, str);
640 list = XListFonts(XtDisplay(w), str, 100, &num);
641 #ifdef DEBUG_SCIPLOT
642 if (1) {
643 int i;
644
645 i = 0;
646 while (i < num) {
647 printf("Attr reset: found: %s\n", list[i]);
648 i++;
649 }
650 }
651 #endif
652 }
653 if (num <= 0) {
654 pf->id &= ~XtFONT_NAME_MASK;
655 pf->id |= XtFONT_NAME_DEFAULT;
656 FontX11String(pf->id, str);
657 list = XListFonts(XtDisplay(w), str, 100, &num);
658 #ifdef DEBUG_SCIPLOT
659 if (1) {
660 int i;
661
662 i = 0;
663 while (i < num) {
664 printf("Name reset: found: %s\n", list[i]);
665 i++;
666 }
667 }
668 #endif
669 }
670 if (num <= 0) {
671 pf->id &= ~XtFONT_SIZE_MASK;
672 pf->id |= XtFONT_SIZE_DEFAULT;
673 FontX11String(pf->id, str);
674 list = XListFonts(XtDisplay(w), str, 100, &num);
675 #ifdef DEBUG_SCIPLOT
676 if (1) {
677 int i;
678
679 i = 0;
680 while (i < num) {
681 printf("Size reset: found: %s\n", list[i]);
682 i++;
683 }
684 }
685 #endif
686 }
687 if (num <= 0)
688 strcpy(str, "fixed");
689 else
690 XFreeFontNames(list);
691 pf->font = XLoadQueryFont(XtDisplay(w), str);
692 }
693
694 static XFontStruct *
FontFromFontnum(SciPlotWidget w,int fontnum)695 FontFromFontnum (SciPlotWidget w, int fontnum)
696 {
697 XFontStruct *f;
698
699 if (fontnum >= w->plot.num_fonts)
700 fontnum = 0;
701 f = w->plot.fonts[fontnum].font;
702 return f;
703 }
704
705 static real
FontHeight(XFontStruct * f)706 FontHeight(XFontStruct *f)
707 {
708 return (real) (f->max_bounds.ascent + f->max_bounds.descent);
709 }
710
711 static real
FontnumHeight(SciPlotWidget w,int fontnum)712 FontnumHeight(SciPlotWidget w, int fontnum)
713 {
714 XFontStruct *f;
715
716 f = FontFromFontnum(w, fontnum);
717 return FontHeight(f);
718 }
719
720 static real
FontDescent(XFontStruct * f)721 FontDescent(XFontStruct *f)
722 {
723 return (real) (f->max_bounds.descent);
724 }
725
726 static real
FontnumDescent(SciPlotWidget w,int fontnum)727 FontnumDescent(SciPlotWidget w, int fontnum)
728 {
729 XFontStruct *f;
730
731 f = FontFromFontnum(w, fontnum);
732 return FontDescent(f);
733 }
734
735 static real
FontAscent(XFontStruct * f)736 FontAscent(XFontStruct *f)
737 {
738 return (real) (f->max_bounds.ascent);
739 }
740
741 static real
FontnumAscent(SciPlotWidget w,int fontnum)742 FontnumAscent(SciPlotWidget w, int fontnum)
743 {
744 XFontStruct *f;
745
746 f = FontFromFontnum(w, fontnum);
747 return FontAscent(f);
748 }
749
750 static real
FontTextWidth(XFontStruct * f,char * c)751 FontTextWidth(XFontStruct *f, char *c)
752 {
753 return (real) XTextWidth(f, c, strlen(c));
754 }
755
756 static real
FontnumTextWidth(SciPlotWidget w,int fontnum,char * c)757 FontnumTextWidth(SciPlotWidget w, int fontnum, char *c)
758 {
759 XFontStruct *f;
760
761 f = FontFromFontnum(w, fontnum);
762 return FontTextWidth(f, c);
763 }
764
765
766 /*
767 * Private List functions
768 */
769
770 static int
_ListNew(SciPlotWidget w)771 _ListNew (SciPlotWidget w)
772 {
773 int index;
774 SciPlotList *p;
775 Boolean found;
776
777 /* First check to see if there is any free space in the index */
778 found = FALSE;
779 for (index = 0; index < w->plot.num_plotlist; index++) {
780 p = w->plot.plotlist + index;
781 if (!p->used) {
782 found = TRUE;
783 break;
784 }
785 }
786
787 /* If no space is found, increase the size of the index */
788 if (!found) {
789 w->plot.num_plotlist++;
790 if (w->plot.alloc_plotlist == 0) {
791 w->plot.alloc_plotlist = NUMPLOTLINEALLOC;
792 w->plot.plotlist = (SciPlotList *) XtCalloc(w->plot.alloc_plotlist, sizeof(SciPlotList));
793 if (!w->plot.plotlist) {
794 printf("Can't calloc memory for SciPlotList\n");
795 exit(1);
796 }
797 w->plot.alloc_plotlist = NUMPLOTLINEALLOC;
798 }
799 else if (w->plot.num_plotlist > w->plot.alloc_plotlist) {
800 w->plot.alloc_plotlist += NUMPLOTLINEALLOC;
801 w->plot.plotlist = (SciPlotList *) XtRealloc((char *) w->plot.plotlist,
802 w->plot.alloc_plotlist * sizeof(SciPlotList));
803 if (!w->plot.plotlist) {
804 printf("Can't realloc memory for SciPlotList\n");
805 exit(1);
806 }
807 }
808 index = w->plot.num_plotlist - 1;
809 p = w->plot.plotlist + index;
810 }
811
812 p->LineStyle = p->LineColor = p->PointStyle = p->PointColor = 0;
813 p->number = p->allocated = 0;
814 p->data = NULL;
815 p->legend = NULL;
816 p->draw = p->used = TRUE;
817 p->markersize = (real) w->plot.DefaultMarkerSize;
818 return index;
819 }
820
821 static void
_ListDelete(SciPlotList * p)822 _ListDelete (SciPlotList *p)
823 {
824 p->draw = p->used = FALSE;
825 p->number = p->allocated = 0;
826 if (p->data)
827 XtFree((char *) p->data);
828 p->data = NULL;
829 if (p->legend)
830 XtFree((char *) p->legend);
831 p->legend = NULL;
832 }
833
834 static SciPlotList *
_ListFind(SciPlotWidget w,int id)835 _ListFind (SciPlotWidget w, int id)
836 {
837 SciPlotList *p;
838
839 if ((id >= 0) && (id < w->plot.num_plotlist)) {
840 p = w->plot.plotlist + id;
841 if (p->used)
842 return p;
843 }
844 return NULL;
845 }
846
847 static void
_ListSetStyle(SciPlotList * p,int pcolor,int pstyle,int lcolor,int lstyle)848 _ListSetStyle (SciPlotList *p, int pcolor, int pstyle, int lcolor, int lstyle)
849 {
850 /* Note! Do checks in here later on... */
851
852 if (lstyle >= 0)
853 p->LineStyle = lstyle;
854 if (lcolor >= 0)
855 p->LineColor = lcolor;
856 if (pstyle >= 0)
857 p->PointStyle = pstyle;
858 if (pcolor >= 0)
859 p->PointColor = pcolor;
860 }
861
862 static void
_ListSetLegend(SciPlotList * p,char * legend)863 _ListSetLegend (SciPlotList *p, char *legend)
864 {
865 /* Note! Do checks in here later on... */
866
867 p->legend = (char *) XtMalloc(strlen(legend) + 1);
868 strcpy(p->legend, legend);
869 }
870
871 static void
_ListAllocData(SciPlotList * p,int num)872 _ListAllocData (SciPlotList *p, int num)
873 {
874 if (p->data) {
875 XtFree((char *) p->data);
876 p->allocated = 0;
877 }
878 p->allocated = num + NUMPLOTDATAEXTRA;
879 p->data = (realpair *) XtCalloc(p->allocated, sizeof(realpair));
880 if (!p->data) {
881 p->number = p->allocated = 0;
882 }
883 }
884
885 static void
_ListReallocData(SciPlotList * p,int more)886 _ListReallocData (SciPlotList *p, int more)
887 {
888 if (!p->data) {
889 _ListAllocData(p, more);
890 }
891 else if (p->number + more > p->allocated) {
892 p->allocated += more + NUMPLOTDATAEXTRA;
893 p->data = (realpair *) XtRealloc((char *) p->data, p->allocated * sizeof(realpair));
894 if (!p->data) {
895 p->number = p->allocated = 0;
896 }
897 }
898
899 }
900
901 static void
_ListAddReal(SciPlotList * p,int num,real * xlist,real * ylist)902 _ListAddReal (SciPlotList *p, int num, real *xlist, real *ylist)
903 {
904 int i;
905
906 _ListReallocData(p, num);
907 if (p->data) {
908 for (i = 0; i < num; i++) {
909 p->data[i + p->number].x = xlist[i];
910 p->data[i + p->number].y = ylist[i];
911 }
912 p->number += num;
913 }
914 }
915
916 static void
_ListAddFloat(SciPlotList * p,int num,float * xlist,float * ylist)917 _ListAddFloat (SciPlotList *p, int num, float *xlist, float *ylist)
918 {
919 int i;
920
921 _ListReallocData(p, num);
922 if (p->data) {
923 for (i = 0; i < num; i++) {
924 p->data[i + p->number].x = xlist[i];
925 p->data[i + p->number].y = ylist[i];
926 }
927 p->number += num;
928 }
929 }
930
931 static void
_ListAddDouble(SciPlotList * p,int num,double * xlist,double * ylist)932 _ListAddDouble (SciPlotList *p, int num, double *xlist, double *ylist)
933 {
934 int i;
935
936 _ListReallocData(p, num);
937 if (p->data) {
938 for (i = 0; i < num; i++) {
939 p->data[i + p->number].x = xlist[i];
940 p->data[i + p->number].y = ylist[i];
941 }
942 p->number += num;
943 }
944 }
945
946 static void
_ListSetReal(SciPlotList * p,int num,real * xlist,real * ylist)947 _ListSetReal(SciPlotList *p, int num, real *xlist, real *ylist)
948 {
949 if ((!p->data) || (p->allocated < num))
950 _ListAllocData(p, num);
951 p->number = 0;
952 _ListAddReal(p, num, xlist, ylist);
953 }
954
955 static void
_ListSetFloat(SciPlotList * p,int num,float * xlist,float * ylist)956 _ListSetFloat (SciPlotList *p, int num, float *xlist, float *ylist)
957 {
958 if ((!p->data) || (p->allocated < num))
959 _ListAllocData(p, num);
960 p->number = 0;
961 _ListAddFloat(p, num, xlist, ylist);
962 }
963
964 static void
_ListSetDouble(SciPlotList * p,int num,double * xlist,double * ylist)965 _ListSetDouble (SciPlotList *p, int num, double *xlist, double *ylist)
966 {
967 if ((!p->data) || (p->allocated < num))
968 _ListAllocData(p, num);
969 p->number = 0;
970 _ListAddDouble(p, num, xlist, ylist);
971 }
972
973
974 /*
975 * Private SciPlot functions
976 */
977
978
979 /*
980 * The following vertical text drawing routine uses the "Fill Stippled" idea
981 * found in xvertext-5.0, by Alan Richardson (mppa3@syma.sussex.ac.uk).
982 *
983 * The following code is my interpretation of his idea, including some
984 * hacked together excerpts from his source. The credit for the clever bits
985 * belongs to him.
986 *
987 * To be complete, portions of the subroutine XDrawVString are
988 * Copyright (c) 1993 Alan Richardson (mppa3@syma.sussex.ac.uk)
989 */
990 static void
XDrawVString(Display * display,Window win,GC gc,int x,int y,char * str,int len,XFontStruct * f)991 XDrawVString (Display *display, Window win, GC gc, int x, int y, char *str, int len, XFontStruct *f)
992 {
993 XImage *before, *after;
994 char *dest, *source;
995 int xloop, yloop, xdest, ydest;
996 Pixmap pix, rotpix;
997 int width, height;
998 GC drawGC;
999
1000 width = (int) FontTextWidth(f, str);
1001 height = (int) FontHeight(f);
1002
1003 pix = XCreatePixmap(display, win, width, height, 1);
1004 rotpix = XCreatePixmap(display, win, height, width, 1);
1005
1006 drawGC = XCreateGC(display, pix, 0L, NULL);
1007 XSetBackground(display, drawGC, 0);
1008 XSetFont(display, drawGC, f->fid);
1009 XSetForeground(display, drawGC, 0);
1010 XFillRectangle(display, pix, drawGC, 0, 0, width, height);
1011 XFillRectangle(display, rotpix, drawGC, 0, 0, height, width);
1012 XSetForeground(display, drawGC, 1);
1013
1014 XDrawImageString(display, pix, drawGC, 0, (int) FontAscent(f),
1015 str, strlen(str));
1016
1017 source = (char *) XtCalloc((((width + 7) / 8) * height), 1);
1018 before = XCreateImage(display, DefaultVisual(display, DefaultScreen(display)),
1019 1, XYPixmap, 0, source, width, height, 8, 0);
1020 before->byte_order = before->bitmap_bit_order = MSBFirst;
1021 XGetSubImage(display, pix, 0, 0, width, height, 1L, XYPixmap, before, 0, 0);
1022 source = (char *) XtCalloc((((height + 7) / 8) * width), 1);
1023 after = XCreateImage(display, DefaultVisual(display, DefaultScreen(display)),
1024 1, XYPixmap, 0, source, height, width, 8, 0);
1025 after->byte_order = after->bitmap_bit_order = MSBFirst;
1026
1027 for (yloop = 0; yloop < height; yloop++) {
1028 for (xloop = 0; xloop < width; xloop++) {
1029 source = before->data + (xloop / 8) +
1030 (yloop * before->bytes_per_line);
1031 if (*source & (128 >> (xloop % 8))) {
1032 dest = after->data + (yloop / 8) +
1033 ((width - 1 - xloop) * after->bytes_per_line);
1034 *dest |= (128 >> (yloop % 8));
1035 }
1036 }
1037 }
1038
1039 #ifdef DEBUG_SCIPLOT_VTEXT
1040 if (1) {
1041 char sourcebit;
1042
1043 for (yloop = 0; yloop < before->height; yloop++) {
1044 for (xloop = 0; xloop < before->width; xloop++) {
1045 source = before->data + (xloop / 8) +
1046 (yloop * before->bytes_per_line);
1047 sourcebit = *source & (128 >> (xloop % 8));
1048 if (sourcebit)
1049 putchar('X');
1050 else
1051 putchar('.');
1052 }
1053 putchar('\n');
1054 }
1055
1056 for (yloop = 0; yloop < after->height; yloop++) {
1057 for (xloop = 0; xloop < after->width; xloop++) {
1058 source = after->data + (xloop / 8) +
1059 (yloop * after->bytes_per_line);
1060 sourcebit = *source & (128 >> (xloop % 8));
1061 if (sourcebit)
1062 putchar('X');
1063 else
1064 putchar('.');
1065 }
1066 putchar('\n');
1067 }
1068 }
1069 #endif
1070
1071 xdest = x - (int) FontAscent(f);
1072 if (xdest < 0)
1073 xdest = 0;
1074 ydest = y - width;
1075
1076 XPutImage(display, rotpix, drawGC, after, 0, 0, 0, 0,
1077 after->width, after->height);
1078
1079 XSetFillStyle(display, gc, FillStippled);
1080 XSetStipple(display, gc, rotpix);
1081 XSetTSOrigin(display, gc, xdest, ydest);
1082 XFillRectangle(display, win, gc, xdest, ydest, after->width, after->height);
1083 XSetFillStyle(display, gc, FillSolid);
1084
1085 XFreeGC(display, drawGC);
1086 XDestroyImage(before);
1087 XDestroyImage(after);
1088 XFreePixmap(display, pix);
1089 XFreePixmap(display, rotpix);
1090
1091 /* Note that it appears that there is a memory leak here, but XDestroyImage
1092 * frees the image data that is XtCalloc'ed
1093 */
1094
1095 }
1096
1097 static char dots[] =
1098 {2, 1, 1};
1099 static char widedots[] =
1100 {2, 1, 4};
1101
1102 static GC
ItemGetGC(SciPlotWidget w,SciPlotItem * item)1103 ItemGetGC (SciPlotWidget w, SciPlotItem *item)
1104 {
1105 GC gc;
1106 short color;
1107
1108 switch (item->kind.any.style) {
1109 case XtLINE_SOLID:
1110 gc = w->plot.defaultGC;
1111 break;
1112 case XtLINE_DOTTED:
1113 XSetDashes(XtDisplay(w), w->plot.dashGC, 0, &dots[1],
1114 (int) dots[0]);
1115 gc = w->plot.dashGC;
1116 break;
1117 case XtLINE_WIDEDOT:
1118 XSetDashes(XtDisplay(w), w->plot.dashGC, 0, &widedots[1],
1119 (int) widedots[0]);
1120 gc = w->plot.dashGC;
1121 break;
1122 default:
1123 return NULL;
1124 break;
1125 }
1126 if (w->plot.Monochrome)
1127 if (item->kind.any.color > 0)
1128 color = w->plot.ForegroundColor;
1129 else
1130 color = w->plot.BackgroundColor;
1131 else if (item->kind.any.color >= w->plot.num_colors)
1132 color = w->plot.ForegroundColor;
1133 else if (item->kind.any.color <= 0)
1134 color = w->plot.BackgroundColor;
1135 else
1136 color = item->kind.any.color;
1137 XSetForeground(XtDisplay(w), gc, w->plot.colors[color]);
1138 return gc;
1139 }
1140
1141 static GC
ItemGetFontGC(SciPlotWidget w,SciPlotItem * item)1142 ItemGetFontGC (SciPlotWidget w, SciPlotItem *item)
1143 {
1144 GC gc;
1145 short color, fontnum;
1146
1147 gc = w->plot.dashGC;
1148 if (w->plot.Monochrome)
1149 if (item->kind.any.color > 0)
1150 color = w->plot.ForegroundColor;
1151 else
1152 color = w->plot.BackgroundColor;
1153 else if (item->kind.any.color >= w->plot.num_colors)
1154 color = w->plot.ForegroundColor;
1155 else if (item->kind.any.color <= 0)
1156 color = w->plot.BackgroundColor;
1157 else
1158 color = item->kind.any.color;
1159 XSetForeground(XtDisplay(w), gc, w->plot.colors[color]);
1160 if (item->kind.text.font >= w->plot.num_fonts)
1161 fontnum = 0;
1162 else
1163 fontnum = item->kind.text.font;
1164
1165 /*
1166 * fontnum==0 hack: 0 is supposed to be the default font, but the program
1167 * can't seem to get the default font ID from the GC for some reason. So,
1168 * use a different GC where the default font still exists.
1169 */
1170 XSetFont(XtDisplay(w), gc, w->plot.fonts[fontnum].font->fid);
1171 return gc;
1172 }
1173
1174 static void
ItemDraw(SciPlotWidget w,SciPlotItem * item)1175 ItemDraw (SciPlotWidget w, SciPlotItem *item)
1176 {
1177 XPoint point[8];
1178 XSegment seg;
1179 XRectangle rect;
1180 int i;
1181 GC gc;
1182
1183 if (!XtIsRealized((Widget) w))
1184 return;
1185 if ((item->type > SciPlotStartTextTypes) && (item->type < SciPlotEndTextTypes))
1186 gc = ItemGetFontGC(w, item);
1187 else
1188 gc = ItemGetGC(w, item);
1189 if (!gc)
1190 return;
1191 switch (item->type) {
1192 case SciPlotLine:
1193 seg.x1 = (short) item->kind.line.x1;
1194 seg.y1 = (short) item->kind.line.y1;
1195 seg.x2 = (short) item->kind.line.x2;
1196 seg.y2 = (short) item->kind.line.y2;
1197 XDrawSegments(XtDisplay(w), XtWindow(w), gc,
1198 &seg, 1);
1199 break;
1200 case SciPlotRect:
1201 XDrawRectangle(XtDisplay(w), XtWindow(w), gc,
1202 (int) (item->kind.rect.x),
1203 (int) (item->kind.rect.y),
1204 (unsigned int) (item->kind.rect.w),
1205 (unsigned int) (item->kind.rect.h));
1206 break;
1207 case SciPlotFRect:
1208 XFillRectangle(XtDisplay(w), XtWindow(w), gc,
1209 (int) (item->kind.rect.x),
1210 (int) (item->kind.rect.y),
1211 (unsigned int) (item->kind.rect.w),
1212 (unsigned int) (item->kind.rect.h));
1213 XDrawRectangle(XtDisplay(w), XtWindow(w), gc,
1214 (int) (item->kind.rect.x),
1215 (int) (item->kind.rect.y),
1216 (unsigned int) (item->kind.rect.w),
1217 (unsigned int) (item->kind.rect.h));
1218 break;
1219 case SciPlotPoly:
1220 i = 0;
1221 while (i < item->kind.poly.count) {
1222 point[i].x = (int) item->kind.poly.x[i];
1223 point[i].y = (int) item->kind.poly.y[i];
1224 i++;
1225 }
1226 point[i].x = (int) item->kind.poly.x[0];
1227 point[i].y = (int) item->kind.poly.y[0];
1228 XDrawLines(XtDisplay(w), XtWindow(w), gc,
1229 point, i + 1, CoordModeOrigin);
1230 break;
1231 case SciPlotFPoly:
1232 i = 0;
1233 while (i < item->kind.poly.count) {
1234 point[i].x = (int) item->kind.poly.x[i];
1235 point[i].y = (int) item->kind.poly.y[i];
1236 i++;
1237 }
1238 point[i].x = (int) item->kind.poly.x[0];
1239 point[i].y = (int) item->kind.poly.y[0];
1240 XFillPolygon(XtDisplay(w), XtWindow(w), gc,
1241 point, i + 1, Complex, CoordModeOrigin);
1242 XDrawLines(XtDisplay(w), XtWindow(w), gc,
1243 point, i + 1, CoordModeOrigin);
1244 break;
1245 case SciPlotCircle:
1246 XDrawArc(XtDisplay(w), XtWindow(w), gc,
1247 (int) (item->kind.circ.x - item->kind.circ.r),
1248 (int) (item->kind.circ.y - item->kind.circ.r),
1249 (unsigned int) (item->kind.circ.r * 2),
1250 (unsigned int) (item->kind.circ.r * 2),
1251 0 * 64, 360 * 64);
1252 break;
1253 case SciPlotFCircle:
1254 XFillArc(XtDisplay(w), XtWindow(w), gc,
1255 (int) (item->kind.circ.x - item->kind.circ.r),
1256 (int) (item->kind.circ.y - item->kind.circ.r),
1257 (unsigned int) (item->kind.circ.r * 2),
1258 (unsigned int) (item->kind.circ.r * 2),
1259 0 * 64, 360 * 64);
1260 break;
1261 case SciPlotText:
1262 XDrawString(XtDisplay(w), XtWindow(w), gc,
1263 (int) (item->kind.text.x), (int) (item->kind.text.y),
1264 item->kind.text.text,
1265 (int) item->kind.text.length);
1266 break;
1267 case SciPlotVText:
1268 XDrawVString(XtDisplay(w), XtWindow(w), gc,
1269 (int) (item->kind.text.x), (int) (item->kind.text.y),
1270 item->kind.text.text,
1271 (int) item->kind.text.length,
1272 FontFromFontnum(w, item->kind.text.font));
1273 break;
1274 case SciPlotClipRegion:
1275 rect.x = (short) item->kind.line.x1;
1276 rect.y = (short) item->kind.line.y1;
1277 rect.width = (short) item->kind.line.x2;
1278 rect.height = (short) item->kind.line.y2;
1279 XSetClipRectangles(XtDisplay(w), w->plot.dashGC, 0, 0, &rect, 1, Unsorted);
1280 XSetClipRectangles(XtDisplay(w), w->plot.defaultGC, 0, 0, &rect, 1, Unsorted);
1281 break;
1282 case SciPlotClipClear:
1283 XSetClipMask(XtDisplay(w), w->plot.dashGC, None);
1284 XSetClipMask(XtDisplay(w), w->plot.defaultGC, None);
1285 break;
1286 default:
1287 break;
1288 }
1289 }
1290
1291 static void
ItemDrawAll(SciPlotWidget w)1292 ItemDrawAll (SciPlotWidget w)
1293 {
1294 SciPlotItem *item;
1295 int i;
1296
1297 if (!XtIsRealized((Widget) w))
1298 return;
1299 item = w->plot.drawlist;
1300 i = 0;
1301 while (i < w->plot.num_drawlist) {
1302 ItemDraw(w, item);
1303 i++;
1304 item++;
1305 }
1306 }
1307
1308
1309
1310 /*
1311 * PostScript (r) functions ------------------------------------------------
1312 *
1313 */
1314 typedef struct {
1315 char *command;
1316 char *prolog;
1317 } PScommands;
1318
1319 static PScommands psc[] =
1320 {
1321 {"ma", "moveto"},
1322 {"da", "lineto stroke newpath"},
1323 {"la", "lineto"},
1324 {"poly", "closepath stroke newpath"},
1325 {"fpoly", "closepath fill newpath"},
1326 {"box", "1 index 0 rlineto 0 exch rlineto neg 0 rlineto closepath stroke newpath"},
1327 {"fbox", "1 index 0 rlineto 0 exch rlineto neg 0 rlineto closepath fill newpath"},
1328 {"clipbox", "gsave 1 index 0 rlineto 0 exch rlineto neg 0 rlineto closepath clip newpath"},
1329 {"unclip", "grestore newpath"},
1330 {"cr", "0 360 arc stroke newpath"},
1331 {"fcr", "0 360 arc fill newpath"},
1332 {"vma", "gsave moveto 90 rotate"},
1333 {"norm", "grestore"},
1334 {"solid", "[] 0 setdash"},
1335 {"dot", "[.25 2] 0 setdash"},
1336 {"widedot", "[.25 8] 0 setdash"},
1337 {"rgb", "setrgbcolor"},
1338 {NULL, NULL}
1339 };
1340
1341 enum PSenums {
1342 PSmoveto, PSlineto,
1343 PSpolyline, PSendpoly, PSendfill,
1344 PSbox, PSfbox,
1345 PSclipbox, PSunclip,
1346 PScircle, PSfcircle,
1347 PSvmoveto, PSnormal,
1348 PSsolid, PSdot, PSwidedot,
1349 PSrgb
1350 };
1351
1352 static void
ItemPSDrawAll(SciPlotWidget w,FILE * fd,double yflip,Boolean usecolor)1353 ItemPSDrawAll (SciPlotWidget w, FILE *fd, double yflip, Boolean usecolor)
1354 {
1355 int i, loopcount;
1356 SciPlotItem *item;
1357 XcmsColor currentcolor;
1358 int previousfont, previousline, currentfont, currentline, previouscolor;
1359
1360 item = w->plot.drawlist;
1361 loopcount = 0;
1362 previousfont = 0;
1363 previouscolor = -1;
1364 previousline = XtLINE_SOLID;
1365 while (loopcount < w->plot.num_drawlist) {
1366
1367 /* 2 switch blocks: 1st sets up defaults, 2nd actually draws things. */
1368 currentline = previousline;
1369 currentfont = previousfont;
1370 switch (item->type) {
1371 case SciPlotLine:
1372 case SciPlotCircle:
1373 currentline = item->kind.any.style;
1374 break;
1375 default:
1376 break;
1377 }
1378 if (currentline != XtLINE_NONE) {
1379 if (currentline != previousline) {
1380 switch (item->kind.any.style) {
1381 case XtLINE_SOLID:
1382 fprintf(fd, "%s ", psc[PSsolid].command);
1383 break;
1384 case XtLINE_DOTTED:
1385 fprintf(fd, "%s ", psc[PSdot].command);
1386 break;
1387 case XtLINE_WIDEDOT:
1388 fprintf(fd, "%s ", psc[PSwidedot].command);
1389 break;
1390 }
1391 previousline = currentline;
1392 }
1393
1394 if (usecolor && item->kind.any.color != previouscolor) {
1395
1396 /* Get Pixel index */
1397 currentcolor.pixel = w->plot.colors[item->kind.any.color];
1398 /* Get RGBi components [0.0,1.0] */
1399 XcmsQueryColor( XtDisplay(w), w->plot.cmap, ¤tcolor,
1400 XcmsRGBiFormat );
1401 /* output PostScript command */
1402 fprintf(fd, "%f %f %f %s ", currentcolor.spec.RGBi.red,
1403 currentcolor.spec.RGBi.green, currentcolor.spec.RGBi.blue,
1404 psc[PSrgb].command);
1405
1406 previouscolor=item->kind.any.color;
1407
1408 }
1409
1410 switch (item->type) {
1411 case SciPlotLine:
1412 fprintf(fd, "%.2f %.2f %s %.2f %.2f %s\n",
1413 item->kind.line.x1, yflip - item->kind.line.y1,
1414 psc[PSmoveto].command,
1415 item->kind.line.x2, yflip - item->kind.line.y2,
1416 psc[PSlineto].command);
1417 break;
1418 case SciPlotRect:
1419 fprintf(fd, "%.2f %.2f %s %.2f %.2f %s\n",
1420 item->kind.rect.x,
1421 yflip - item->kind.rect.y - (item->kind.rect.h - 1.0),
1422 psc[PSmoveto].command,
1423 item->kind.rect.w - 1.0, item->kind.rect.h - 1.0,
1424 psc[PSbox].command);
1425 break;
1426 case SciPlotFRect:
1427 fprintf(fd, "%.2f %.2f %s %.2f %.2f %s\n",
1428 item->kind.rect.x,
1429 yflip - item->kind.rect.y - (item->kind.rect.h - 1.0),
1430 psc[PSmoveto].command,
1431 item->kind.rect.w - 1.0, item->kind.rect.h - 1.0,
1432 psc[PSfbox].command);
1433 break;
1434 case SciPlotPoly:
1435 fprintf(fd, "%.2f %.2f %s ",
1436 item->kind.poly.x[0], yflip - item->kind.poly.y[0],
1437 psc[PSmoveto].command);
1438 for (i = 1; i < item->kind.poly.count; i++) {
1439 fprintf(fd, "%.2f %.2f %s ",
1440 item->kind.poly.x[i],
1441 yflip - item->kind.poly.y[i],
1442 psc[PSpolyline].command);
1443 }
1444 fprintf(fd, "%s\n", psc[PSendpoly].command);
1445 break;
1446 case SciPlotFPoly:
1447 fprintf(fd, "%.2f %.2f %s ",
1448 item->kind.poly.x[0], yflip - item->kind.poly.y[0],
1449 psc[PSmoveto].command);
1450 for (i = 1; i < item->kind.poly.count; i++) {
1451 fprintf(fd, "%.2f %.2f %s ",
1452 item->kind.poly.x[i],
1453 yflip - item->kind.poly.y[i],
1454 psc[PSpolyline].command);
1455 }
1456 fprintf(fd, "%s\n", psc[PSendfill].command);
1457 break;
1458 case SciPlotCircle:
1459 fprintf(fd, "%.2f %.2f %.2f %s\n",
1460 item->kind.circ.x, yflip - item->kind.circ.y,
1461 item->kind.circ.r,
1462 psc[PScircle].command);
1463 break;
1464 case SciPlotFCircle:
1465 fprintf(fd, "%.2f %.2f %.2f %s\n",
1466 item->kind.circ.x, yflip - item->kind.circ.y,
1467 item->kind.circ.r,
1468 psc[PSfcircle].command);
1469 break;
1470 case SciPlotText:
1471 fprintf(fd, "font-%d %.2f %.2f %s (%s) show\n",
1472 item->kind.text.font,
1473 item->kind.text.x, yflip - item->kind.text.y,
1474 psc[PSmoveto].command,
1475 item->kind.text.text);
1476 break;
1477 case SciPlotVText:
1478 fprintf(fd, "font-%d %.2f %.2f %s (%s) show %s\n",
1479 item->kind.text.font,
1480 item->kind.text.x, yflip - item->kind.text.y,
1481 psc[PSvmoveto].command,
1482 item->kind.text.text,
1483 psc[PSnormal].command);
1484 break;
1485 case SciPlotClipRegion:
1486 fprintf(fd, "%.2f %.2f %s %.2f %.2f %s\n",
1487 item->kind.line.x1,
1488 yflip - item->kind.line.y1 - item->kind.line.y2,
1489 psc[PSmoveto].command,
1490 item->kind.line.x2, item->kind.line.y2,
1491 psc[PSclipbox].command);
1492 break;
1493 case SciPlotClipClear:
1494 fprintf(fd, "%s\n", psc[PSunclip].command);
1495 break;
1496 default:
1497 break;
1498 }
1499 }
1500 loopcount++;
1501 item++;
1502 }
1503 }
1504
1505 Boolean
SciPlotPSCreateFancy(SciPlotWidget w,char * filename,int drawborder,char * titles,Boolean usecolor)1506 SciPlotPSCreateFancy (SciPlotWidget w, char *filename, int drawborder, char *titles, Boolean usecolor)
1507 {
1508 FILE *fd;
1509 float scale, xoff, yoff, xmax, ymax, yflip, aspect, border, titlefontsize;
1510 int i;
1511 PScommands *p;
1512 char fontname[128];
1513
1514 if (!(fd = fopen(filename, "w"))) {
1515 XtWarning("SciPlotPSCreate: Unable to open postscript file.");
1516 return False;
1517 }
1518 DrawAll(w);
1519
1520 aspect = (float) w->core.width / (float) w->core.height;
1521 border = 36.0;
1522 if (aspect > (612.0 / 792.0)) {
1523 scale = (612.0 - (2 * border)) / (float) w->core.width;
1524 xoff = border;
1525 yoff = (792.0 - (2 * border) - scale * (float) w->core.height) / 2.0;
1526 xmax = xoff + scale * (float) w->core.width;
1527 ymax = yoff + scale * (float) w->core.height;
1528 }
1529 else {
1530 scale = (792.0 - (2 * border)) / (float) w->core.height;
1531 yoff = border;
1532 xoff = (612.0 - (2 * border) - scale * (float) w->core.width) / 2.0;
1533 xmax = xoff + scale * (float) w->core.width;
1534 ymax = yoff + scale * (float) w->core.height;
1535 }
1536 yflip = w->core.height;
1537 fprintf(fd, "%s\n%s %.2f %s\n%s %f %f %f %f\n%s\n",
1538 "%!PS-ADOBE-3.0 EPSF-3.0",
1539 "%%Creator: SciPlot Widget",
1540 _SCIPLOT_WIDGET_VERSION,
1541 "Copyright (c) 1995 Robert W. McMullen",
1542 "%%BoundingBox:", xoff, yoff, xmax, ymax,
1543 "%%EndComments");
1544
1545 p = psc;
1546 while (p->command) {
1547 fprintf(fd, "/%s {%s} bind def\n", p->command, p->prolog);
1548 p++;
1549 }
1550
1551 for (i = 0; i < w->plot.num_fonts; i++) {
1552 FontnumPostScriptString(w, i, fontname);
1553 fprintf(fd, "/font-%d {%s setfont} bind def\n",
1554 i, fontname);
1555 }
1556 titlefontsize = 10.0;
1557 fprintf(fd, "/font-title {/%s findfont %f scalefont setfont} bind def\n",
1558 "Times-Roman", titlefontsize);
1559 fprintf(fd, "%f setlinewidth\n", 0.001);
1560 fprintf(fd, "newpath gsave\n%f %f translate %f %f scale\n",
1561 xoff, yoff, scale, scale);
1562
1563 ItemPSDrawAll(w, fd, yflip, usecolor);
1564
1565 fprintf(fd, "grestore\n");
1566
1567 if (drawborder) {
1568 fprintf(fd, "%.2f %.2f %s %.2f %.2f %s\n",
1569 border, border,
1570 psc[PSmoveto].command,
1571 612.0 - 2.0 * border, 792.0 - 2.0 * border,
1572 psc[PSbox].command);
1573 }
1574 if (titles) {
1575 char *ptr;
1576 char buf[256];
1577 int len, i, j;
1578 float x, y;
1579
1580 x = border + titlefontsize;
1581 y = 792.0 - border - (2.0 * titlefontsize);
1582 len = strlen(titles);
1583 ptr = titles;
1584 i = 0;
1585 while (i < len) {
1586 j = 0;
1587 while ((*ptr != '\n') && (i < len)) {
1588 if ((*ptr == '(') || (*ptr == ')'))
1589 buf[j++] = '\\';
1590 buf[j++] = *ptr;
1591 ptr++;
1592 i++;
1593 }
1594 buf[j] = '\0';
1595 ptr++;
1596 i++;
1597 fprintf(fd, "font-title %.2f %.2f %s (%s) show\n",
1598 x, y, psc[PSmoveto].command, buf);
1599 y -= titlefontsize * 1.5;
1600 }
1601 if (border) {
1602 y += titlefontsize * 0.5;
1603 fprintf(fd, "%.2f %.2f %s %.2f %.2f %s\n",
1604 border, y,
1605 psc[PSmoveto].command,
1606 612.0 - border, y,
1607 psc[PSlineto].command);
1608 }
1609 }
1610
1611 fprintf(fd, "showpage\n");
1612 fclose(fd);
1613 return True;
1614 }
1615
1616 Boolean
SciPlotPSCreate(Widget wi,char * filename)1617 SciPlotPSCreate (Widget wi, char *filename)
1618 {
1619 SciPlotWidget w;
1620
1621 if (!XtIsSciPlot(wi)) {
1622 XtWarning("SciPlotPSCreate: Not a SciPlot widget.");
1623 return False;
1624 }
1625
1626 w = (SciPlotWidget) wi;
1627 return SciPlotPSCreateFancy(w, filename, False, NULL, False);
1628 }
1629
1630 Boolean
SciPlotPSCreateColor(Widget wi,char * filename)1631 SciPlotPSCreateColor (Widget wi, char *filename)
1632 {
1633 SciPlotWidget w;
1634
1635 if (!XtIsSciPlot(wi)) {
1636 XtWarning("SciPlotPSCreate: Not a SciPlot widget.");
1637 return False;
1638 }
1639
1640 w = (SciPlotWidget) wi;
1641 return SciPlotPSCreateFancy(w, filename, False, NULL, True);
1642 }
1643
1644
1645 /*
1646 * Private device independent drawing functions
1647 */
1648
1649 static void
EraseClassItems(SciPlotWidget w,SciPlotDrawingEnum drawing)1650 EraseClassItems (SciPlotWidget w, SciPlotDrawingEnum drawing)
1651 {
1652 SciPlotItem *item;
1653 int i;
1654
1655 if (!XtIsRealized((Widget) w))
1656 return;
1657 item = w->plot.drawlist;
1658 i = 0;
1659 while (i < w->plot.num_drawlist) {
1660 if (item->drawing_class == drawing) {
1661 item->kind.any.color = 0;
1662 item->kind.any.style = XtLINE_SOLID;
1663 ItemDraw(w, item);
1664 }
1665 i++;
1666 item++;
1667 }
1668 }
1669
1670 static void
EraseAllItems(SciPlotWidget w)1671 EraseAllItems (SciPlotWidget w)
1672 {
1673 SciPlotItem *item;
1674 int i;
1675
1676 item = w->plot.drawlist;
1677 i = 0;
1678 while (i < w->plot.num_drawlist) {
1679 if ((item->type > SciPlotStartTextTypes) &&
1680 (item->type < SciPlotEndTextTypes))
1681 XtFree(item->kind.text.text);
1682 i++;
1683 item++;
1684 }
1685 w->plot.num_drawlist = 0;
1686 }
1687
1688 static void
EraseAll(SciPlotWidget w)1689 EraseAll (SciPlotWidget w)
1690 {
1691 EraseAllItems(w);
1692 if (XtIsRealized((Widget) w))
1693 XClearWindow(XtDisplay(w), XtWindow(w));
1694 }
1695
1696 static SciPlotItem *
ItemGetNew(SciPlotWidget w)1697 ItemGetNew (SciPlotWidget w)
1698 {
1699 SciPlotItem *item;
1700
1701 w->plot.num_drawlist++;
1702 if (w->plot.num_drawlist >= w->plot.alloc_drawlist) {
1703 w->plot.alloc_drawlist += NUMPLOTITEMEXTRA;
1704 w->plot.drawlist = (SciPlotItem *) XtRealloc((char *) w->plot.drawlist,
1705 w->plot.alloc_drawlist * sizeof(SciPlotItem));
1706 if (!w->plot.drawlist) {
1707 printf("Can't realloc memory for SciPlotItem list\n");
1708 exit(1);
1709 }
1710 #ifdef DEBUG_SCIPLOT
1711 printf("Alloced #%d for drawlist\n", w->plot.alloc_drawlist);
1712 #endif
1713 }
1714 item = w->plot.drawlist + (w->plot.num_drawlist - 1);
1715 item->type = SciPlotFALSE;
1716 item->drawing_class = w->plot.current_id;
1717 return item;
1718 }
1719
1720
1721 static void
LineSet(SciPlotWidget w,real x1,real y1,real x2,real y2,int color,int style)1722 LineSet(SciPlotWidget w, real x1, real y1, real x2, real y2,
1723 int color, int style)
1724 {
1725 SciPlotItem *item;
1726
1727 item = ItemGetNew(w);
1728 item->kind.any.color = (short) color;
1729 item->kind.any.style = (short) style;
1730 item->kind.line.x1 = (real) x1;
1731 item->kind.line.y1 = (real) y1;
1732 item->kind.line.x2 = (real) x2;
1733 item->kind.line.y2 = (real) y2;
1734 item->type = SciPlotLine;
1735 ItemDraw(w, item);
1736 }
1737
1738 static void
RectSet(SciPlotWidget w,real x1,real y1,real x2,real y2,int color,int style)1739 RectSet(SciPlotWidget w, real x1, real y1, real x2, real y2,
1740 int color, int style)
1741 {
1742 SciPlotItem *item;
1743 real x, y, width, height;
1744
1745 if (x1 < x2)
1746 x = x1, width = (x2 - x1 + 1);
1747 else
1748 x = x2, width = (x1 - x2 + 1);
1749 if (y1 < y2)
1750 y = y1, height = (y2 - y1 + 1);
1751 else
1752 y = y2, height = (y1 - y2 + 1);
1753
1754 item = ItemGetNew(w);
1755 item->kind.any.color = (short) color;
1756 item->kind.any.style = (short) style;
1757 item->kind.rect.x = (real) x;
1758 item->kind.rect.y = (real) y;
1759 item->kind.rect.w = (real) width;
1760 item->kind.rect.h = (real) height;
1761 item->type = SciPlotRect;
1762 ItemDraw(w, item);
1763 }
1764
1765 static void
FilledRectSet(SciPlotWidget w,real x1,real y1,real x2,real y2,int color,int style)1766 FilledRectSet (SciPlotWidget w, real x1, real y1, real x2, real y2, int color, int style)
1767 {
1768 SciPlotItem *item;
1769 real x, y, width, height;
1770
1771 if (x1 < x2)
1772 x = x1, width = (x2 - x1 + 1);
1773 else
1774 x = x2, width = (x1 - x2 + 1);
1775 if (y1 < y2)
1776 y = y1, height = (y2 - y1 + 1);
1777 else
1778 y = y2, height = (y1 - y2 + 1);
1779
1780 item = ItemGetNew(w);
1781 item->kind.any.color = (short) color;
1782 item->kind.any.style = (short) style;
1783 item->kind.rect.x = (real) x;
1784 item->kind.rect.y = (real) y;
1785 item->kind.rect.w = (real) width;
1786 item->kind.rect.h = (real) height;
1787 item->type = SciPlotFRect;
1788 ItemDraw(w, item);
1789 }
1790
1791 static void
TriSet(SciPlotWidget w,real x1,real y1,real x2,real y2,real x3,real y3,int color,int style)1792 TriSet (SciPlotWidget w, real x1, real y1, real x2, real y2, real x3, real y3, int color, int style)
1793 {
1794 SciPlotItem *item;
1795
1796 item = ItemGetNew(w);
1797 item->kind.any.color = (short) color;
1798 item->kind.any.style = (short) style;
1799 item->kind.poly.count = 3;
1800 item->kind.poly.x[0] = (real) x1;
1801 item->kind.poly.y[0] = (real) y1;
1802 item->kind.poly.x[1] = (real) x2;
1803 item->kind.poly.y[1] = (real) y2;
1804 item->kind.poly.x[2] = (real) x3;
1805 item->kind.poly.y[2] = (real) y3;
1806 item->type = SciPlotPoly;
1807 ItemDraw(w, item);
1808 }
1809
1810 static void
FilledTriSet(SciPlotWidget w,real x1,real y1,real x2,real y2,real x3,real y3,int color,int style)1811 FilledTriSet (SciPlotWidget w, real x1, real y1, real x2, real y2, real x3, real y3, int color, int style)
1812 {
1813 SciPlotItem *item;
1814
1815 item = ItemGetNew(w);
1816 item->kind.any.color = (short) color;
1817 item->kind.any.style = (short) style;
1818 item->kind.poly.count = 3;
1819 item->kind.poly.x[0] = (real) x1;
1820 item->kind.poly.y[0] = (real) y1;
1821 item->kind.poly.x[1] = (real) x2;
1822 item->kind.poly.y[1] = (real) y2;
1823 item->kind.poly.x[2] = (real) x3;
1824 item->kind.poly.y[2] = (real) y3;
1825 item->type = SciPlotFPoly;
1826 ItemDraw(w, item);
1827 }
1828
1829 static void
QuadSet(SciPlotWidget w,real x1,real y1,real x2,real y2,real x3,real y3,real x4,real y4,int color,int style)1830 QuadSet (SciPlotWidget w, real x1, real y1, real x2, real y2, real x3, real y3, real x4, real y4, int color, int style)
1831 {
1832 SciPlotItem *item;
1833
1834 item = ItemGetNew(w);
1835 item->kind.any.color = (short) color;
1836 item->kind.any.style = (short) style;
1837 item->kind.poly.count = 4;
1838 item->kind.poly.x[0] = (real) x1;
1839 item->kind.poly.y[0] = (real) y1;
1840 item->kind.poly.x[1] = (real) x2;
1841 item->kind.poly.y[1] = (real) y2;
1842 item->kind.poly.x[2] = (real) x3;
1843 item->kind.poly.y[2] = (real) y3;
1844 item->kind.poly.x[3] = (real) x4;
1845 item->kind.poly.y[3] = (real) y4;
1846 item->type = SciPlotPoly;
1847 ItemDraw(w, item);
1848 }
1849
1850 static void
FilledQuadSet(SciPlotWidget w,real x1,real y1,real x2,real y2,real x3,real y3,real x4,real y4,int color,int style)1851 FilledQuadSet (SciPlotWidget w, real x1, real y1, real x2, real y2, real x3, real y3, real x4, real y4, int color, int style)
1852 {
1853 SciPlotItem *item;
1854
1855 item = ItemGetNew(w);
1856 item->kind.any.color = (short) color;
1857 item->kind.any.style = (short) style;
1858 item->kind.poly.count = 4;
1859 item->kind.poly.x[0] = (real) x1;
1860 item->kind.poly.y[0] = (real) y1;
1861 item->kind.poly.x[1] = (real) x2;
1862 item->kind.poly.y[1] = (real) y2;
1863 item->kind.poly.x[2] = (real) x3;
1864 item->kind.poly.y[2] = (real) y3;
1865 item->kind.poly.x[3] = (real) x4;
1866 item->kind.poly.y[3] = (real) y4;
1867 item->type = SciPlotFPoly;
1868 ItemDraw(w, item);
1869 }
1870
1871 static void
CircleSet(SciPlotWidget w,real x,real y,real r,int color,int style)1872 CircleSet (SciPlotWidget w, real x, real y, real r, int color, int style)
1873 {
1874 SciPlotItem *item;
1875
1876 item = ItemGetNew(w);
1877 item->kind.any.color = (short) color;
1878 item->kind.any.style = (short) style;
1879 item->kind.circ.x = (real) x;
1880 item->kind.circ.y = (real) y;
1881 item->kind.circ.r = (real) r;
1882 item->type = SciPlotCircle;
1883 ItemDraw(w, item);
1884 }
1885
1886 static void
FilledCircleSet(SciPlotWidget w,real x,real y,real r,int color,int style)1887 FilledCircleSet (SciPlotWidget w, real x, real y, real r, int color, int style)
1888 {
1889 SciPlotItem *item;
1890
1891 item = ItemGetNew(w);
1892 item->kind.any.color = (short) color;
1893 item->kind.any.style = (short) style;
1894 item->kind.circ.x = (real) x;
1895 item->kind.circ.y = (real) y;
1896 item->kind.circ.r = (real) r;
1897 item->type = SciPlotFCircle;
1898 ItemDraw(w, item);
1899 }
1900
1901 static void
TextSet(SciPlotWidget w,real x,real y,char * text,int color,int font)1902 TextSet (SciPlotWidget w, real x, real y, char *text, int color, int font)
1903 {
1904 SciPlotItem *item;
1905
1906 item = ItemGetNew(w);
1907 item->kind.any.color = (short) color;
1908 item->kind.any.style = 0;
1909 item->kind.text.x = (real) x;
1910 item->kind.text.y = (real) y;
1911 item->kind.text.length = strlen(text);
1912 item->kind.text.text = XtMalloc((int) item->kind.text.length + 1);
1913 item->kind.text.font = font;
1914 strcpy(item->kind.text.text, text);
1915 item->type = SciPlotText;
1916 ItemDraw(w, item);
1917 #ifdef DEBUG_SCIPLOT_TEXT
1918 if (1) {
1919 real x1, y1;
1920
1921 y -= FontnumAscent(w, font);
1922 y1 = y + FontnumHeight(w, font) - 1.0;
1923 x1 = x + FontnumTextWidth(w, font, text) - 1.0;
1924 RectSet(w, x, y, x1, y1, color, XtLINE_SOLID);
1925 }
1926 #endif
1927 }
1928
1929 static void
TextCenter(SciPlotWidget w,real x,real y,char * text,int color,int font)1930 TextCenter (SciPlotWidget w, real x, real y, char *text, int color, int font)
1931 {
1932 x -= FontnumTextWidth(w, font, text) / 2.0;
1933 y += FontnumHeight(w, font) / 2.0 - FontnumDescent(w, font);
1934 TextSet(w, x, y, text, color, font);
1935 }
1936
1937 static void
VTextSet(SciPlotWidget w,real x,real y,char * text,int color,int font)1938 VTextSet (SciPlotWidget w, real x, real y, char *text, int color, int font)
1939 {
1940 SciPlotItem *item;
1941
1942 item = ItemGetNew(w);
1943 item->kind.any.color = (short) color;
1944 item->kind.any.style = 0;
1945 item->kind.text.x = (real) x;
1946 item->kind.text.y = (real) y;
1947 item->kind.text.length = strlen(text);
1948 item->kind.text.text = XtMalloc((int) item->kind.text.length + 1);
1949 item->kind.text.font = font;
1950 strcpy(item->kind.text.text, text);
1951 item->type = SciPlotVText;
1952 ItemDraw(w, item);
1953 #ifdef DEBUG_SCIPLOT_TEXT
1954 if (1) {
1955 real x1, y1;
1956
1957 x += FontnumDescent(w, font);
1958 x1 = x - FontnumHeight(w, font) - 1.0;
1959 y1 = y - FontnumTextWidth(w, font, text) - 1.0;
1960 RectSet(w, x, y, x1, y1, color, XtLINE_SOLID);
1961 }
1962 #endif
1963 }
1964
1965 static void
VTextCenter(SciPlotWidget w,real x,real y,char * text,int color,int font)1966 VTextCenter (SciPlotWidget w, real x, real y, char *text, int color, int font)
1967 {
1968 x += FontnumHeight(w, font) / 2.0 - FontnumDescent(w, font);
1969 y += FontnumTextWidth(w, font, text) / 2.0;
1970 VTextSet(w, x, y, text, color, font);
1971 }
1972
1973 static void
ClipSet(SciPlotWidget w)1974 ClipSet (SciPlotWidget w)
1975 {
1976 SciPlotItem *item;
1977
1978 if (w->plot.ChartType == XtCARTESIAN) {
1979 item = ItemGetNew(w);
1980 item->kind.any.style = XtLINE_SOLID;
1981 item->kind.any.color = 1;
1982 item->kind.line.x1 = w->plot.x.Origin;
1983 item->kind.line.x2 = w->plot.x.Size;
1984 item->kind.line.y1 = w->plot.y.Origin;
1985 item->kind.line.y2 = w->plot.y.Size;
1986 #ifdef DEBUG_SCIPLOT
1987 printf("clipping region: x=%f y=%f w=%f h=%f\n",
1988 item->kind.line.x1,
1989 item->kind.line.y1,
1990 item->kind.line.x2,
1991 item->kind.line.y2
1992 );
1993 #endif
1994 item->type = SciPlotClipRegion;
1995 ItemDraw(w, item);
1996 }
1997 }
1998
1999 static void
ClipClear(SciPlotWidget w)2000 ClipClear (SciPlotWidget w)
2001 {
2002 SciPlotItem *item;
2003
2004 if (w->plot.ChartType == XtCARTESIAN) {
2005 item = ItemGetNew(w);
2006 item->kind.any.style = XtLINE_SOLID;
2007 item->kind.any.color = 1;
2008 item->type = SciPlotClipClear;
2009 ItemDraw(w, item);
2010 }
2011 }
2012
2013
2014 /*
2015 * Private data point to screen location converters
2016 */
2017
2018 static real
PlotX(SciPlotWidget w,real xin)2019 PlotX (SciPlotWidget w, real xin)
2020 {
2021 real xout;
2022
2023 if (w->plot.XLog)
2024 xout = w->plot.x.Origin +
2025 ((log10(xin) - log10(w->plot.x.DrawOrigin)) *
2026 (w->plot.x.Size / w->plot.x.DrawSize));
2027 else
2028 xout = w->plot.x.Origin +
2029 ((xin - w->plot.x.DrawOrigin) *
2030 (w->plot.x.Size / w->plot.x.DrawSize));
2031 return xout;
2032 }
2033
2034 static real
PlotY(SciPlotWidget w,real yin)2035 PlotY (SciPlotWidget w, real yin)
2036 {
2037 real yout;
2038
2039 if (w->plot.YLog)
2040 yout = w->plot.y.Origin + w->plot.y.Size -
2041 ((log10(yin) - log10(w->plot.y.DrawOrigin)) *
2042 (w->plot.y.Size / w->plot.y.DrawSize));
2043 else
2044 yout = w->plot.y.Origin + w->plot.y.Size -
2045 ((yin - w->plot.y.DrawOrigin) *
2046 (w->plot.y.Size / w->plot.y.DrawSize));
2047 return yout;
2048 }
2049
2050 static void
PlotRTRadians(SciPlotWidget w,real r,real t,real * xout,real * yout)2051 PlotRTRadians (SciPlotWidget w, real r, real t, real *xout, real *yout)
2052 {
2053 *xout = w->plot.x.Center + (r * (real) cos(t) /
2054 w->plot.PolarScale * w->plot.x.Size / 2.0);
2055 *yout = w->plot.y.Center + (-r * (real) sin(t) /
2056 w->plot.PolarScale * w->plot.x.Size / 2.0);
2057 }
2058
2059 static void
PlotRTDegrees(SciPlotWidget w,real r,real t,real * xout,real * yout)2060 PlotRTDegrees (SciPlotWidget w, real r, real t, real *xout, real *yout)
2061 {
2062 t *= DEG2RAD;
2063 PlotRTRadians(w, r, t, xout, yout);
2064 }
2065
2066 static void
PlotRT(SciPlotWidget w,real r,real t,real * xout,real * yout)2067 PlotRT (SciPlotWidget w, real r, real t, real *xout, real *yout)
2068 {
2069 if (w->plot.Degrees)
2070 t *= DEG2RAD;
2071 PlotRTRadians(w, r, t, xout, yout);
2072 }
2073
2074
2075 /*
2076 * Private calculation utilities for axes
2077 */
2078
2079 #define NUMBER_MINOR 8
2080 #define MAX_MAJOR 8
2081 static float CAdeltas[8] =
2082 {0.1, 0.2, 0.25, 0.5, 1.0, 2.0, 2.5, 5.0};
2083 static int CAdecimals[8] =
2084 {0, 0, 1, 0, 0, 0, 1, 0};
2085 static int CAminors[8] =
2086 {4, 4, 4, 5, 4, 4, 4, 5};
2087
2088 static void
ComputeAxis(SciPlotAxis * axis,real min,real max,Boolean log)2089 ComputeAxis (SciPlotAxis *axis, real min, real max, Boolean log)
2090 {
2091 real range, rnorm, delta, calcmin, calcmax;
2092 int nexp, majornum, minornum, majordecimals, decimals, i;
2093
2094 range = max - min;
2095 if (log) {
2096 if (range==0.0) {
2097 calcmin = powi(10.0, (int) floor(log10(min)));
2098 calcmax = 10.0*calcmin;
2099 }
2100 else {
2101 calcmin = powi(10.0, (int) floor(log10(min)));
2102 calcmax = powi(10.0, (int) ceil(log10(max)));
2103 }
2104
2105 /* printf("calcmin=%e min=%e calcmax=%e max=%e\n",calcmin,min, */
2106 /* calcmax,max); */
2107
2108 delta = 10.0;
2109
2110 axis->DrawOrigin = calcmin;
2111 axis->DrawMax = calcmax;
2112 axis->DrawSize = log10(calcmax) - log10(calcmin);
2113 axis->MajorInc = delta;
2114 axis->MajorNum = (int) (log10(calcmax) - log10(calcmin)) + 1;
2115 axis->MinorNum = 10;
2116 axis->Precision = -(int) (log10(calcmin) * 1.0001);
2117 #ifdef DEBUG_SCIPLOT
2118 printf("calcmin=%e log=%e (int)log=%d Precision=%d\n",
2119 calcmin, log10(calcmin), (int) (log10(calcmin) * 1.0001), axis->Precision);
2120 #endif
2121 if (axis->Precision < 0)
2122 axis->Precision = 0;
2123 }
2124 else {
2125 if (range==0.0) nexp=0;
2126 else nexp = (int) floor(log10(range));
2127 rnorm = range / powi(10.0, nexp);
2128 for (i = 0; i < NUMBER_MINOR; i++) {
2129 delta = CAdeltas[i];
2130 minornum = CAminors[i];
2131 majornum = (int) ((rnorm + 0.9999 * delta) / delta);
2132 majordecimals = CAdecimals[i];
2133 if (majornum <= MAX_MAJOR)
2134 break;
2135 }
2136 delta *= powi(10.0, nexp);
2137 #ifdef DEBUG_SCIPLOT
2138 printf("nexp=%d range=%f rnorm=%f delta=%f\n", nexp, range, rnorm, delta);
2139 #endif
2140
2141 if (min < 0.0)
2142 calcmin = ((float) ((int) ((min - .9999 * delta) / delta))) * delta;
2143 else if ((min > 0.0) && (min < 1.0))
2144 calcmin = ((float) ((int) ((1.0001 * min) / delta))) * delta;
2145 else if (min >= 1.0)
2146 calcmin = ((float) ((int) ((.9999 * min) / delta))) * delta;
2147 else
2148 calcmin = min;
2149 if (max < 0.0)
2150 calcmax = ((float) ((int) ((.9999 * max) / delta))) * delta;
2151 else if (max > 0.0)
2152 calcmax = ((float) ((int) ((max + .9999 * delta) / delta))) * delta;
2153 else
2154 calcmax = max;
2155
2156 axis->DrawOrigin = calcmin;
2157 axis->DrawMax = calcmax;
2158 axis->DrawSize = calcmax - calcmin;
2159 axis->MajorInc = delta;
2160 axis->MajorNum = majornum;
2161 axis->MinorNum = minornum;
2162
2163 delta = log10(axis->MajorInc);
2164 if (delta > 0.0)
2165 decimals = -(int) floor(delta) + majordecimals;
2166 else
2167 decimals = (int) ceil(-delta) + majordecimals;
2168 if (decimals < 0)
2169 decimals = 0;
2170 #ifdef DEBUG_SCIPLOT
2171 printf("delta=%f majordecimals=%d decimals=%d\n",
2172 delta, majordecimals, decimals);
2173 #endif
2174 axis->Precision = decimals;
2175 }
2176
2177 #ifdef DEBUG_SCIPLOT
2178 printf("Tics: min=%f max=%f size=%f major inc=%f #major=%d #minor=%d decimals=%d\n",
2179 axis->DrawOrigin, axis->DrawMax, axis->DrawSize,
2180 axis->MajorInc, axis->MajorNum, axis->MinorNum, axis->Precision);
2181 #endif
2182 }
2183
2184 static void
ComputeDrawingRange(SciPlotWidget w)2185 ComputeDrawingRange (SciPlotWidget w)
2186 {
2187 if (w->plot.ChartType == XtCARTESIAN) {
2188 ComputeAxis(&w->plot.x, w->plot.Min.x, w->plot.Max.x,
2189 w->plot.XLog);
2190 ComputeAxis(&w->plot.y, w->plot.Min.y, w->plot.Max.y,
2191 w->plot.YLog);
2192 }
2193 else {
2194 ComputeAxis(&w->plot.x, (real) 0.0, w->plot.Max.x,
2195 (Boolean) FALSE);
2196 w->plot.PolarScale = w->plot.x.DrawMax;
2197 }
2198 }
2199
2200 static Boolean
CheckMinMax(SciPlotWidget w)2201 CheckMinMax (SciPlotWidget w)
2202 {
2203 register int i, j;
2204 register SciPlotList *p;
2205 register real val;
2206
2207 if (w->plot.ChartType == XtCARTESIAN) {
2208 for (i = 0; i < w->plot.num_plotlist; i++) {
2209 p = w->plot.plotlist + i;
2210 if (p->draw) {
2211 for (j = 0; j < p->number; j++) {
2212
2213 /* Don't count the "break in line segment" flag for Min/Max */
2214 if (p->data[j].x > SCIPLOT_SKIP_VAL &&
2215 p->data[j].y > SCIPLOT_SKIP_VAL) {
2216
2217 val = p->data[j].x;
2218 if (val > w->plot.x.DrawMax || val < w->plot.x.DrawOrigin)
2219 return True;
2220 val = p->data[j].y;
2221 if (val > w->plot.y.DrawMax || val < w->plot.y.DrawOrigin)
2222 return True;
2223 }
2224 }
2225 }
2226 }
2227 }
2228 else {
2229 for (i = 0; i < w->plot.num_plotlist; i++) {
2230 p = w->plot.plotlist + i;
2231 if (p->draw) {
2232 for (j = 0; j < p->number; j++) {
2233 val = p->data[j].x;
2234 if (val > w->plot.Max.x || val < w->plot.Min.x)
2235 return True;
2236 }
2237 }
2238 }
2239 }
2240 return False;
2241 }
2242
2243 static void
ComputeMinMax(SciPlotWidget w)2244 ComputeMinMax (SciPlotWidget w)
2245 {
2246 register int i, j;
2247 register SciPlotList *p;
2248 register real val;
2249 Boolean firstx, firsty;
2250
2251 w->plot.Min.x = w->plot.Min.y = w->plot.Max.x = w->plot.Max.y = 1.0;
2252 firstx = True;
2253 firsty = True;
2254
2255 for (i = 0; i < w->plot.num_plotlist; i++) {
2256 p = w->plot.plotlist + i;
2257 if (p->draw) {
2258 for (j = 0; j < p->number; j++) {
2259
2260 /* Don't count the "break in line segment" flag for Min/Max */
2261 if (p->data[j].x > SCIPLOT_SKIP_VAL &&
2262 p->data[j].y > SCIPLOT_SKIP_VAL) {
2263
2264 val = p->data[j].x;
2265 if (!w->plot.XLog || (w->plot.XLog && (val > 0.0))) {
2266 if (firstx) {
2267 w->plot.Min.x = w->plot.Max.x = val;
2268 firstx = False;
2269 }
2270 else {
2271 if (val > w->plot.Max.x)
2272 w->plot.Max.x = val;
2273 else if (val < w->plot.Min.x)
2274 w->plot.Min.x = val;
2275 }
2276 }
2277
2278 val = p->data[j].y;
2279 if (!w->plot.YLog || (w->plot.YLog && (val > 0.0))) {
2280 if (firsty) {
2281 w->plot.Min.y = w->plot.Max.y = val;
2282 firsty = False;
2283 }
2284 else {
2285 if (val > w->plot.Max.y)
2286 w->plot.Max.y = val;
2287 else if (val < w->plot.Min.y)
2288 w->plot.Min.y = val;
2289 }
2290 }
2291 }
2292
2293 }
2294 }
2295 }
2296
2297 /* fix defaults if there is only one point. */
2298 if (firstx) {
2299 if (w->plot.XLog) {
2300 w->plot.Min.x = 1.0;
2301 w->plot.Max.x = 10.0;
2302 }
2303 else {
2304 w->plot.Min.x = 0.0;
2305 w->plot.Max.x = 10.0;
2306 }
2307 }
2308 if (firsty) {
2309 if (w->plot.YLog) {
2310 w->plot.Min.y = 1.0;
2311 w->plot.Max.y = 10.0;
2312 }
2313 else {
2314 w->plot.Min.y = 0.0;
2315 w->plot.Max.y = 10.0;
2316 }
2317 }
2318 if (w->plot.ChartType == XtCARTESIAN) {
2319 if (!w->plot.XLog) {
2320 if (!w->plot.XAutoScale) {
2321 w->plot.Min.x = w->plot.UserMin.x;
2322 w->plot.Max.x = w->plot.UserMax.x;
2323 }
2324 else if (w->plot.XOrigin) {
2325 if (w->plot.Min.x > 0.0)
2326 w->plot.Min.x = 0.0;
2327 if (w->plot.Max.x < 0.0)
2328 w->plot.Max.x = 0.0;
2329 }
2330 if (fabs(w->plot.Min.x - w->plot.Max.x) < 1.e-10) {
2331 w->plot.Min.x -= .5;
2332 w->plot.Max.x += .5;
2333 }
2334 }
2335 if (!w->plot.YLog) {
2336 if (!w->plot.YAutoScale) {
2337 w->plot.Min.y = w->plot.UserMin.y;
2338 w->plot.Max.y = w->plot.UserMax.y;
2339 }
2340 else if (w->plot.YOrigin) {
2341 if (w->plot.Min.y > 0.0)
2342 w->plot.Min.y = 0.0;
2343 if (w->plot.Max.y < 0.0)
2344 w->plot.Max.y = 0.0;
2345 }
2346 if (fabs(w->plot.Min.y - w->plot.Max.y) < 1.e-10) {
2347 w->plot.Min.y -= .5;
2348 w->plot.Max.y += .5;
2349 }
2350 }
2351 }
2352 else {
2353 if (fabs(w->plot.Min.x) > fabs(w->plot.Max.x))
2354 w->plot.Max.x = fabs(w->plot.Min.x);
2355 }
2356
2357 #ifdef DEBUG_SCIPLOT
2358 printf("Min: (%f,%f)\tMax: (%f,%f)\n",
2359 w->plot.Min.x, w->plot.Min.y,
2360 w->plot.Max.x, w->plot.Max.y);
2361 #endif
2362 }
2363
2364 static void
ComputeLegendDimensions(SciPlotWidget w)2365 ComputeLegendDimensions (SciPlotWidget w)
2366 {
2367 real current, xmax, ymax;
2368 int i;
2369 SciPlotList *p;
2370
2371 if (w->plot.ShowLegend) {
2372 xmax = 0.0;
2373 ymax = 2.0 * (real) w->plot.LegendMargin;
2374
2375 for (i = 0; i < w->plot.num_plotlist; i++) {
2376 p = w->plot.plotlist + i;
2377 if (p->draw) {
2378 current = (real) w->plot.Margin +
2379 (real) w->plot.LegendMargin * 3.0 +
2380 (real) w->plot.LegendLineSize +
2381 FontnumTextWidth(w, w->plot.axisFont, p->legend);
2382 if (current > xmax)
2383 xmax = current;
2384 ymax += FontnumHeight(w, w->plot.axisFont);
2385 }
2386 }
2387
2388 w->plot.x.LegendSize = xmax;
2389 w->plot.x.LegendPos = (real) w->plot.Margin;
2390 w->plot.y.LegendSize = ymax;
2391 w->plot.y.LegendPos = 0.0;
2392 }
2393 else {
2394 w->plot.x.LegendSize =
2395 w->plot.x.LegendPos =
2396 w->plot.y.LegendSize =
2397 w->plot.y.LegendPos = 0.0;
2398 }
2399 }
2400
2401 static void
ComputeDimensions(SciPlotWidget w)2402 ComputeDimensions (SciPlotWidget w)
2403 {
2404 real x, y, width, height, axisnumbersize, axisXlabelsize, axisYlabelsize;
2405
2406 /* x,y is the origin of the upper left corner of the drawing area inside
2407 * the widget. Doesn't necessarily have to be (Margin,Margin) as it is now.
2408 */
2409 x = (real) w->plot.Margin;
2410 y = (real) w->plot.Margin;
2411
2412 /* width = (real)w->core.width - (real)w->plot.Margin - x -
2413 * ** legendwidth - AxisFontHeight
2414 */
2415 width = (real) w->core.width - (real) w->plot.Margin - x -
2416 w->plot.x.LegendSize;
2417
2418 /* height = (real)w->core.height - (real)w->plot.Margin - y
2419 * - Height of axis numbers (including margin)
2420 * - Height of axis label (including margin)
2421 * - Height of Title (including margin)
2422 */
2423 height = (real) w->core.height - (real) w->plot.Margin - y;
2424
2425 w->plot.x.Origin = x;
2426 w->plot.y.Origin = y;
2427
2428 /* Adjust the size depending upon what sorts of text are visible. */
2429 if (w->plot.ShowTitle)
2430 height -= (real) w->plot.TitleMargin +
2431 FontnumHeight(w, w->plot.titleFont);
2432
2433 if (w->plot.ChartType == XtCARTESIAN) {
2434 axisnumbersize = (real) w->plot.Margin +
2435 FontnumHeight(w, w->plot.axisFont);
2436 if (w->plot.XAxisNumbers) {
2437 height -= axisnumbersize;
2438 }
2439 if (w->plot.YAxisNumbers) {
2440 width -= axisnumbersize;
2441 w->plot.x.Origin += axisnumbersize;
2442 }
2443
2444 if (w->plot.ShowXLabel) {
2445 axisXlabelsize = (real) w->plot.Margin +
2446 FontnumHeight(w, w->plot.labelFont);
2447 height -= axisXlabelsize;
2448 }
2449 if (w->plot.ShowYLabel) {
2450 axisYlabelsize = (real) w->plot.Margin +
2451 FontnumHeight(w, w->plot.labelFont);
2452 width -= axisYlabelsize;
2453 w->plot.x.Origin += axisYlabelsize;
2454 }
2455 }
2456
2457 w->plot.x.Size = width;
2458 w->plot.y.Size = height;
2459
2460 /* Adjust parameters for polar plot */
2461 if (w->plot.ChartType == XtPOLAR) {
2462 if (height < width)
2463 w->plot.x.Size = height;
2464 }
2465 w->plot.x.Center = w->plot.x.Origin + (width / 2.0);
2466 w->plot.y.Center = w->plot.y.Origin + (height / 2.0);
2467
2468 }
2469
2470 static void
AdjustDimensionsCartesian(SciPlotWidget w)2471 AdjustDimensionsCartesian (SciPlotWidget w)
2472 {
2473 real xextra, yextra, val, xhorz;
2474 real x, y, width, height, axisnumbersize, axisXlabelsize, axisYlabelsize;
2475 char numberformat[16], label[16];
2476 int precision;
2477
2478 /* Compute xextra and yextra, which are the extra distances that the text
2479 * labels on the axes stick outside of the graph.
2480 */
2481 xextra = yextra = 0.0;
2482 if (w->plot.XAxisNumbers) {
2483 precision = w->plot.x.Precision;
2484 if (w->plot.XLog) {
2485 val = w->plot.x.DrawMax;
2486 precision -= w->plot.x.MajorNum;
2487 if (precision < 0)
2488 precision = 0;
2489 }
2490 else
2491 val = w->plot.x.DrawOrigin + floor(w->plot.x.DrawSize /
2492 w->plot.x.MajorInc) * w->plot.x.MajorInc;
2493 x = PlotX(w, val);
2494 sprintf(numberformat, "%%.%df", precision);
2495 sprintf(label, numberformat, val);
2496 x += FontnumTextWidth(w, w->plot.axisFont, label);
2497 if ((int) x > w->core.width) {
2498 xextra = ceil(x - w->core.width + w->plot.Margin);
2499 if (xextra < 0.0)
2500 xextra = 0.0;
2501 }
2502 }
2503
2504 yextra=xhorz=0.0;
2505 if (w->plot.YAxisNumbers) {
2506 precision = w->plot.y.Precision;
2507 if (w->plot.YLog) {
2508 int p1,p2;
2509
2510 p1=precision;
2511 val = w->plot.y.DrawOrigin;
2512 if (p1 > 0)
2513 p1--;
2514
2515 val = w->plot.y.DrawMax;
2516 p2 = precision - w->plot.y.MajorNum;
2517 if (p2 < 0)
2518 p2 = 0;
2519
2520 if (p1>p2) precision=p1;
2521 else precision=p2;
2522 }
2523 else
2524 val = w->plot.y.DrawOrigin + floor(w->plot.y.DrawSize /
2525 w->plot.y.MajorInc * 1.0001) * w->plot.y.MajorInc;
2526 y = PlotY(w, val);
2527 sprintf(numberformat, "%%.%df", precision);
2528 sprintf(label, numberformat, val);
2529 #ifdef DEBUG_SCIPLOT
2530 printf("ylabel=%s\n", label);
2531 #endif
2532 if (w->plot.YNumHorz) {
2533 yextra=FontnumHeight(w, w->plot.axisFont)/2.0;
2534 xhorz=FontnumTextWidth(w, w->plot.axisFont, label) + (real)w->plot.Margin;
2535 }
2536 else {
2537 y -= FontnumTextWidth(w, w->plot.axisFont, label);
2538 if ((int) y <= 0) {
2539 yextra = ceil(w->plot.Margin - y);
2540 if (yextra < 0.0)
2541 yextra = 0.0;
2542 }
2543 }
2544 }
2545
2546 /* x,y is the origin of the upper left corner of the drawing area inside
2547 * the widget. Doesn't necessarily have to be (Margin,Margin) as it is now.
2548 */
2549 x = (real) w->plot.Margin + xhorz;
2550 y = (real) w->plot.Margin + yextra;
2551
2552 /* width = (real)w->core.width - (real)w->plot.Margin - x -
2553 * legendwidth - AxisFontHeight
2554 */
2555 width = (real) w->core.width - (real) w->plot.Margin - x - xextra;
2556
2557
2558 /* height = (real)w->core.height - (real)w->plot.Margin - y
2559 * - Height of axis numbers (including margin)
2560 * - Height of axis label (including margin)
2561 * - Height of Title (including margin)
2562 */
2563 height = (real) w->core.height - (real) w->plot.Margin - y;
2564
2565 w->plot.x.Origin = x;
2566 w->plot.y.Origin = y;
2567
2568 /* Adjust the size depending upon what sorts of text are visible. */
2569 if (w->plot.ShowTitle)
2570 height -= (real) w->plot.TitleMargin +
2571 FontnumHeight(w, w->plot.titleFont);
2572
2573 axisXlabelsize = 0.0;
2574 axisYlabelsize = 0.0;
2575 axisnumbersize = (real) w->plot.Margin +
2576 FontnumHeight(w, w->plot.axisFont);
2577 if (w->plot.XAxisNumbers) {
2578 height -= axisnumbersize;
2579 }
2580 if (w->plot.YAxisNumbers && !w->plot.YNumHorz) {
2581 width -= axisnumbersize;
2582 w->plot.x.Origin += axisnumbersize;
2583 }
2584
2585 if (w->plot.ShowXLabel) {
2586 axisXlabelsize = (real) w->plot.Margin +
2587 FontnumHeight(w, w->plot.labelFont);
2588 height -= axisXlabelsize;
2589 }
2590 if (w->plot.ShowYLabel) {
2591 axisYlabelsize = (real) w->plot.Margin +
2592 FontnumHeight(w, w->plot.labelFont);
2593 width -= axisYlabelsize;
2594 w->plot.x.Origin += axisYlabelsize;
2595 }
2596
2597 /* Move legend position to the right of the plot */
2598 if (w->plot.LegendThroughPlot) {
2599 w->plot.x.LegendPos += w->plot.x.Origin + width - w->plot.x.LegendSize;
2600 w->plot.y.LegendPos += w->plot.y.Origin;
2601 }
2602 else {
2603 width -= w->plot.x.LegendSize;
2604 w->plot.x.LegendPos += w->plot.x.Origin + width;
2605 w->plot.y.LegendPos += w->plot.y.Origin;
2606 }
2607
2608 w->plot.x.Size = width;
2609 w->plot.y.Size = height;
2610
2611 w->plot.y.AxisPos = w->plot.y.Origin + w->plot.y.Size +
2612 (real) w->plot.Margin +
2613 FontnumAscent(w, w->plot.axisFont);
2614 if (w->plot.YNumHorz) {
2615 w->plot.x.AxisPos = w->plot.x.Origin - (real) w->plot.Margin;
2616 }
2617 else {
2618 w->plot.x.AxisPos = w->plot.x.Origin -
2619 (real) w->plot.Margin -
2620 FontnumDescent(w, w->plot.axisFont);
2621 }
2622
2623 w->plot.y.LabelPos = w->plot.y.Origin + w->plot.y.Size +
2624 (real) w->plot.Margin + (FontnumHeight(w, w->plot.labelFont) / 2.0);
2625 if (w->plot.XAxisNumbers)
2626 w->plot.y.LabelPos += axisnumbersize;
2627 if (w->plot.YAxisNumbers) {
2628 if (w->plot.YNumHorz) {
2629 w->plot.x.LabelPos = w->plot.x.Origin -
2630 xhorz - (real) w->plot.Margin -
2631 (FontnumHeight(w, w->plot.labelFont) / 2.0);
2632 }
2633 else {
2634 w->plot.x.LabelPos = w->plot.x.Origin -
2635 axisnumbersize - (real) w->plot.Margin -
2636 (FontnumHeight(w, w->plot.labelFont) / 2.0);
2637 }
2638 }
2639 else {
2640 w->plot.x.LabelPos = w->plot.x.Origin - (real) w->plot.Margin -
2641 (FontnumHeight(w, w->plot.labelFont) / 2.0);
2642 }
2643
2644 w->plot.y.TitlePos = (real) w->core.height - (real) w->plot.Margin;
2645 w->plot.x.TitlePos = (real) w->plot.Margin;
2646
2647 #ifdef DEBUG_SCIPLOT
2648 printf("y.Origin: %f\n", w->plot.y.Origin);
2649 printf("y.Size: %f\n", w->plot.y.Size);
2650 printf("axisnumbersize: %f\n", axisnumbersize);
2651 printf("y.axisLabelSize: %f\n", axisYlabelsize);
2652 printf("y.TitleSize: %f\n",
2653 (real) w->plot.TitleMargin + FontnumHeight(w, w->plot.titleFont));
2654 printf("y.Margin: %f\n", (real) w->plot.Margin);
2655 printf("total-------------------%f\n", w->plot.y.Origin + w->plot.y.Size +
2656 axisnumbersize + axisYlabelsize + (real) w->plot.Margin +
2657 (real) w->plot.TitleMargin + FontnumHeight(w, w->plot.titleFont));
2658 printf("total should be---------%f\n", (real) w->core.height);
2659 #endif
2660 }
2661
2662 static void
AdjustDimensionsPolar(SciPlotWidget w)2663 AdjustDimensionsPolar (SciPlotWidget w)
2664 {
2665 real x, y, xextra, yextra, val;
2666 real width, height, size;
2667 char numberformat[16], label[16];
2668
2669 /* Compute xextra and yextra, which are the extra distances that the text
2670 * labels on the axes stick outside of the graph.
2671 */
2672 xextra = yextra = 0.0;
2673 val = w->plot.PolarScale;
2674 PlotRTDegrees(w, val, 0.0, &x, &y);
2675 sprintf(numberformat, "%%.%df", w->plot.x.Precision);
2676 sprintf(label, numberformat, val);
2677 x += FontnumTextWidth(w, w->plot.axisFont, label);
2678 if ((int) x > w->core.width) {
2679 xextra = x - w->core.width + w->plot.Margin;
2680 if (xextra < 0.0)
2681 xextra = 0.0;
2682 }
2683 yextra = 0.0;
2684
2685
2686 /* x,y is the origin of the upper left corner of the drawing area inside
2687 * the widget. Doesn't necessarily have to be (Margin,Margin) as it is now.
2688 */
2689 w->plot.x.Origin = (real) w->plot.Margin;
2690 w->plot.y.Origin = (real) w->plot.Margin;
2691
2692 /* width = (real)w->core.width - (real)w->plot.Margin - x -
2693 * legendwidth - AxisFontHeight
2694 */
2695 width = (real) w->core.width - (real) w->plot.Margin - w->plot.x.Origin - xextra;
2696
2697 /* height = (real)w->core.height - (real)w->plot.Margin - y
2698 * - Height of axis numbers (including margin)
2699 * - Height of axis label (including margin)
2700 * - Height of Title (including margin)
2701 */
2702 height = (real) w->core.height - (real) w->plot.Margin - w->plot.y.Origin - yextra;
2703
2704 /* Adjust the size depending upon what sorts of text are visible. */
2705 if (w->plot.ShowTitle)
2706 height -= (real) w->plot.TitleMargin +
2707 FontnumHeight(w, w->plot.titleFont);
2708
2709 /* Only need to carry one number for the size, (since it is a circle!) */
2710 if (height < width)
2711 size = height;
2712 else
2713 size = width;
2714
2715 /* Assign some preliminary values */
2716 w->plot.x.Center = w->plot.x.Origin + (width / 2.0);
2717 w->plot.y.Center = w->plot.y.Origin + (height / 2.0);
2718 w->plot.x.LegendPos += width - w->plot.x.LegendSize;
2719 w->plot.y.LegendPos += w->plot.y.Origin;
2720
2721 /*
2722 * Check and see if the legend can fit in the blank space in the upper right
2723 *
2724 * To fit, the legend must:
2725 * 1) be less than half the width/height of the plot
2726 * 2) hmmm.
2727 */
2728 if (!w->plot.LegendThroughPlot) {
2729 real radius = size / 2.0;
2730 real dist;
2731
2732 x = w->plot.x.LegendPos - w->plot.x.Center;
2733 y = (w->plot.y.LegendPos + w->plot.y.LegendSize) - w->plot.y.Center;
2734
2735 dist = sqrt(x * x + y * y);
2736 /* printf("rad=%f dist=%f: legend=(%f,%f) center=(%f,%f)\n", */
2737 /* radius,dist,w->plot.x.LegendPos,w->plot.y.LegendPos, */
2738 /* w->plot.x.Center,w->plot.y.Center); */
2739
2740 /* It doesn't fit if this check is true. Make the plot smaller */
2741
2742 /* This is a first cut horrible algorithm. My calculus is a bit
2743 * rusty tonight--can't seem to figure out how to maximize a circle
2744 * in a rectangle with a rectangular chunk out of it. */
2745 if (dist < radius) {
2746 width -= w->plot.x.LegendSize;
2747 height -= w->plot.y.LegendSize;
2748
2749 /* readjust some parameters */
2750 w->plot.x.Center = w->plot.x.Origin + width / 2.0;
2751 w->plot.y.Center = w->plot.y.Origin + w->plot.y.LegendSize + height / 2.0;
2752 if (height < width)
2753 size = height;
2754 else
2755 size = width;
2756 }
2757
2758 }
2759
2760
2761 /* OK, customization is finished when we reach here. */
2762 w->plot.x.Size = w->plot.y.Size = size;
2763
2764 w->plot.y.TitlePos = w->plot.y.Center + w->plot.y.Size / 2.0 +
2765 (real) w->plot.TitleMargin +
2766 FontnumAscent(w, w->plot.titleFont);
2767 w->plot.x.TitlePos = w->plot.x.Origin;
2768 }
2769
2770 static void
AdjustDimensions(SciPlotWidget w)2771 AdjustDimensions (SciPlotWidget w)
2772 {
2773 if (w->plot.ChartType == XtCARTESIAN) {
2774 AdjustDimensionsCartesian(w);
2775 }
2776 else {
2777 AdjustDimensionsPolar(w);
2778 }
2779 }
2780
2781 static void
ComputeAllDimensions(SciPlotWidget w)2782 ComputeAllDimensions (SciPlotWidget w)
2783 {
2784 ComputeLegendDimensions(w);
2785 ComputeDimensions(w);
2786 ComputeDrawingRange(w);
2787 AdjustDimensions(w);
2788 }
2789
2790 static void
ComputeAll(SciPlotWidget w)2791 ComputeAll (SciPlotWidget w)
2792 {
2793 ComputeMinMax(w);
2794 ComputeAllDimensions(w);
2795 }
2796
2797
2798 /*
2799 * Private drawing routines
2800 */
2801
2802 static void
DrawMarker(SciPlotWidget w,real xpaper,real ypaper,real size,int color,int style)2803 DrawMarker (SciPlotWidget w, real xpaper, real ypaper, real size, int color, int style)
2804 {
2805 real sizex, sizey;
2806
2807 switch (style) {
2808 case XtMARKER_CIRCLE:
2809 CircleSet(w, xpaper, ypaper, size, color, XtLINE_SOLID);
2810 break;
2811 case XtMARKER_FCIRCLE:
2812 FilledCircleSet(w, xpaper, ypaper, size, color, XtLINE_SOLID);
2813 break;
2814 case XtMARKER_SQUARE:
2815 size -= .5;
2816 RectSet(w, xpaper - size, ypaper - size,
2817 xpaper + size, ypaper + size,
2818 color, XtLINE_SOLID);
2819 break;
2820 case XtMARKER_FSQUARE:
2821 size -= .5;
2822 FilledRectSet(w, xpaper - size, ypaper - size,
2823 xpaper + size, ypaper + size,
2824 color, XtLINE_SOLID);
2825 break;
2826 case XtMARKER_UTRIANGLE:
2827 sizex = size * .866;
2828 sizey = size / 2.0;
2829 TriSet(w, xpaper, ypaper - size,
2830 xpaper + sizex, ypaper + sizey,
2831 xpaper - sizex, ypaper + sizey,
2832 color, XtLINE_SOLID);
2833 break;
2834 case XtMARKER_FUTRIANGLE:
2835 sizex = size * .866;
2836 sizey = size / 2.0;
2837 FilledTriSet(w, xpaper, ypaper - size,
2838 xpaper + sizex, ypaper + sizey,
2839 xpaper - sizex, ypaper + sizey,
2840 color, XtLINE_SOLID);
2841 break;
2842 case XtMARKER_DTRIANGLE:
2843 sizex = size * .866;
2844 sizey = size / 2.0;
2845 TriSet(w, xpaper, ypaper + size,
2846 xpaper + sizex, ypaper - sizey,
2847 xpaper - sizex, ypaper - sizey,
2848 color, XtLINE_SOLID);
2849 break;
2850 case XtMARKER_FDTRIANGLE:
2851 sizex = size * .866;
2852 sizey = size / 2.0;
2853 FilledTriSet(w, xpaper, ypaper + size,
2854 xpaper + sizex, ypaper - sizey,
2855 xpaper - sizex, ypaper - sizey,
2856 color, XtLINE_SOLID);
2857 break;
2858 case XtMARKER_RTRIANGLE:
2859 sizey = size * .866;
2860 sizex = size / 2.0;
2861 TriSet(w, xpaper + size, ypaper,
2862 xpaper - sizex, ypaper + sizey,
2863 xpaper - sizex, ypaper - sizey,
2864 color, XtLINE_SOLID);
2865 break;
2866 case XtMARKER_FRTRIANGLE:
2867 sizey = size * .866;
2868 sizex = size / 2.0;
2869 FilledTriSet(w, xpaper + size, ypaper,
2870 xpaper - sizex, ypaper + sizey,
2871 xpaper - sizex, ypaper - sizey,
2872 color, XtLINE_SOLID);
2873 break;
2874 case XtMARKER_LTRIANGLE:
2875 sizey = size * .866;
2876 sizex = size / 2.0;
2877 TriSet(w, xpaper - size, ypaper,
2878 xpaper + sizex, ypaper + sizey,
2879 xpaper + sizex, ypaper - sizey,
2880 color, XtLINE_SOLID);
2881 break;
2882 case XtMARKER_FLTRIANGLE:
2883 sizey = size * .866;
2884 sizex = size / 2.0;
2885 FilledTriSet(w, xpaper - size, ypaper,
2886 xpaper + sizex, ypaper + sizey,
2887 xpaper + sizex, ypaper - sizey,
2888 color, XtLINE_SOLID);
2889 break;
2890 case XtMARKER_DIAMOND:
2891 QuadSet(w, xpaper, ypaper - size,
2892 xpaper + size, ypaper,
2893 xpaper, ypaper + size,
2894 xpaper - size, ypaper,
2895 color, XtLINE_SOLID);
2896 break;
2897 case XtMARKER_FDIAMOND:
2898 FilledQuadSet(w, xpaper, ypaper - size,
2899 xpaper + size, ypaper,
2900 xpaper, ypaper + size,
2901 xpaper - size, ypaper,
2902 color, XtLINE_SOLID);
2903 break;
2904 case XtMARKER_HOURGLASS:
2905 QuadSet(w, xpaper - size, ypaper - size,
2906 xpaper + size, ypaper - size,
2907 xpaper - size, ypaper + size,
2908 xpaper + size, ypaper + size,
2909 color, XtLINE_SOLID);
2910 break;
2911 case XtMARKER_FHOURGLASS:
2912 FilledQuadSet(w, xpaper - size, ypaper - size,
2913 xpaper + size, ypaper - size,
2914 xpaper - size, ypaper + size,
2915 xpaper + size, ypaper + size,
2916 color, XtLINE_SOLID);
2917 break;
2918 case XtMARKER_BOWTIE:
2919 QuadSet(w, xpaper - size, ypaper - size,
2920 xpaper - size, ypaper + size,
2921 xpaper + size, ypaper - size,
2922 xpaper + size, ypaper + size,
2923 color, XtLINE_SOLID);
2924 break;
2925 case XtMARKER_FBOWTIE:
2926 FilledQuadSet(w, xpaper - size, ypaper - size,
2927 xpaper - size, ypaper + size,
2928 xpaper + size, ypaper - size,
2929 xpaper + size, ypaper + size,
2930 color, XtLINE_SOLID);
2931 break;
2932 case XtMARKER_DOT:
2933 FilledCircleSet(w, xpaper, ypaper, 1.5, color, XtLINE_SOLID);
2934 break;
2935
2936 default:
2937 break;
2938 }
2939 }
2940
2941 static void
DrawLegend(SciPlotWidget w)2942 DrawLegend (SciPlotWidget w)
2943 {
2944 real x, y, len, height, height2, len2, ascent;
2945 int i;
2946 SciPlotList *p;
2947
2948 w->plot.current_id = SciPlotDrawingLegend;
2949 if (w->plot.ShowLegend) {
2950 x = w->plot.x.LegendPos;
2951 y = w->plot.y.LegendPos;
2952 len = (real) w->plot.LegendLineSize;
2953 len2 = len / 2.0;
2954 height = FontnumHeight(w, w->plot.axisFont);
2955 height2 = height / 2.0;
2956 ascent = FontnumAscent(w, w->plot.axisFont);
2957 RectSet(w, x, y,
2958 x + w->plot.x.LegendSize - 1.0 - (real) w->plot.Margin,
2959 y + w->plot.y.LegendSize - 1.0,
2960 w->plot.ForegroundColor, XtLINE_SOLID);
2961 x += (real) w->plot.LegendMargin;
2962 y += (real) w->plot.LegendMargin;
2963
2964 for (i = 0; i < w->plot.num_plotlist; i++) {
2965 p = w->plot.plotlist + i;
2966 if (p->draw) {
2967 LineSet(w, x, y + height2, x + len, y + height2,
2968 p->LineColor, p->LineStyle);
2969 DrawMarker(w, x + len2, y + height2, p->markersize,
2970 p->PointColor, p->PointStyle);
2971 TextSet(w, x + len + (real) w->plot.LegendMargin,
2972 y + ascent,
2973 p->legend, w->plot.ForegroundColor,
2974 w->plot.axisFont);
2975 y += height;
2976 }
2977 }
2978 }
2979 }
2980
2981 static void
DrawCartesianAxes(SciPlotWidget w)2982 DrawCartesianAxes (SciPlotWidget w)
2983 {
2984 real x, y, x1, y1, x2, y2, tic, val, height, majorval;
2985 int j, precision;
2986 char numberformat[16], label[16];
2987
2988 w->plot.current_id = SciPlotDrawingAxis;
2989 height = FontnumHeight(w, w->plot.labelFont);
2990 x1 = PlotX(w, w->plot.x.DrawOrigin);
2991 y1 = PlotY(w, w->plot.y.DrawOrigin);
2992 x2 = PlotX(w, w->plot.x.DrawMax);
2993 y2 = PlotY(w, w->plot.y.DrawMax);
2994 LineSet(w, x1, y1, x2, y1, w->plot.ForegroundColor, XtLINE_SOLID);
2995 LineSet(w, x1, y1, x1, y2, w->plot.ForegroundColor, XtLINE_SOLID);
2996
2997 precision = w->plot.x.Precision;
2998 sprintf(numberformat, "%%.%df", precision);
2999 if (w->plot.XLog) {
3000 val = w->plot.x.DrawOrigin;
3001 if (precision > 0)
3002 precision--;
3003 }
3004 else {
3005 val = w->plot.x.DrawOrigin;
3006 }
3007 x = PlotX(w, val);
3008 if (w->plot.DrawMajorTics)
3009 LineSet(w, x, y1 + 5, x, y1 - 5, w->plot.ForegroundColor, XtLINE_SOLID);
3010 if (w->plot.XAxisNumbers) {
3011 sprintf(label, numberformat, val);
3012 TextSet(w, x, w->plot.y.AxisPos, label, w->plot.ForegroundColor,
3013 w->plot.axisFont);
3014 }
3015
3016 majorval = val;
3017 while ((majorval * 1.0001) < w->plot.x.DrawMax) {
3018 if (w->plot.XLog) {
3019
3020 /* Hack to make sure that 9.99999e? still gets interpreted as 10.0000e? */
3021 if (majorval * 1.1 > w->plot.x.DrawMax)
3022 break;
3023 tic = majorval;
3024 if (w->plot.DrawMinor || w->plot.DrawMinorTics) {
3025 for (j = 2; j < w->plot.x.MinorNum; j++) {
3026 val = tic * (real) j;
3027 x = PlotX(w, val);
3028 if (w->plot.DrawMinor)
3029 LineSet(w, x, y1, x, y2,
3030 w->plot.ForegroundColor,
3031 XtLINE_WIDEDOT);
3032 if (w->plot.DrawMinorTics)
3033 LineSet(w, x, y1, x, y1 - 3,
3034 w->plot.ForegroundColor,
3035 XtLINE_SOLID);
3036 }
3037 }
3038 val = tic * (real) w->plot.x.MinorNum;
3039 sprintf(numberformat, "%%.%df", precision);
3040 if (precision > 0)
3041 precision--;
3042 }
3043 else {
3044 tic = majorval;
3045 if (w->plot.DrawMinor || w->plot.DrawMinorTics) {
3046 for (j = 1; j < w->plot.x.MinorNum; j++) {
3047 val = tic + w->plot.x.MajorInc * (real) j /
3048 w->plot.x.MinorNum;
3049 x = PlotX(w, val);
3050 if (w->plot.DrawMinor)
3051 LineSet(w, x, y1, x, y2,
3052 w->plot.ForegroundColor,
3053 XtLINE_WIDEDOT);
3054 if (w->plot.DrawMinorTics)
3055 LineSet(w, x, y1, x, y1 - 3,
3056 w->plot.ForegroundColor,
3057 XtLINE_SOLID);
3058 }
3059 }
3060 val = tic + w->plot.x.MajorInc;
3061 }
3062 x = PlotX(w, val);
3063 if (w->plot.DrawMajor)
3064 LineSet(w, x, y1, x, y2, w->plot.ForegroundColor,
3065 XtLINE_DOTTED);
3066 else if (w->plot.DrawMinor)
3067 LineSet(w, x, y1, x, y2, w->plot.ForegroundColor,
3068 XtLINE_WIDEDOT);
3069 if (w->plot.DrawMajorTics)
3070 LineSet(w, x, y1 + 5, x, y1 - 5, w->plot.ForegroundColor,
3071 XtLINE_SOLID);
3072 if (w->plot.XAxisNumbers) {
3073 sprintf(label, numberformat, val);
3074 TextSet(w, x, w->plot.y.AxisPos, label, w->plot.ForegroundColor,
3075 w->plot.axisFont);
3076 }
3077 majorval = val;
3078 }
3079
3080 precision = w->plot.y.Precision;
3081 sprintf(numberformat, "%%.%df", precision);
3082 if (w->plot.YLog) {
3083 val = w->plot.y.DrawOrigin;
3084 if (precision > 0)
3085 precision--;
3086 }
3087 else {
3088 val = w->plot.y.DrawOrigin;
3089 }
3090 y = PlotY(w, val);
3091 if (w->plot.DrawMajorTics)
3092 LineSet(w, x1 + 5, y, x1 - 5, y, w->plot.ForegroundColor, XtLINE_SOLID);
3093 if (w->plot.YAxisNumbers) {
3094 sprintf(label, numberformat, val);
3095 if (w->plot.YNumHorz) {
3096 y+=FontnumHeight(w, w->plot.axisFont)/2.0 -
3097 FontnumDescent(w, w->plot.axisFont);
3098 TextSet(w,
3099 w->plot.x.AxisPos - FontnumTextWidth(w, w->plot.axisFont, label),
3100 y, label, w->plot.ForegroundColor,
3101 w->plot.axisFont);
3102 }
3103 else {
3104 VTextSet(w, w->plot.x.AxisPos, y, label, w->plot.ForegroundColor,
3105 w->plot.axisFont);
3106 }
3107 }
3108 majorval = val;
3109
3110 /* majorval*1.0001 is a fudge to get rid of rounding errors that seem to
3111 * occur when continuing to add the major axis increment.
3112 */
3113 while ((majorval * 1.0001) < w->plot.y.DrawMax) {
3114 if (w->plot.YLog) {
3115
3116 /* Hack to make sure that 9.99999e? still gets interpreted as 10.0000e? */
3117 if (majorval * 1.1 > w->plot.y.DrawMax)
3118 break;
3119 tic = majorval;
3120 if (w->plot.DrawMinor || w->plot.DrawMinorTics) {
3121 for (j = 2; j < w->plot.y.MinorNum; j++) {
3122 val = tic * (real) j;
3123 y = PlotY(w, val);
3124 if (w->plot.DrawMinor)
3125 LineSet(w, x1, y, x2, y,
3126 w->plot.ForegroundColor,
3127 XtLINE_WIDEDOT);
3128 if (w->plot.DrawMinorTics)
3129 LineSet(w, x1, y, x1 + 3, y,
3130 w->plot.ForegroundColor,
3131 XtLINE_SOLID);
3132 }
3133 }
3134 val = tic * (real) w->plot.y.MinorNum;
3135 sprintf(numberformat, "%%.%df", precision);
3136 if (precision > 0)
3137 precision--;
3138 }
3139 else {
3140 tic = majorval;
3141 if (w->plot.DrawMinor || w->plot.DrawMinorTics) {
3142 for (j = 1; j < w->plot.y.MinorNum; j++) {
3143 val = tic + w->plot.y.MajorInc * (real) j /
3144 w->plot.y.MinorNum;
3145 y = PlotY(w, val);
3146 if (w->plot.DrawMinor)
3147 LineSet(w, x1, y, x2, y,
3148 w->plot.ForegroundColor,
3149 XtLINE_WIDEDOT);
3150 if (w->plot.DrawMinorTics)
3151 LineSet(w, x1, y, x1 + 3, y,
3152 w->plot.ForegroundColor,
3153 XtLINE_SOLID);
3154 }
3155 }
3156 val = tic + w->plot.y.MajorInc;
3157 }
3158 y = PlotY(w, val);
3159 if (w->plot.DrawMajor)
3160 LineSet(w, x1, y, x2, y, w->plot.ForegroundColor,
3161 XtLINE_DOTTED);
3162 else if (w->plot.DrawMinor)
3163 LineSet(w, x1, y, x2, y, w->plot.ForegroundColor,
3164 XtLINE_WIDEDOT);
3165 if (w->plot.DrawMajorTics)
3166 LineSet(w, x1 - 5, y, x1 + 5, y, w->plot.ForegroundColor,
3167 XtLINE_SOLID);
3168 if (w->plot.YAxisNumbers) {
3169 sprintf(label, numberformat, val);
3170 if (w->plot.YNumHorz) {
3171 y+=FontnumHeight(w, w->plot.axisFont)/2.0 -
3172 FontnumDescent(w, w->plot.axisFont);
3173 TextSet(w,
3174 w->plot.x.AxisPos - FontnumTextWidth(w, w->plot.axisFont, label),
3175 y, label, w->plot.ForegroundColor,
3176 w->plot.axisFont);
3177 }
3178 else {
3179 VTextSet(w, w->plot.x.AxisPos, y, label, w->plot.ForegroundColor,
3180 w->plot.axisFont);
3181 }
3182 }
3183 majorval = val;
3184 }
3185
3186 if (w->plot.ShowTitle)
3187 TextSet(w, w->plot.x.TitlePos, w->plot.y.TitlePos,
3188 w->plot.plotTitle, w->plot.ForegroundColor,
3189 w->plot.titleFont);
3190 if (w->plot.ShowXLabel)
3191 TextCenter(w, w->plot.x.Origin + (w->plot.x.Size / 2.0),
3192 w->plot.y.LabelPos, w->plot.xlabel,
3193 w->plot.ForegroundColor, w->plot.labelFont);
3194 if (w->plot.ShowYLabel)
3195 VTextCenter(w, w->plot.x.LabelPos,
3196 w->plot.y.Origin + (w->plot.y.Size / 2.0),
3197 w->plot.ylabel, w->plot.ForegroundColor,
3198 w->plot.labelFont);
3199 }
3200
3201
3202 static void
DrawCartesianPlot(SciPlotWidget w)3203 DrawCartesianPlot (SciPlotWidget w)
3204 {
3205 int i, j, jstart;
3206 SciPlotList *p;
3207
3208 w->plot.current_id = SciPlotDrawingAny;
3209 ClipSet(w);
3210 w->plot.current_id = SciPlotDrawingLine;
3211 for (i = 0; i < w->plot.num_plotlist; i++) {
3212 p = w->plot.plotlist + i;
3213 if (p->draw) {
3214 real x1, y1, x2, y2;
3215 Boolean skipnext=False;
3216
3217 jstart = 0;
3218 while ((jstart < p->number) &&
3219 (((p->data[jstart].x <= SCIPLOT_SKIP_VAL ||
3220 p->data[jstart].y <= SCIPLOT_SKIP_VAL) ||
3221 (w->plot.XLog && (p->data[jstart].x <= 0.0)) ||
3222 (w->plot.YLog && (p->data[jstart].y <= 0.0)))))
3223 jstart++;
3224 if (jstart < p->number) {
3225 x1 = PlotX(w, p->data[jstart].x);
3226 y1 = PlotY(w, p->data[jstart].y);
3227 }
3228 for (j = jstart; j < p->number; j++) {
3229 if (p->data[j].x <= SCIPLOT_SKIP_VAL ||
3230 p->data[j].y <= SCIPLOT_SKIP_VAL) {
3231 skipnext=True;
3232 continue;
3233 }
3234
3235 if (!((w->plot.XLog && (p->data[j].x <= 0.0)) ||
3236 (w->plot.YLog && (p->data[j].y <= 0.0)))) {
3237 x2 = PlotX(w, p->data[j].x);
3238 y2 = PlotY(w, p->data[j].y);
3239 if (!skipnext)
3240 LineSet(w, x1, y1, x2, y2, p->LineColor, p->LineStyle);
3241 x1 = x2;
3242 y1 = y2;
3243 }
3244
3245 skipnext=False;
3246 }
3247 }
3248 }
3249 w->plot.current_id = SciPlotDrawingAny;
3250 ClipClear(w);
3251 w->plot.current_id = SciPlotDrawingLine;
3252 for (i = 0; i < w->plot.num_plotlist; i++) {
3253 p = w->plot.plotlist + i;
3254 if (p->draw) {
3255 real x2, y2;
3256
3257 for (j = 0; j < p->number; j++) {
3258 if (!((w->plot.XLog && (p->data[j].x <= 0.0)) ||
3259 (w->plot.YLog && (p->data[j].y <= 0.0)) ||
3260 p->data[j].x <= SCIPLOT_SKIP_VAL ||
3261 p->data[j].y <= SCIPLOT_SKIP_VAL )) {
3262 x2 = PlotX(w, p->data[j].x);
3263 y2 = PlotY(w, p->data[j].y);
3264 if ((x2 >= w->plot.x.Origin) &&
3265 (x2 <= w->plot.x.Origin + w->plot.x.Size) &&
3266 (y2 >= w->plot.y.Origin) &&
3267 (y2 <= w->plot.y.Origin + w->plot.y.Size)) {
3268
3269 DrawMarker(w, x2, y2,
3270 p->markersize,
3271 p->PointColor,
3272 p->PointStyle);
3273 }
3274
3275 }
3276 }
3277 }
3278 }
3279 }
3280
3281 static void
DrawPolarAxes(SciPlotWidget w)3282 DrawPolarAxes (SciPlotWidget w)
3283 {
3284 real x1, y1, x2, y2, max, tic, val, height;
3285 int i, j;
3286 char numberformat[16], label[16];
3287
3288 w->plot.current_id = SciPlotDrawingAxis;
3289 sprintf(numberformat, "%%.%df", w->plot.x.Precision);
3290 height = FontnumHeight(w, w->plot.labelFont);
3291 max = w->plot.PolarScale;
3292 PlotRTDegrees(w, 0.0, 0.0, &x1, &y1);
3293 PlotRTDegrees(w, max, 0.0, &x2, &y2);
3294 LineSet(w, x1, y1, x2, y2, 1, XtLINE_SOLID);
3295 for (i = 45; i < 360; i += 45) {
3296 PlotRTDegrees(w, max, (real) i, &x2, &y2);
3297 LineSet(w, x1, y1, x2, y2, w->plot.ForegroundColor, XtLINE_DOTTED);
3298 }
3299 for (i = 1; i <= w->plot.x.MajorNum; i++) {
3300 tic = w->plot.PolarScale *
3301 (real) i / (real) w->plot.x.MajorNum;
3302 if (w->plot.DrawMinor || w->plot.DrawMinorTics) {
3303 for (j = 1; j < w->plot.x.MinorNum; j++) {
3304 val = tic - w->plot.x.MajorInc * (real) j /
3305 w->plot.x.MinorNum;
3306 PlotRTDegrees(w, val, 0.0, &x2, &y2);
3307 if (w->plot.DrawMinor)
3308 CircleSet(w, x1, y1, x2 - x1,
3309 w->plot.ForegroundColor, XtLINE_WIDEDOT);
3310 if (w->plot.DrawMinorTics)
3311 LineSet(w, x2, y2 - 2.5, x2, y2 + 2.5,
3312 w->plot.ForegroundColor, XtLINE_SOLID);
3313 }
3314 }
3315 PlotRTDegrees(w, tic, 0.0, &x2, &y2);
3316 if (w->plot.DrawMajor)
3317 CircleSet(w, x1, y1, x2 - x1, w->plot.ForegroundColor, XtLINE_DOTTED);
3318 if (w->plot.DrawMajorTics)
3319 LineSet(w, x2, y2 - 5.0, x2, y2 + 5.0, w->plot.ForegroundColor, XtLINE_SOLID);
3320 if (w->plot.XAxisNumbers) {
3321 sprintf(label, numberformat, tic);
3322 TextSet(w, x2, y2 + height, label, w->plot.ForegroundColor, w->plot.axisFont);
3323 }
3324 }
3325
3326 if (w->plot.ShowTitle)
3327 TextSet(w, w->plot.x.TitlePos, w->plot.y.TitlePos,
3328 w->plot.plotTitle, w->plot.ForegroundColor, w->plot.titleFont);
3329 }
3330
3331 static void
DrawPolarPlot(SciPlotWidget w)3332 DrawPolarPlot (SciPlotWidget w)
3333 {
3334 int i, j;
3335 SciPlotList *p;
3336
3337 w->plot.current_id = SciPlotDrawingLine;
3338 for (i = 0; i < w->plot.num_plotlist; i++) {
3339 p = w->plot.plotlist + i;
3340 if (p->draw) {
3341 int jstart;
3342 real x1, y1, x2, y2;
3343 Boolean skipnext=False;
3344
3345 jstart = 0;
3346 while ((jstart < p->number) &&
3347 (p->data[jstart].x <= SCIPLOT_SKIP_VAL ||
3348 p->data[jstart].y <= SCIPLOT_SKIP_VAL))
3349 jstart++;
3350 if (jstart < p->number) {
3351 PlotRT(w, p->data[0].x, p->data[0].y, &x1, &y1);
3352 }
3353 for (j = jstart; j < p->number; j++) {
3354 if (p->data[j].x <= SCIPLOT_SKIP_VAL ||
3355 p->data[j].y <= SCIPLOT_SKIP_VAL) {
3356 skipnext=True;
3357 continue;
3358 }
3359
3360 PlotRT(w, p->data[j].x, p->data[j].y, &x2, &y2);
3361 if (!skipnext) {
3362 LineSet(w, x1, y1, x2, y2,
3363 p->LineColor, p->LineStyle);
3364 DrawMarker(w, x1, y1, p->markersize,
3365 p->PointColor, p->PointStyle);
3366 DrawMarker(w, x2, y2, p->markersize,
3367 p->PointColor, p->PointStyle);
3368 }
3369 x1 = x2;
3370 y1 = y2;
3371
3372 skipnext=False;
3373 }
3374 }
3375 }
3376 }
3377
3378 static void
DrawAll(SciPlotWidget w)3379 DrawAll (SciPlotWidget w)
3380 {
3381 if (w->plot.ChartType == XtCARTESIAN) {
3382 DrawCartesianAxes(w);
3383 DrawLegend(w);
3384 DrawCartesianPlot(w);
3385 }
3386 else {
3387 DrawPolarAxes(w);
3388 DrawLegend(w);
3389 DrawPolarPlot(w);
3390 }
3391 }
3392
3393 static Boolean
DrawQuick(SciPlotWidget w)3394 DrawQuick (SciPlotWidget w)
3395 {
3396 Boolean range_check;
3397
3398 range_check = CheckMinMax(w);
3399 EraseClassItems(w, SciPlotDrawingLine);
3400 EraseAllItems(w);
3401 DrawAll(w);
3402
3403 return range_check;
3404 }
3405
3406
3407 /*
3408 * Public Plot functions
3409 */
3410
3411 int
SciPlotAllocNamedColor(Widget wi,char * name)3412 SciPlotAllocNamedColor (Widget wi, char *name)
3413 {
3414 XColor used, exact;
3415 SciPlotWidget w;
3416
3417 if (!XtIsSciPlot(wi))
3418 return -1;
3419
3420 w = (SciPlotWidget) wi;
3421
3422 if (!XAllocNamedColor(XtDisplay(w), w->plot.cmap, name, &used, &exact))
3423 return 1;
3424 return ColorStore(w, used.pixel);
3425 }
3426
3427 int
SciPlotAllocRGBColor(Widget wi,int r,int g,int b)3428 SciPlotAllocRGBColor (Widget wi, int r, int g, int b)
3429 {
3430 XColor used;
3431 SciPlotWidget w;
3432
3433 if (!XtIsSciPlot(wi))
3434 return -1;
3435
3436 w = (SciPlotWidget) wi;
3437
3438 used.pixel = 0;
3439 r *= 256;
3440 g *= 256;
3441 b *= 256;
3442 if (r > 65535)
3443 r = 65535;
3444 if (g > 65535)
3445 g = 65535;
3446 if (b > 65535)
3447 b = 65535;
3448 used.red = (unsigned short) r;
3449 used.green = (unsigned short) g;
3450 used.blue = (unsigned short) b;
3451 if (!XAllocColor(XtDisplay(w), w->plot.cmap, &used))
3452 return 1;
3453 return ColorStore(w, used.pixel);
3454 }
3455
3456 void
SciPlotSetBackgroundColor(Widget wi,int color)3457 SciPlotSetBackgroundColor (Widget wi, int color)
3458 {
3459 SciPlotWidget w;
3460
3461 if (!XtIsSciPlot(wi))
3462 return;
3463
3464 w = (SciPlotWidget) wi;
3465 if (color < w->plot.num_colors) {
3466 w->plot.BackgroundColor = color;
3467 w->core.background_pixel = w->plot.colors[color];
3468 XSetWindowBackground( XtDisplay(w), XtWindow(w), w->core.background_pixel);
3469 }
3470 }
3471
3472 void
SciPlotSetForegroundColor(Widget wi,int color)3473 SciPlotSetForegroundColor (Widget wi, int color)
3474 {
3475 SciPlotWidget w;
3476
3477 if (!XtIsSciPlot(wi))
3478 return;
3479
3480 w = (SciPlotWidget) wi;
3481 if (color < w->plot.num_colors)
3482 w->plot.ForegroundColor = color;
3483 }
3484
3485 void
SciPlotListDelete(Widget wi,int idnum)3486 SciPlotListDelete (Widget wi, int idnum)
3487 {
3488 SciPlotList *p;
3489 SciPlotWidget w;
3490
3491 if (!XtIsSciPlot(wi))
3492 return;
3493
3494 w = (SciPlotWidget) wi;
3495
3496 p = _ListFind(w, idnum);
3497 if (p)
3498 _ListDelete(p);
3499 }
3500
3501 int
SciPlotListCreateFromData(Widget wi,int num,real * xlist,real * ylist,char * legend,int pcolor,int pstyle,int lcolor,int lstyle)3502 SciPlotListCreateFromData (Widget wi, int num, real *xlist, real *ylist, char *legend, int pcolor, int pstyle, int lcolor, int lstyle)
3503 {
3504 int idnum;
3505 SciPlotList *p;
3506 SciPlotWidget w;
3507
3508 if (!XtIsSciPlot(wi))
3509 return -1;
3510
3511 w = (SciPlotWidget) wi;
3512
3513 idnum = _ListNew(w);
3514 p = w->plot.plotlist + idnum;
3515 _ListSetReal(p, num, xlist, ylist);
3516 _ListSetLegend(p, legend);
3517 _ListSetStyle(p, pcolor, pstyle, lcolor, lstyle);
3518 return idnum;
3519 }
3520
3521 int
SciPlotListCreateFloat(Widget wi,int num,float * xlist,float * ylist,char * legend)3522 SciPlotListCreateFloat (Widget wi, int num, float *xlist, float *ylist, char *legend)
3523 {
3524 int idnum;
3525 SciPlotList *p;
3526 SciPlotWidget w;
3527
3528 if (!XtIsSciPlot(wi))
3529 return -1;
3530
3531 w = (SciPlotWidget) wi;
3532
3533 idnum = _ListNew(w);
3534 p = w->plot.plotlist + idnum;
3535 _ListSetFloat(p, num, xlist, ylist);
3536 _ListSetLegend(p, legend);
3537 _ListSetStyle(p, 1, XtMARKER_CIRCLE, 1, XtLINE_SOLID);
3538 return idnum;
3539 }
3540
3541 void
SciPlotListUpdateFloat(Widget wi,int idnum,int num,float * xlist,float * ylist)3542 SciPlotListUpdateFloat (Widget wi, int idnum, int num, float *xlist, float *ylist)
3543 {
3544 SciPlotList *p;
3545 SciPlotWidget w;
3546
3547 if (!XtIsSciPlot(wi))
3548 return;
3549
3550 w = (SciPlotWidget) wi;
3551
3552 p = _ListFind(w, idnum);
3553 if (p)
3554 _ListSetFloat(p, num, xlist, ylist);
3555 }
3556
3557 void
SciPlotListAddFloat(Widget wi,int idnum,int num,float * xlist,float * ylist)3558 SciPlotListAddFloat (Widget wi, int idnum, int num, float *xlist, float *ylist)
3559 {
3560 SciPlotList *p;
3561 SciPlotWidget w;
3562
3563 if (!XtIsSciPlot(wi))
3564 return;
3565
3566 w = (SciPlotWidget) wi;
3567
3568 p = _ListFind(w, idnum);
3569 if (p)
3570 _ListAddFloat(p, num, xlist, ylist);
3571 }
3572
3573 int
SciPlotListCreateDouble(Widget wi,int num,double * xlist,double * ylist,char * legend)3574 SciPlotListCreateDouble (Widget wi, int num, double *xlist, double *ylist, char *legend)
3575 {
3576 int idnum;
3577 SciPlotList *p;
3578 SciPlotWidget w;
3579
3580 if (!XtIsSciPlot(wi))
3581 return -1;
3582
3583 w = (SciPlotWidget) wi;
3584
3585 idnum = _ListNew(w);
3586 p = w->plot.plotlist + idnum;
3587 _ListSetDouble(p, num, xlist, ylist);
3588 _ListSetLegend(p, legend);
3589 _ListSetStyle(p, 1, XtMARKER_CIRCLE, 1, XtLINE_SOLID);
3590 return idnum;
3591 }
3592
3593 void
SciPlotListUpdateDouble(Widget wi,int idnum,int num,double * xlist,double * ylist)3594 SciPlotListUpdateDouble (Widget wi, int idnum, int num, double *xlist, double *ylist)
3595 {
3596 SciPlotList *p;
3597 SciPlotWidget w;
3598
3599 if (!XtIsSciPlot(wi))
3600 return;
3601
3602 w = (SciPlotWidget) wi;
3603
3604 p = _ListFind(w, idnum);
3605 if (p)
3606 _ListSetDouble(p, num, xlist, ylist);
3607 }
3608
3609 void
SciPlotListAddDouble(Widget wi,int idnum,int num,double * xlist,double * ylist)3610 SciPlotListAddDouble (Widget wi, int idnum, int num, double *xlist, double *ylist)
3611 {
3612 SciPlotList *p;
3613 SciPlotWidget w;
3614
3615 if (!XtIsSciPlot(wi))
3616 return;
3617
3618 w = (SciPlotWidget) wi;
3619
3620 p = _ListFind(w, idnum);
3621 if (p)
3622 _ListAddDouble(p, num, xlist, ylist);
3623 }
3624
3625 void
SciPlotListSetStyle(Widget wi,int idnum,int pcolor,int pstyle,int lcolor,int lstyle)3626 SciPlotListSetStyle (Widget wi, int idnum, int pcolor, int pstyle, int lcolor, int lstyle)
3627 {
3628 SciPlotList *p;
3629 SciPlotWidget w;
3630
3631 if (!XtIsSciPlot(wi))
3632 return;
3633
3634 w = (SciPlotWidget) wi;
3635
3636 p = _ListFind(w, idnum);
3637 if (p)
3638 _ListSetStyle(p, pcolor, pstyle, lcolor, lstyle);
3639 }
3640
3641 void
SciPlotListSetMarkerSize(Widget wi,int idnum,float size)3642 SciPlotListSetMarkerSize (Widget wi, int idnum, float size)
3643 {
3644 SciPlotList *p;
3645 SciPlotWidget w;
3646
3647 if (!XtIsSciPlot(wi))
3648 return;
3649
3650 w = (SciPlotWidget) wi;
3651
3652 p = _ListFind(w, idnum);
3653 if (p)
3654 p->markersize=size;
3655 }
3656
3657 void
SciPlotSetXAutoScale(Widget wi)3658 SciPlotSetXAutoScale (Widget wi)
3659 {
3660 SciPlotWidget w;
3661
3662 if (!XtIsSciPlot(wi))
3663 return;
3664
3665 w = (SciPlotWidget) wi;
3666 w->plot.XAutoScale = True;
3667 }
3668
3669 void
SciPlotSetXUserScale(Widget wi,double min,double max)3670 SciPlotSetXUserScale (Widget wi, double min, double max)
3671 {
3672 SciPlotWidget w;
3673
3674 if (!XtIsSciPlot(wi))
3675 return;
3676
3677 w = (SciPlotWidget) wi;
3678 if (min < max) {
3679 w->plot.XAutoScale = False;
3680 w->plot.UserMin.x = (real) min;
3681 w->plot.UserMax.x = (real) max;
3682 }
3683 }
3684
3685 void
SciPlotSetYAutoScale(Widget wi)3686 SciPlotSetYAutoScale (Widget wi)
3687 {
3688 SciPlotWidget w;
3689
3690 if (!XtIsSciPlot(wi))
3691 return;
3692
3693 w = (SciPlotWidget) wi;
3694 w->plot.YAutoScale = True;
3695 }
3696
3697 void
SciPlotSetYUserScale(Widget wi,double min,double max)3698 SciPlotSetYUserScale (Widget wi, double min, double max)
3699 {
3700 SciPlotWidget w;
3701
3702 if (!XtIsSciPlot(wi))
3703 return;
3704
3705 w = (SciPlotWidget) wi;
3706 if (min < max) {
3707 w->plot.YAutoScale = False;
3708 w->plot.UserMin.y = (real) min;
3709 w->plot.UserMax.y = (real) max;
3710 }
3711 }
3712
3713 void
SciPlotPrintStatistics(Widget wi)3714 SciPlotPrintStatistics (Widget wi)
3715 {
3716 int i, j;
3717 SciPlotList *p;
3718 SciPlotWidget w;
3719
3720 if (!XtIsSciPlot(wi))
3721 return;
3722
3723 w = (SciPlotWidget) wi;
3724
3725 printf("Title=%s\nxlabel=%s\tylabel=%s\n",
3726 w->plot.plotTitle, w->plot.xlabel, w->plot.ylabel);
3727 printf("ChartType=%d\n", w->plot.ChartType);
3728 printf("Degrees=%d\n", w->plot.Degrees);
3729 printf("XLog=%d\tYLog=%d\n", w->plot.XLog, w->plot.YLog);
3730 printf("XAutoScale=%d\tYAutoScale=%d\n",
3731 w->plot.XAutoScale, w->plot.YAutoScale);
3732 for (i = 0; i < w->plot.num_plotlist; i++) {
3733 p = w->plot.plotlist + i;
3734 if (p->draw) {
3735 printf("\nLegend=%s\n", p->legend);
3736 printf("Styles: point=%d line=%d Color: point=%d line=%d\n",
3737 p->PointStyle, p->LineStyle, p->PointColor, p->LineColor);
3738 for (j = 0; j < p->number; j++)
3739 printf("%f\t%f\n", p->data[j].x, p->data[j].y);
3740 printf("\n");
3741 }
3742 }
3743 }
3744
3745 void
SciPlotExportData(Widget wi,FILE * fd)3746 SciPlotExportData (Widget wi, FILE *fd)
3747 {
3748 int i, j;
3749 SciPlotList *p;
3750 SciPlotWidget w;
3751
3752 if (!XtIsSciPlot(wi))
3753 return;
3754
3755 w = (SciPlotWidget) wi;
3756
3757 fprintf(fd, "Title=\"%s\"\n", w->plot.plotTitle);
3758 fprintf(fd, "Xaxis=\"%s\"\n", w->plot.xlabel);
3759 fprintf(fd, "Yaxis=\"%s\"\n\n", w->plot.ylabel);
3760 for (i = 0; i < w->plot.num_plotlist; i++) {
3761 p = w->plot.plotlist + i;
3762 if (p->draw) {
3763 fprintf(fd, "Line=\"%s\"\n",p->legend);
3764 for (j = 0; j < p->number; j++)
3765 fprintf(fd, "%e\t%e\n", p->data[j].x, p->data[j].y);
3766 fprintf(fd, "\n");
3767 }
3768 }
3769 }
3770
3771 int
SciPlotStoreAllocatedColor(Widget wi,Pixel p)3772 SciPlotStoreAllocatedColor(Widget wi, Pixel p)
3773 {
3774 SciPlotWidget w;
3775
3776 if (!XtIsSciPlot(wi))
3777 return -1;
3778
3779 w = (SciPlotWidget) wi;
3780
3781 return ColorStore(w, p);
3782 }
3783
3784 void
SciPlotUpdate(Widget wi)3785 SciPlotUpdate (Widget wi)
3786 {
3787 SciPlotWidget w;
3788
3789 if (!XtIsSciPlot(wi))
3790 return;
3791
3792 w = (SciPlotWidget) wi;
3793 EraseAll(w);
3794 #ifdef DEBUG_SCIPLOT
3795 SciPlotPrintStatistics(w);
3796 #endif
3797 ComputeAll(w);
3798 DrawAll(w);
3799 }
3800
3801 Boolean
SciPlotQuickUpdate(Widget wi)3802 SciPlotQuickUpdate (Widget wi)
3803 {
3804 SciPlotWidget w;
3805
3806 if (!XtIsSciPlot(wi))
3807 return False;
3808
3809 w = (SciPlotWidget) wi;
3810 return DrawQuick(w);
3811 }
3812