~ubuntu-branches/ubuntu/karmic/python-scipy/karmic

« back to all changes in this revision

Viewing changes to Lib/xplt/src/gist/draw0.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel T. Chen (new)
  • Date: 2005-03-16 02:15:29 UTC
  • Revision ID: james.westby@ubuntu.com-20050316021529-xrjlowsejs0cijig
Tags: upstream-0.3.2
ImportĀ upstreamĀ versionĀ 0.3.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
   DRAW0.C
 
3
   Virtual functions for Drauing class.
 
4
 
 
5
   $Id: draw0.c,v 1.1 2003/03/08 15:26:45 travo Exp $
 
6
 */
 
7
/*    Copyright (c) 1994.  The Regents of the University of California.
 
8
                    All rights reserved.  */
 
9
 
 
10
#include "draw.h"
 
11
#include "gtext.h"
 
12
#include "play.h"
 
13
#include "pstdlib.h"
 
14
 
 
15
extern char *strcpy(char *, const char *);
 
16
 
 
17
extern double log10(double);
 
18
#define SAFELOG0 (-999.)
 
19
#define SAFELOG(x) ((x)>0? log10(x) : ((x)<0? log10(-(x)) : -999.))
 
20
 
 
21
extern void Gd_KillRing(void *elv);
 
22
 
 
23
static void KillElement(GdElement *el);
 
24
static void LinesKill(void *el);
 
25
static void DisjointKill(void *el);
 
26
static void TextKill(void *el);
 
27
static void CellsKill(void *el);
 
28
static void PolysKill(void *el);
 
29
static void MeshKill(void *el);
 
30
static void FilledKill(void *el);
 
31
static void VectorsKill(void *el);
 
32
static void KillConGrps(GeLines **grps, int ngrps);
 
33
static void ContoursKill(void *el);
 
34
static void SystemKill(void *el);
 
35
extern void Gd_KillMeshXY(void *vMeshEl);
 
36
 
 
37
static int LinesGet(void *el);
 
38
static int DisjointGet(void *el);
 
39
static int TextGet(void *el);
 
40
static int CellsGet(void *el);
 
41
static int PolysGet(void *el);
 
42
static int MeshGet(void *el);
 
43
static int FilledGet(void *el);
 
44
static int VectorsGet(void *el);
 
45
static int ContoursGet(void *el);
 
46
static int SystemGet(void *el);
 
47
extern void Gd_MeshXYGet(void *vMeshEl);
 
48
 
 
49
static int LinesSet(void *el, int xyzChanged);
 
50
extern void Gd_LinesSubSet(void *el);
 
51
static int DisjointSet(void *el, int xyzChanged);
 
52
static int TextSet(void *el, int xyzChanged);
 
53
static int CellsSet(void *el, int xyzChanged);
 
54
static int PolysSet(void *el, int xyzChanged);
 
55
static void MeshXYSet(void *vMeshEl, int xyzChanged);
 
56
static int MeshSet(void *el, int xyzChanged);
 
57
static int FilledSet(void *el, int xyzChanged);
 
58
static int VectorsSet(void *el, int xyzChanged);
 
59
static int ContoursSet(void *el, int xyzChanged);
 
60
static int SystemSet(void *el, int xyzChanged);
 
61
 
 
62
static int LinesDraw(void *el, int xIsLog, int yIsLog);
 
63
static int DisjointDraw(void *el, int xIsLog, int yIsLog);
 
64
static int TextDraw(void *el, int xIsLog, int yIsLog);
 
65
static int CellsDraw(void *el, int xIsLog, int yIsLog);
 
66
static int PolysDraw(void *el, int xIsLog, int yIsLog);
 
67
static void MeshDrawSet(GaQuadMesh *mesh, void *vMeshEl,
 
68
                        int xIsLog, int yIsLog);
 
69
static int MeshDraw(void *el, int xIsLog, int yIsLog);
 
70
static int FilledDraw(void *el, int xIsLog, int yIsLog);
 
71
static int VectorsDraw(void *el, int xIsLog, int yIsLog);
 
72
static int ContoursDraw(void *el, int xIsLog, int yIsLog);
 
73
static int SystemDraw(void *el, int xIsLog, int yIsLog);
 
74
 
 
75
static int LinesScan(void *el, int flags, GpBox *limits);
 
76
static int DisjointScan(void *el, int flags, GpBox *limits);
 
77
static int TextScan(void *el, int flags, GpBox *limits);
 
78
static int CellsScan(void *el, int flags, GpBox *limits);
 
79
static int PolysScan(void *el, int flags, GpBox *limits);
 
80
static int MeshXYScan(void *vMeshEl, int flags, GpBox *limits, GpBox *box);
 
81
static int MeshScan(void *el, int flags, GpBox *limits);
 
82
static int FilledScan(void *el, int flags, GpBox *limits);
 
83
static int VectorsScan(void *el, int flags, GpBox *limits);
 
84
static int ContoursScan(void *el, int flags, GpBox *limits);
 
85
static int SystemScan(void *el, int flags, GpBox *limits);
 
86
 
 
87
static void NoMargin(void *el, GpBox *margin);
 
88
static void LinesMargin(void *el, GpBox *margin);
 
89
static void DisjointMargin(void *el, GpBox *margin);
 
90
static void TextMargin(void *el, GpBox *margin);
 
91
static void MeshMargin(void *el, GpBox *margin);
 
92
static void VectorsMargin(void *el, GpBox *margin);
 
93
static void ContoursMargin(void *el, GpBox *margin);
 
94
 
 
95
extern void Gd_ScanZ(long n, const GpReal *z, GpReal *zmin, GpReal *zmax);
 
96
static int ScanMn(long n, GpReal *x, GpReal *y, GpReal ymin,
 
97
                  GpReal *xmin, GpReal *xmax);
 
98
static int ScanMx(long n, GpReal *x, GpReal *y, GpReal ymax,
 
99
                  GpReal *xmin, GpReal *xmax);
 
100
static int ScanMnMx(long n, GpReal *x, GpReal *y, GpReal ymin, GpReal ymax,
 
101
                    GpReal *xmin, GpReal *xmax);
 
102
static void ScanRXY(long n, GpReal *x, GpReal *y,
 
103
                    int flags, GpBox *limits, GpBox *box);
 
104
static int GetLogZ(long n, GpReal *z, GpReal **zlog,
 
105
                   GpReal *zmin, GpReal *zmax);
 
106
static int Get_LogZ(long n, long nndc, GpReal *z, GpReal **zlog,
 
107
                    GpReal *zmin, GpReal *zmax);
 
108
 
 
109
extern int Gd_MakeContours(GeContours *con);
 
110
extern int Gd_DrawRing(void *elv, int xIsLog, int yIsLog,
 
111
                       GeSystem *sys, int t);
 
112
extern void Gd_NextMeshBlock(long *ii, long *jj, long len, long iMax,
 
113
                             int *reg, int region);
 
114
 
 
115
/* ------------------------------------------------------------------------ */
 
116
/* Set virtual function tables */
 
117
 
 
118
extern GdOpTable *GetDrawingOpTables(void);
 
119
static GdOpTable opTables[E_SYSTEM+1]= {
 
120
  { E_NONE, 0, 0, 0, 0, 0, 0 },
 
121
  { E_LINES, &LinesKill, &LinesGet, &LinesSet,
 
122
      &LinesDraw, &LinesScan, &LinesMargin },
 
123
  { E_DISJOINT, &DisjointKill, &DisjointGet, &DisjointSet,
 
124
      &DisjointDraw, &DisjointScan, &DisjointMargin },
 
125
  { E_TEXT, &TextKill, &TextGet, &TextSet,
 
126
      &TextDraw, &TextScan, &TextMargin },
 
127
  { E_MESH, &MeshKill, &MeshGet, &MeshSet,
 
128
      &MeshDraw, &MeshScan, &MeshMargin },
 
129
  { E_FILLED, &FilledKill, &FilledGet, &FilledSet,
 
130
      &FilledDraw, &FilledScan, &NoMargin },
 
131
  { E_VECTORS, &VectorsKill, &VectorsGet, &VectorsSet,
 
132
      &VectorsDraw, &VectorsScan, &VectorsMargin },
 
133
  { E_CONTOURS, &ContoursKill, &ContoursGet, &ContoursSet,
 
134
      &ContoursDraw, &ContoursScan, &ContoursMargin },
 
135
  { E_CELLS, &CellsKill, &CellsGet, &CellsSet,
 
136
      &CellsDraw, &CellsScan, &NoMargin },
 
137
  { E_POLYS, &PolysKill, &PolysGet, &PolysSet,
 
138
      &PolysDraw, &PolysScan, &NoMargin },
 
139
  { E_SYSTEM, &SystemKill, &SystemGet, &SystemSet,
 
140
      &SystemDraw, &SystemScan, &NoMargin }
 
141
};
 
142
 
 
143
/* this is called at the first call to GdNewDrawing */
 
144
GdOpTable *GetDrawingOpTables(void)
 
145
{
 
146
  return opTables;
 
147
}
 
148
 
 
149
/* ------------------------------------------------------------------------ */
 
150
/* Destructors for drawing elements are private, accessed via the
 
151
   Kill virtual function */
 
152
 
 
153
void Gd_KillRing(void *elv)
 
154
{
 
155
  GdElement *el, *next= elv;
 
156
  while ((el= next)) {
 
157
    next= el->next;
 
158
    if (el == next) next= 0;
 
159
    el->ops->Kill(el);
 
160
  }
 
161
}
 
162
 
 
163
static void KillElement(GdElement *el)
 
164
{
 
165
  GdElement *next= el->next;
 
166
  if (el->legend) p_free(el->legend);
 
167
  if (next) {
 
168
    if (next==el) next= 0;
 
169
    else { next->prev= el->prev;   el->prev->next= next; }
 
170
  }
 
171
  p_free(el);
 
172
  return;
 
173
}
 
174
 
 
175
static void LinesKill(void *el)
 
176
{
 
177
  GeLines *lines= el;
 
178
  if (lines->x) p_free(lines->x);
 
179
  if (lines->y) p_free(lines->y);
 
180
  if (lines->xlog) p_free(lines->xlog);
 
181
  if (lines->ylog) p_free(lines->ylog);
 
182
  KillElement(el);
 
183
}
 
184
 
 
185
static void DisjointKill(void *el)
 
186
{
 
187
  GeDisjoint *lines= el;
 
188
  if (lines->x) p_free(lines->x);
 
189
  if (lines->y) p_free(lines->y);
 
190
  if (lines->xlog) p_free(lines->xlog);
 
191
  if (lines->ylog) p_free(lines->ylog);
 
192
  if (lines->xq) p_free(lines->xq);
 
193
  if (lines->yq) p_free(lines->yq);
 
194
  if (lines->xqlog) p_free(lines->xqlog);
 
195
  if (lines->yqlog) p_free(lines->yqlog);
 
196
  KillElement(el);
 
197
}
 
198
 
 
199
static void TextKill(void *el)
 
200
{
 
201
  GeText *text= el;
 
202
  if (text->text) p_free(text->text);
 
203
  KillElement(el);
 
204
}
 
205
 
 
206
static void CellsKill(void *el)
 
207
{
 
208
  GeCells *cells= el;
 
209
  if (cells->colors) p_free(cells->colors);
 
210
  KillElement(el);
 
211
}
 
212
 
 
213
static void PolysKill(void *el)
 
214
{
 
215
  GePolys *polys= el;
 
216
  if (polys->x) p_free(polys->x);
 
217
  if (polys->y) p_free(polys->y);
 
218
  if (polys->xlog) p_free(polys->xlog);
 
219
  if (polys->ylog) p_free(polys->ylog);
 
220
  if (polys->pn) p_free(polys->pn);
 
221
  if (polys->colors) p_free(polys->colors);
 
222
  KillElement(el);
 
223
}
 
224
 
 
225
static void MeshKill(void *el)
 
226
{
 
227
  Gd_KillMeshXY(el);
 
228
  KillElement(el);
 
229
}
 
230
 
 
231
static void FilledKill(void *el)
 
232
{
 
233
  GeFill *fill= el;
 
234
  Gd_KillMeshXY(el);
 
235
  if (fill->colors) {
 
236
    if (!(fill->noCopy&NOCOPY_COLORS)) p_free(fill->colors);
 
237
    else if (GdFree) GdFree(fill->colors);
 
238
  }
 
239
  KillElement(el);
 
240
}
 
241
 
 
242
static void VectorsKill(void *el)
 
243
{
 
244
  GeVectors *vec= el;
 
245
  Gd_KillMeshXY(el);
 
246
  if (!(vec->noCopy&NOCOPY_UV)) {
 
247
    if (vec->u) p_free(vec->u);
 
248
    if (vec->v) p_free(vec->v);
 
249
  } else if (GdFree) {
 
250
    if (vec->u) GdFree(vec->u);
 
251
    if (vec->v) GdFree(vec->v);
 
252
  }
 
253
  KillElement(el);
 
254
}
 
255
 
 
256
static void KillConGrps(GeLines **grps, int ngrps)
 
257
{
 
258
  int i;
 
259
  for (i=0 ; i<ngrps ; i++) { Gd_KillRing(grps[i]);  grps[i]= 0; }
 
260
}
 
261
 
 
262
static void ContoursKill(void *el)
 
263
{
 
264
  GeContours *con= el;
 
265
  Gd_KillMeshXY(el);
 
266
  if (con->z) {
 
267
    if (!(con->noCopy&NOCOPY_Z)) p_free(con->z);
 
268
    else if (GdFree) GdFree(con->z);
 
269
  }
 
270
  if (con->levels) p_free(con->levels);
 
271
  if (con->groups) {
 
272
    KillConGrps(con->groups, con->nLevels);
 
273
    p_free(con->groups);
 
274
  }
 
275
  KillElement(el);
 
276
}
 
277
 
 
278
static void SystemKill(void *el)
 
279
{
 
280
  GeSystem *sys= el;
 
281
  Gd_KillRing(sys->elements);
 
282
  KillElement(el);
 
283
}
 
284
 
 
285
void Gd_KillMeshXY(void *vMeshEl)
 
286
{
 
287
  GeMesh *meshEl= vMeshEl;
 
288
  GaQuadMesh *mesh= &meshEl->mesh;
 
289
  int noCopy= meshEl->noCopy;
 
290
  if (!(noCopy&NOCOPY_MESH)) {
 
291
    if (mesh->x) p_free(mesh->x);
 
292
    if (mesh->y) p_free(mesh->y);
 
293
  } else if (GdFree) {
 
294
    if (mesh->x) GdFree(mesh->x);
 
295
    if (mesh->y) GdFree(mesh->y);
 
296
  }
 
297
  if (mesh->reg) {
 
298
    if (!(noCopy&NOCOPY_REG)) p_free(mesh->reg);
 
299
    else if (GdFree) GdFree(mesh->reg);
 
300
  }
 
301
  if (mesh->triangle) {
 
302
    if (!(noCopy&NOCOPY_TRI)) p_free(mesh->triangle);
 
303
    else if (GdFree) GdFree(mesh->triangle);
 
304
  }
 
305
}
 
306
 
 
307
/* ------------------------------------------------------------------------ */
 
308
/* GetProps virtual function loads gistA, gistD from GdElement */
 
309
 
 
310
static int LinesGet(void *el)
 
311
{
 
312
  GeLines *e= el;
 
313
  gistD.hidden= e->el.hidden;
 
314
  gistD.legend= e->el.legend;
 
315
  gistD.n= e->n;
 
316
  gistD.x= e->x;
 
317
  gistD.y= e->y;
 
318
  gistA.l= e->l;
 
319
  gistA.dl= e->dl;
 
320
  gistA.m= e->m;
 
321
  return E_LINES;
 
322
}
 
323
 
 
324
static int DisjointGet(void *el)
 
325
{
 
326
  GeDisjoint *e= el;
 
327
  gistD.hidden= e->el.hidden;
 
328
  gistD.legend= e->el.legend;
 
329
  gistD.n= e->n;
 
330
  gistD.x= e->x;
 
331
  gistD.y= e->y;
 
332
  gistD.xq= e->xq;
 
333
  gistD.yq= e->yq;
 
334
  gistA.l= e->l;
 
335
  return E_DISJOINT;
 
336
}
 
337
 
 
338
static int TextGet(void *el)
 
339
{
 
340
  GeText *e= el;
 
341
  gistD.hidden= e->el.hidden;
 
342
  gistD.legend= e->el.legend;
 
343
  gistD.x0= e->x0;
 
344
  gistD.y0= e->y0;
 
345
  gistD.text= e->text;
 
346
  gistA.t= e->t;
 
347
  return E_TEXT;
 
348
}
 
349
 
 
350
static int CellsGet(void *el)
 
351
{
 
352
  GeCells *e= el;
 
353
  gistD.hidden= e->el.hidden;
 
354
  gistD.legend= e->el.legend;
 
355
  gistD.px= e->px;
 
356
  gistD.py= e->py;
 
357
  gistD.qx= e->qx;
 
358
  gistD.qy= e->qy;
 
359
  gistD.width= e->width;
 
360
  gistD.height= e->height;
 
361
  gistD.colors= e->colors;
 
362
  gistA.rgb = e->rgb;
 
363
  return E_CELLS;
 
364
}
 
365
 
 
366
static int PolysGet(void *el)
 
367
{
 
368
  GePolys *e= el;
 
369
  gistD.hidden= e->el.hidden;
 
370
  gistD.legend= e->el.legend;
 
371
  gistD.n= e->n;
 
372
  gistD.x= e->x;
 
373
  gistD.y= e->y;
 
374
  gistD.pn= e->pn;
 
375
  gistD.colors= e->colors;
 
376
  gistA.e = e->e;
 
377
  gistA.rgb = e->rgb;
 
378
  return E_POLYS;
 
379
}
 
380
 
 
381
static int MeshGet(void *el)
 
382
{
 
383
  GeMesh *e= el;
 
384
  Gd_MeshXYGet(el);
 
385
  gistD.hidden= e->el.hidden;
 
386
  gistD.legend= e->el.legend;
 
387
  gistD.boundary= e->boundary;
 
388
  gistD.inhibit= e->inhibit;
 
389
  gistA.l= e->l;
 
390
  return E_MESH;
 
391
}
 
392
 
 
393
static int FilledGet(void *el)
 
394
{
 
395
  GeFill *e= el;
 
396
  Gd_MeshXYGet(el);
 
397
  gistD.hidden= e->el.hidden;
 
398
  gistD.legend= e->el.legend;
 
399
  gistD.nColumns= e->nColumns;
 
400
  gistD.colors= e->colors;
 
401
  gistA.e= e->e;
 
402
  gistA.rgb = e->rgb;
 
403
  return E_FILLED;
 
404
}
 
405
 
 
406
static int VectorsGet(void *el)
 
407
{
 
408
  GeVectors *e= el;
 
409
  Gd_MeshXYGet(el);
 
410
  gistD.hidden= e->el.hidden;
 
411
  gistD.legend= e->el.legend;
 
412
  gistD.u= e->u;
 
413
  gistD.v= e->v;
 
414
  gistD.scale= e->scale;
 
415
  gistA.l= e->l;
 
416
  gistA.f= e->f;
 
417
  gistA.vect= e->vect;
 
418
  return E_VECTORS;
 
419
}
 
420
 
 
421
static int ContoursGet(void *el)
 
422
{
 
423
  GeContours *e= el;
 
424
  Gd_MeshXYGet(el);
 
425
  gistD.hidden= e->el.hidden;
 
426
  gistD.legend= e->el.legend;
 
427
  gistD.z= e->z;
 
428
  gistD.nLevels= e->nLevels;
 
429
  gistD.levels= e->levels;
 
430
  gistA.l= e->l;
 
431
  gistA.dl= e->dl;
 
432
  gistA.m= e->m;
 
433
  return E_CONTOURS;
 
434
}
 
435
 
 
436
static int SystemGet(void *el)
 
437
{
 
438
  GeSystem *e= el;
 
439
  gistD.hidden= e->el.hidden;
 
440
  gistD.legend= e->el.legend;
 
441
  return E_SYSTEM;
 
442
}
 
443
 
 
444
void Gd_MeshXYGet(void *vMeshEl)
 
445
{
 
446
  GeMesh *meshEl= vMeshEl;
 
447
  GaQuadMesh *mesh= &meshEl->mesh;
 
448
  gistD.noCopy= meshEl->noCopy;
 
449
  gistD.mesh.iMax= mesh->iMax;
 
450
  gistD.mesh.jMax= mesh->jMax;
 
451
  gistD.mesh.x= mesh->x;
 
452
  gistD.mesh.y= mesh->y;
 
453
  gistD.mesh.reg= mesh->reg;
 
454
  gistD.mesh.triangle= mesh->triangle;
 
455
  gistD.region= meshEl->region;
 
456
}
 
457
 
 
458
/* ------------------------------------------------------------------------ */
 
459
/* SetProps virtual function loads GdElement from gistA, gistD */
 
460
 
 
461
static int LinesSet(void *el, int xyzChanged)
 
462
{
 
463
  GeLines *e= el;
 
464
  Gd_LinesSubSet(el);
 
465
  e->el.legend= gistD.legend;
 
466
  if (xyzChanged & CHANGE_XY) {
 
467
    e->n= gistD.n;
 
468
    e->x= gistD.x;
 
469
    e->y= gistD.y;
 
470
    if (e->xlog) { p_free(e->xlog); e->xlog= 0; }
 
471
    if (e->ylog) { p_free(e->ylog); e->ylog= 0; }
 
472
  }
 
473
  return 0;
 
474
}
 
475
 
 
476
void Gd_LinesSubSet(void *el)
 
477
{
 
478
  GeLines *e= el;
 
479
  e->el.hidden= gistD.hidden;
 
480
  e->l= gistA.l;
 
481
  e->dl= gistA.dl;
 
482
  e->m= gistA.m;
 
483
}
 
484
 
 
485
static int DisjointSet(void *el, int xyzChanged)
 
486
{
 
487
  GeDisjoint *e= el;
 
488
  e->el.hidden= gistD.hidden;
 
489
  e->el.legend= gistD.legend;
 
490
  e->n= gistD.n;
 
491
  e->x= gistD.x;
 
492
  e->y= gistD.y;
 
493
  e->xq= gistD.xq;
 
494
  e->yq= gistD.yq;
 
495
  e->l= gistA.l;
 
496
  if (xyzChanged & CHANGE_XY) {
 
497
    if (e->xlog) { p_free(e->xlog); e->xlog= 0; }
 
498
    if (e->ylog) { p_free(e->ylog); e->ylog= 0; }
 
499
    if (e->xqlog) { p_free(e->xqlog); e->xqlog= 0; }
 
500
    if (e->yqlog) { p_free(e->yqlog); e->yqlog= 0; }
 
501
  }
 
502
  return 0;
 
503
}
 
504
 
 
505
/* ARGSUSED */
 
506
static int TextSet(void *el, int xyzChanged)
 
507
{
 
508
  GeText *e= el;
 
509
  e->el.hidden= gistD.hidden;
 
510
  e->el.legend= gistD.legend;
 
511
  e->x0= gistD.x0;
 
512
  e->y0= gistD.y0;
 
513
  e->text= gistD.text;
 
514
  e->t= gistA.t;
 
515
  return 0;
 
516
}
 
517
 
 
518
/* ARGSUSED */
 
519
static int CellsSet(void *el, int xyzChanged)
 
520
{
 
521
  GeCells *e= el;
 
522
  e->el.hidden= gistD.hidden;
 
523
  e->el.legend= gistD.legend;
 
524
  e->px= gistD.px;
 
525
  e->py= gistD.py;
 
526
  e->qx= gistD.qx;
 
527
  e->qy= gistD.qy;
 
528
  e->width= gistD.width;
 
529
  e->height= gistD.height;
 
530
  e->colors= gistD.colors;
 
531
  return 0;
 
532
}
 
533
 
 
534
static int PolysSet(void *el, int xyzChanged)
 
535
{
 
536
  GePolys *e= el;
 
537
  Gd_LinesSubSet(el);
 
538
  e->el.legend= gistD.legend;
 
539
  if (xyzChanged & CHANGE_XY) {
 
540
    e->n= gistD.n;
 
541
    e->x= gistD.x;
 
542
    e->y= gistD.y;
 
543
    if (e->xlog) { p_free(e->xlog); e->xlog= 0; }
 
544
    if (e->ylog) { p_free(e->ylog); e->ylog= 0; }
 
545
  }
 
546
  e->pn= gistD.pn;
 
547
  e->colors= gistD.colors;
 
548
  return 0;
 
549
}
 
550
 
 
551
static void MeshXYSet(void *vMeshEl, int xyzChanged)
 
552
{
 
553
  GeMesh *meshEl= vMeshEl;
 
554
  GaQuadMesh *mesh= &meshEl->mesh;
 
555
  meshEl->el.legend= gistD.legend;
 
556
  meshEl->el.hidden= gistD.hidden;
 
557
  meshEl->noCopy= gistD.noCopy;
 
558
  mesh->iMax= gistD.mesh.iMax;
 
559
  mesh->jMax= gistD.mesh.jMax;
 
560
  mesh->x= gistD.mesh.x;
 
561
  mesh->y= gistD.mesh.y;
 
562
  mesh->reg= gistD.mesh.reg;
 
563
  mesh->triangle= gistD.mesh.triangle;
 
564
  if (xyzChanged & CHANGE_XY) {
 
565
    if (meshEl->xlog) { p_free(meshEl->xlog); meshEl->xlog= 0; }
 
566
    if (meshEl->ylog) { p_free(meshEl->ylog); meshEl->ylog= 0; }
 
567
  }
 
568
  meshEl->region= gistD.region;
 
569
}
 
570
 
 
571
static int MeshSet(void *el, int xyzChanged)
 
572
{
 
573
  GeMesh *e= el;
 
574
  MeshXYSet(el, xyzChanged);
 
575
  e->boundary= gistD.boundary;
 
576
  e->inhibit= gistD.inhibit;
 
577
  e->l= gistA.l;
 
578
  return 0;
 
579
}
 
580
 
 
581
static int FilledSet(void *el, int xyzChanged)
 
582
{
 
583
  GeFill *e= el;
 
584
  MeshXYSet(el, xyzChanged);
 
585
  e->nColumns= gistD.nColumns;
 
586
  e->colors= gistD.colors;
 
587
  e->e= gistA.e;
 
588
  return 0;
 
589
}
 
590
 
 
591
static int VectorsSet(void *el, int xyzChanged)
 
592
{
 
593
  GeVectors *e= el;
 
594
  MeshXYSet(el, xyzChanged);
 
595
  e->u= gistD.u;
 
596
  e->v= gistD.v;
 
597
  e->scale= gistD.scale;
 
598
  e->l= gistA.l;
 
599
  e->f= gistA.f;
 
600
  e->vect= gistA.vect;
 
601
  return 0;
 
602
}
 
603
 
 
604
static int ContoursSet(void *el, int xyzChanged)
 
605
{
 
606
  GeContours *e= el;
 
607
  int oldN= e->nLevels;
 
608
  MeshXYSet(el, xyzChanged);
 
609
  e->z= gistD.z;
 
610
  e->nLevels= gistD.nLevels;
 
611
  e->levels= gistD.levels;
 
612
  e->l= gistA.l;
 
613
  e->dl= gistA.dl;
 
614
  e->m= gistA.m;
 
615
  if (xyzChanged & CHANGE_Z) {
 
616
    if (e->groups) {
 
617
      KillConGrps(e->groups, oldN);
 
618
      if (oldN!=gistD.nLevels) {
 
619
        p_free(e->groups);
 
620
        e->groups= 0;
 
621
      }
 
622
    }
 
623
    if (gistD.nLevels>0) {
 
624
      if (!e->groups)
 
625
        e->groups= (GeLines **)p_malloc(sizeof(GeLines *)*gistD.nLevels);
 
626
      if (!e->groups || Gd_MakeContours(e)) return 1;
 
627
    }
 
628
  }
 
629
  return 0;
 
630
}
 
631
 
 
632
/* ARGSUSED */
 
633
static int SystemSet(void *el, int xyzChanged)
 
634
{
 
635
  GeSystem *e= el;
 
636
  e->el.hidden= gistD.hidden;
 
637
  e->el.legend= gistD.legend;
 
638
  return 0;
 
639
}
 
640
 
 
641
/* ------------------------------------------------------------------------ */
 
642
/* Draw virtual function calls Gp and Ga level rendering routines */
 
643
 
 
644
static int LinesDraw(void *el, int xIsLog, int yIsLog)
 
645
{
 
646
  GeLines *e= el;
 
647
  GpReal *px= xIsLog? e->xlog : e->x;
 
648
  GpReal *py= yIsLog? e->ylog : e->y;
 
649
  long n= e->n;
 
650
  if (e->el.hidden || n<=0) return 0;
 
651
  gistA.l= e->l;
 
652
  gistA.dl= e->dl;
 
653
  gistA.m= e->m;
 
654
  return GaLines(n, px, py);
 
655
}
 
656
 
 
657
static int DisjointDraw(void *el, int xIsLog, int yIsLog)
 
658
{
 
659
  GeDisjoint *e= el;
 
660
  GpReal *px= xIsLog? e->xlog : e->x;
 
661
  GpReal *py= yIsLog? e->ylog : e->y;
 
662
  GpReal *qx= xIsLog? e->xqlog : e->xq;
 
663
  GpReal *qy= yIsLog? e->yqlog : e->yq;
 
664
  long n= e->n;
 
665
  if (e->el.hidden || n<=0) return 0;
 
666
  gistA.l= e->l;
 
667
  return GpDisjoint(n, px, py, qx, qy);
 
668
}
 
669
 
 
670
static int TextDraw(void *el, int xIsLog, int yIsLog)
 
671
{
 
672
  GeText *e= el;
 
673
  GpReal x0, y0;
 
674
  if (e->el.hidden || !e->text) return 0;
 
675
  x0= xIsLog? SAFELOG(e->x0) : e->x0;
 
676
  y0= yIsLog? SAFELOG(e->y0) : e->y0;
 
677
  gistA.t= e->t;
 
678
  return GpText(x0, y0, e->text);
 
679
}
 
680
 
 
681
static int CellsDraw(void *el, int xIsLog, int yIsLog)
 
682
{
 
683
  GeCells *e= el;
 
684
  GpReal px, py, qx, qy;
 
685
  int value;
 
686
  if (e->el.hidden) return 0;
 
687
  px= xIsLog? SAFELOG(e->px) : e->px;
 
688
  py= yIsLog? SAFELOG(e->py) : e->py;
 
689
  qx= xIsLog? SAFELOG(e->qx) : e->qx;
 
690
  qy= yIsLog? SAFELOG(e->qy) : e->qy;
 
691
  gistA.rgb = e->rgb;
 
692
  value = GpCells(px, py, qx, qy, e->width, e->height, e->width, e->colors);
 
693
  gistA.rgb = 0;  /* modest attempt at backward compatibility */
 
694
  return value;
 
695
}
 
696
 
 
697
static int PolysDraw(void *el, int xIsLog, int yIsLog)
 
698
{
 
699
  int result= 0;
 
700
  GePolys *e= el;
 
701
  GpReal *px= xIsLog? e->xlog : e->x;
 
702
  GpReal *py= yIsLog? e->ylog : e->y;
 
703
  GpColor *colors= e->colors;
 
704
  int rgb = colors? e->rgb : 0;
 
705
  long n= e->n;
 
706
  long *pn= e->pn;
 
707
  long i;
 
708
  if (e->el.hidden || n<=0) return 0;
 
709
  gistA.e= e->e;
 
710
  if (!colors) gistA.f.color =  BG_COLOR;
 
711
  if (n<2 || pn[1]>1) {
 
712
    long j = 0;
 
713
    for (i=0 ; i<n ; i++) {
 
714
      if (rgb)
 
715
        gistA.f.color=P_RGB(colors[j],colors[j+1],colors[j+2]), j+=3;
 
716
      else if (colors)
 
717
        gistA.f.color = colors[i];
 
718
      result|= GpFill(pn[i], px, py);
 
719
      px+= pn[i];
 
720
      py+= pn[i];
 
721
    }
 
722
  } else {
 
723
    long j = 3;
 
724
    long i0= pn[0]-1;
 
725
    for (i=1 ; i<n ; i++) {
 
726
      if (rgb)
 
727
        gistA.f.color=P_RGB(colors[j],colors[j+1],colors[j+2]), j+=3;
 
728
      else if (colors)
 
729
        gistA.f.color = colors[i];
 
730
      result|= GaFillMarker(pn[0], px, py, px[i0+i], py[i0+i]);
 
731
    }
 
732
  }
 
733
  return result;
 
734
}
 
735
 
 
736
static void MeshDrawSet(GaQuadMesh *mesh, void *vMeshEl,
 
737
                        int xIsLog, int yIsLog)
 
738
{
 
739
  GeMesh *meshEl= vMeshEl;
 
740
  GaQuadMesh *msh= &meshEl->mesh;
 
741
  GpReal *x= xIsLog? meshEl->xlog : msh->x;
 
742
  GpReal *y= yIsLog? meshEl->ylog : msh->y;
 
743
  mesh->iMax= msh->iMax;
 
744
  mesh->jMax= msh->jMax;
 
745
  mesh->x= x;
 
746
  mesh->y= y;
 
747
  mesh->reg= msh->reg;
 
748
  mesh->triangle= msh->triangle;
 
749
}
 
750
 
 
751
static int MeshDraw(void *el, int xIsLog, int yIsLog)
 
752
{
 
753
  GeMesh *e= el;
 
754
  GaQuadMesh mesh;
 
755
  if (e->el.hidden) return 0;
 
756
  MeshDrawSet(&mesh, el, xIsLog, yIsLog);
 
757
  gistA.l= e->l;
 
758
  return GaMesh(&mesh, e->region, e->boundary, e->inhibit);
 
759
}
 
760
 
 
761
static int FilledDraw(void *el, int xIsLog, int yIsLog)
 
762
{
 
763
  GeFill *e= el;
 
764
  GaQuadMesh mesh;
 
765
  if (e->el.hidden) return 0;
 
766
  MeshDrawSet(&mesh, el, xIsLog, yIsLog);
 
767
  gistA.e= e->e;
 
768
  gistA.rgb = e->rgb;
 
769
  return GaFillMesh(&mesh, e->region, e->colors, e->nColumns);
 
770
}
 
771
 
 
772
static int VectorsDraw(void *el, int xIsLog, int yIsLog)
 
773
{
 
774
  GeVectors *e= el;
 
775
  GaQuadMesh mesh;
 
776
  if (e->el.hidden) return 0;
 
777
  MeshDrawSet(&mesh, el, xIsLog, yIsLog);
 
778
  gistA.l= e->l;
 
779
  gistA.f= e->f;
 
780
  gistA.vect= e->vect;
 
781
  return GaVectors(&mesh, e->region, e->u, e->v, e->scale);
 
782
}
 
783
 
 
784
static int ContoursDraw(void *el, int xIsLog, int yIsLog)
 
785
{
 
786
  GeContours *e= el;
 
787
  int nLevels= e->nLevels;
 
788
  GeLines **groups= e->groups;
 
789
  int value= 0;
 
790
  if (e->el.hidden || nLevels<=0) return 0;
 
791
  if (!groups) return 1;
 
792
  while (nLevels--) value|= Gd_DrawRing(*groups++, xIsLog, yIsLog, 0, 1);
 
793
  return value;
 
794
}
 
795
 
 
796
static int SystemDraw(void *el, int xIsLog, int yIsLog)
 
797
     /* NOTE: xIsLog input is used in a very non-standard way as the
 
798
        index of this system.  This is possible since xIsLog and yIsLog
 
799
        are otherwise meaningless in SystemDraw.  */
 
800
{
 
801
  GeSystem *e= el;
 
802
  int vflags, hflags= e->flags;
 
803
  int systemCounter= xIsLog;   /* Yes, this is non-standard usage */
 
804
  GpBox port, *tickIn;
 
805
  if (e->el.hidden || !e->elements) return 0;
 
806
 
 
807
  xIsLog= hflags & D_LOGX;
 
808
  yIsLog= hflags & D_LOGY;
 
809
  GpSetTrans(&e->trans);
 
810
 
 
811
  /* In order to prevent needless GaTick calls, a special feature
 
812
     is built into GdBeginSy.  */
 
813
  hflags= e->ticks.horiz.flags;
 
814
  vflags= e->ticks.vert.flags;
 
815
  if (vflags & TICK_C || hflags & TICK_C) tickIn= 0;
 
816
  else {
 
817
    GpReal tlen= e->ticks.vert.tickLen[0];
 
818
    GpReal twid= 0.5*e->ticks.vert.tickStyle.width*DEFAULT_LINE_WIDTH;
 
819
    tlen= (vflags&TICK_IN)? ((vflags&TICK_OUT)? 0.5 : 1.0)*tlen : 0.0;
 
820
 
 
821
    tickIn= &port;
 
822
    port= e->trans.viewport;
 
823
    if (vflags & TICK_L) port.xmin-= e->ticks.vert.tickOff + tlen + twid;
 
824
    if (vflags & TICK_U) port.xmax+= e->ticks.vert.tickOff - tlen - twid;
 
825
 
 
826
    tlen= e->ticks.horiz.tickLen[0];
 
827
    twid= 0.5*e->ticks.horiz.tickStyle.width*DEFAULT_LINE_WIDTH;
 
828
    tlen= (hflags&TICK_IN)? ((hflags&TICK_OUT)? 0.5 : 1.0)*tlen : 0.0;
 
829
    if (hflags & TICK_L) port.ymin-= e->ticks.horiz.tickOff + tlen + twid;
 
830
    if (hflags & TICK_U) port.ymax+= e->ticks.horiz.tickOff - tlen - twid;
 
831
  }
 
832
 
 
833
  hflags= GdBeginSy(&e->el.box, tickIn, &e->trans.viewport,
 
834
                    e->el.number, systemCounter);
 
835
 
 
836
  /* Draw the elements for this coordinate system before the ticks.  */
 
837
  gistClip= 1;   /* turn on clipping for elements */
 
838
  if (hflags & 1) Gd_DrawRing(e->elements, xIsLog, yIsLog, e, 0);
 
839
 
 
840
  /* Draw tick marks on top of elements.  If the user has chosen a style
 
841
     where the ticks overlap the viewport, he probably wants the ticks
 
842
     to obstruct his data anyway. */
 
843
  gistClip= 0;   /* turn off clipping for ticks */
 
844
  if (hflags & 2) GaAltTick(&e->ticks, xIsLog, yIsLog,
 
845
                            e->xtick, e->xlabel, e->ytick, e->ylabel);
 
846
  return 0;
 
847
}
 
848
 
 
849
/* ------------------------------------------------------------------------ */
 
850
/* Scan virtual function gets logs if reqd, sets box, scans xy  */
 
851
 
 
852
static int ScanMn(long n, GpReal *x, GpReal *y, GpReal ymin,
 
853
                  GpReal *xmin, GpReal *xmax)
 
854
{
 
855
  GpReal xn, xx;
 
856
  long i;
 
857
  for (i=0 ; i<n ; i++) if (y[i]>=ymin) break;
 
858
  if (i>=n) return 0;
 
859
  xn= xx= x[i++];
 
860
  for ( ; i<n ; i++) if (y[i]>=ymin) {
 
861
    if (x[i]<xn) xn= x[i];
 
862
    else if (x[i]>xx) xx= x[i];
 
863
  }
 
864
  *xmin= xn;
 
865
  *xmax= xx;
 
866
  return 1;
 
867
}
 
868
 
 
869
static int ScanMx(long n, GpReal *x, GpReal *y, GpReal ymax,
 
870
                  GpReal *xmin, GpReal *xmax)
 
871
{
 
872
  GpReal xn, xx;
 
873
  long i;
 
874
  for (i=0 ; i<n ; i++) if (y[i]<=ymax) break;
 
875
  if (i>=n) return 0;
 
876
  xn= xx= x[i++];
 
877
  for ( ; i<n ; i++) if (y[i]<=ymax) {
 
878
    if (x[i]<xn) xn= x[i];
 
879
    else if (x[i]>xx) xx= x[i];
 
880
  }
 
881
  *xmin= xn;
 
882
  *xmax= xx;
 
883
  return 1;
 
884
}
 
885
 
 
886
static int ScanMnMx(long n, GpReal *x, GpReal *y, GpReal ymin, GpReal ymax,
 
887
                    GpReal *xmin, GpReal *xmax)
 
888
{
 
889
  GpReal xn, xx;
 
890
  long i;
 
891
  for (i=0 ; i<n ; i++) if (y[i]>=ymin && y[i]<=ymax) break;
 
892
  if (i>=n) return 0;
 
893
  xn= xx= x[i++];
 
894
  for ( ; i<n ; i++) if (y[i]>=ymin && y[i]<=ymax) {
 
895
    if (x[i]<xn) xn= x[i];
 
896
    else if (x[i]>xx) xx= x[i];
 
897
  }
 
898
  *xmin= xn;
 
899
  *xmax= xx;
 
900
  return 1;
 
901
}
 
902
 
 
903
static void ScanRXY(long n, GpReal *x, GpReal *y,
 
904
                    int flags, GpBox *limits, GpBox *box)
 
905
{
 
906
  int dxmin= flags & D_XMIN,  dxmax= flags & D_XMAX;
 
907
  int dymin= flags & D_YMIN,  dymax= flags & D_YMAX;
 
908
  int any;
 
909
 
 
910
  if (dxmin || dxmax) {
 
911
    GpReal xmin, xmax;
 
912
    if (dymin) {
 
913
      if (dymax) { xmin= box->xmin;  xmax= box->xmax; any= 1; }
 
914
      else if (box->ymin>limits->ymax) any= 0;
 
915
      else any= ScanMx(n, x, y, limits->ymax, &xmin, &xmax);
 
916
    } else if (box->ymax<limits->ymin) {
 
917
      any= 0;
 
918
    } else {
 
919
      if (dymax) any= ScanMn(n, x, y, limits->ymin, &xmin, &xmax);
 
920
      else if (box->ymin>limits->ymax) any= 0;
 
921
      else any= ScanMnMx(n, x, y, limits->ymin, limits->ymax, &xmin, &xmax);
 
922
    }
 
923
    if (any) {
 
924
      if (dxmin) limits->xmin= xmin;
 
925
      if (dxmax) limits->xmax= xmax;
 
926
    } else {  /* GdScan requires min>max if no curves visible */
 
927
      if (dxmin) {
 
928
        if (dxmax) limits->xmax= 0.0;
 
929
        if (limits->xmax>0.0) limits->xmin= 1.1*limits->xmax;
 
930
        else limits->xmin= 0.9*limits->xmax+1.0;
 
931
      } else { /* dxmax is set */
 
932
        if (limits->xmin>0.0) limits->xmax= 0.9*limits->xmin;
 
933
        else limits->xmax= 1.1*limits->xmin-1.0;
 
934
      }
 
935
    }
 
936
  }
 
937
  if (dymin || dymax) {
 
938
    GpReal ymin, ymax;
 
939
    if (dxmin) {
 
940
      if (dxmax) { ymin= box->ymin;  ymax= box->ymax; any= 1; }
 
941
      else if (box->xmin>limits->xmax) any= 0;
 
942
      else any= ScanMx(n, y, x, limits->xmax, &ymin, &ymax);
 
943
    } else if (box->xmax<limits->xmin) {
 
944
      any= 0;
 
945
    } else {
 
946
      if (dxmax) any= ScanMn(n, y, x, limits->xmin, &ymin, &ymax);
 
947
      else if (box->xmin>limits->xmax) any= 0;
 
948
      else any= ScanMnMx(n, y, x, limits->xmin, limits->xmax, &ymin, &ymax);
 
949
    }
 
950
    if (any) {
 
951
      if (dymin) limits->ymin= ymin;
 
952
      if (dymax) limits->ymax= ymax;
 
953
    } else {  /* GdScan requires min>max if no curves visible */
 
954
      if (dymin) {
 
955
        if (dymax) limits->ymax= 0.0;
 
956
        if (limits->ymax>0.0) limits->ymin= 1.1*limits->ymax;
 
957
        else limits->ymin= 0.9*limits->ymax+1.0;
 
958
      } else { /* dymax is set */
 
959
        if (limits->ymin>0.0) limits->ymax= 0.9*limits->ymin;
 
960
        else limits->ymax= 1.1*limits->ymin-1.0;
 
961
      }
 
962
    }
 
963
  }
 
964
}
 
965
 
 
966
static int GetLogZ(long n, GpReal *z, GpReal **zlog,
 
967
                   GpReal *zmin, GpReal *zmax)
 
968
{
 
969
  GpReal *zl= (GpReal *)p_malloc(sizeof(GpReal)*n);
 
970
  *zlog= zl;
 
971
  if (zl) {
 
972
    long i;
 
973
    for (i=0 ; i<n ; i++) zl[i]= SAFELOG(z[i]);
 
974
    if (zmin) Gd_ScanZ(n, zl, zmin, zmax);
 
975
  } else {
 
976
    strcpy(gistError, "memory manager failed in Gd log function");
 
977
    return -1;
 
978
  }
 
979
  return 0;
 
980
}
 
981
 
 
982
static int Get_LogZ(long n, long nndc, GpReal *z, GpReal **zlog,
 
983
                    GpReal *zmin, GpReal *zmax)
 
984
{
 
985
  GpReal *zl= (GpReal *)p_malloc(sizeof(GpReal)*n);
 
986
  *zlog= zl;
 
987
  if (zl) {
 
988
    long i;
 
989
    for (i=0 ; i<nndc ; i++) zl[i]= z[i];
 
990
    for ( ; i<n ; i++) zl[i]= SAFELOG(z[i]);
 
991
    if (zmin) Gd_ScanZ(n-nndc, zl+nndc, zmin, zmax);
 
992
  } else {
 
993
    strcpy(gistError, "memory manager failed in Gd_log function");
 
994
    return -1;
 
995
  }
 
996
  return 0;
 
997
}
 
998
 
 
999
static int LinesScan(void *el, int flags, GpBox *limits)
 
1000
{
 
1001
  GeLines *e= el;
 
1002
  GpReal *x, *y;
 
1003
 
 
1004
  /* First, get log values if necessary, and set box */
 
1005
  if (flags & D_LOGX) {
 
1006
    if (!e->xlog && GetLogZ(e->n, e->x, &e->xlog,
 
1007
                            &e->logBox.xmin, &e->logBox.xmax)) return 1;
 
1008
    e->el.box.xmin= e->logBox.xmin;
 
1009
    e->el.box.xmax= e->logBox.xmax;
 
1010
    x= e->xlog;
 
1011
  } else {
 
1012
    e->el.box.xmin= e->linBox.xmin;
 
1013
    e->el.box.xmax= e->linBox.xmax;
 
1014
    x= e->x;
 
1015
  }
 
1016
  if (flags & D_LOGY) {
 
1017
    if (!e->ylog && GetLogZ(e->n, e->y, &e->ylog,
 
1018
                            &e->logBox.ymin, &e->logBox.ymax)) return 1;
 
1019
    e->el.box.ymin= e->logBox.ymin;
 
1020
    e->el.box.ymax= e->logBox.ymax;
 
1021
    y= e->ylog;
 
1022
  } else {
 
1023
    e->el.box.ymin= e->linBox.ymin;
 
1024
    e->el.box.ymax= e->linBox.ymax;
 
1025
    y= e->y;
 
1026
  }
 
1027
 
 
1028
  if (flags & D_RESTRICT) {
 
1029
    /* Scan points, restricting x limits to lie within fixed y limits
 
1030
       and vice-versa.  Assume that limits.min<limits.max.  */
 
1031
    ScanRXY(e->n, x, y, flags, limits, &e->el.box);
 
1032
  } else {
 
1033
    /* Unrestricted limits are either fixed or same as bounding box.  */
 
1034
    if (flags & D_XMIN) limits->xmin= e->el.box.xmin;
 
1035
    if (flags & D_XMAX) limits->xmax= e->el.box.xmax;
 
1036
    if (flags & D_YMIN) limits->ymin= e->el.box.ymin;
 
1037
    if (flags & D_YMAX) limits->ymax= e->el.box.ymax;
 
1038
  }
 
1039
 
 
1040
  return 0;
 
1041
}
 
1042
 
 
1043
static int DisjointScan(void *el, int flags, GpBox *limits)
 
1044
{
 
1045
  GeDisjoint *e= el;
 
1046
  GpReal *x, *y, *xq, *yq;
 
1047
  GpReal xymin, xymax;
 
1048
 
 
1049
  /* First, get log values if necessary, and set box */
 
1050
  if (flags & D_LOGX) {
 
1051
    if (!e->xlog && GetLogZ(e->n, e->x, &e->xlog,
 
1052
                            &e->logBox.xmin, &e->logBox.xmax)) return 1;
 
1053
    e->el.box.xmin= e->logBox.xmin;
 
1054
    e->el.box.xmax= e->logBox.xmax;
 
1055
    x= e->xlog;
 
1056
    if (!e->xqlog && GetLogZ(e->n, e->xq, &e->xqlog,
 
1057
                             &xymin, &xymax)) return 1;
 
1058
    if (xymin<e->el.box.xmin) e->el.box.xmin= e->logBox.xmin;
 
1059
    if (xymax>e->el.box.xmax) e->el.box.xmax= e->logBox.xmax;
 
1060
    xq= e->xqlog;
 
1061
  } else {
 
1062
    e->el.box.xmin= e->linBox.xmin;
 
1063
    e->el.box.xmax= e->linBox.xmax;
 
1064
    x= e->x;
 
1065
    xq= e->xq;
 
1066
  }
 
1067
  if (flags & D_LOGY) {
 
1068
    if (!e->ylog && GetLogZ(e->n, e->y, &e->ylog,
 
1069
                            &e->logBox.ymin, &e->logBox.ymax)) return 1;
 
1070
    e->el.box.ymin= e->logBox.ymin;
 
1071
    e->el.box.ymax= e->logBox.ymax;
 
1072
    y= e->ylog;
 
1073
    if (!e->yqlog && GetLogZ(e->n, e->yq, &e->yqlog,
 
1074
                             &xymin, &xymax)) return 1;
 
1075
    if (xymin<e->el.box.ymin) e->el.box.ymin= e->logBox.ymin;
 
1076
    if (xymax>e->el.box.ymax) e->el.box.ymax= e->logBox.ymax;
 
1077
    yq= e->yqlog;
 
1078
  } else {
 
1079
    e->el.box.ymin= e->linBox.ymin;
 
1080
    e->el.box.ymax= e->linBox.ymax;
 
1081
    y= e->y;
 
1082
    yq= e->yq;
 
1083
  }
 
1084
 
 
1085
  if (flags & D_RESTRICT) {
 
1086
    /* Scan points, restricting x limits to lie within fixed y limits
 
1087
       and vice-versa.  Assume that limits.min<limits.max.  */
 
1088
    GpBox box;
 
1089
    ScanRXY(e->n, x, y, flags, limits, &e->el.box);
 
1090
    ScanRXY(e->n, xq, yq, flags, &box, &e->el.box);
 
1091
    GpSwallow(limits, &box);
 
1092
  } else {
 
1093
    /* Unrestricted limits are either fixed or same as bounding box.  */
 
1094
    if (flags & D_XMIN) limits->xmin= e->el.box.xmin;
 
1095
    if (flags & D_XMAX) limits->xmax= e->el.box.xmax;
 
1096
    if (flags & D_YMIN) limits->ymin= e->el.box.ymin;
 
1097
    if (flags & D_YMAX) limits->ymax= e->el.box.ymax;
 
1098
  }
 
1099
 
 
1100
  return 0;
 
1101
}
 
1102
 
 
1103
static int TextScan(void *el, int flags, GpBox *limits)
 
1104
{
 
1105
  GeText *e= el;
 
1106
  GpReal x0= e->x0;
 
1107
  GpReal y0= e->y0;
 
1108
 
 
1109
  if (flags & D_LOGX) x0= SAFELOG(x0);
 
1110
  if (flags & D_LOGY) y0= SAFELOG(y0);
 
1111
 
 
1112
  if (flags & D_XMIN) limits->xmin= x0;
 
1113
  if (flags & D_XMAX) limits->xmax= x0;
 
1114
  if (flags & D_YMIN) limits->ymin= y0;
 
1115
  if (flags & D_YMAX) limits->ymax= y0;
 
1116
  return 0;
 
1117
}
 
1118
 
 
1119
static int CellsScan(void *el, int flags, GpBox *limits)
 
1120
{
 
1121
  GeCells *e= el;
 
1122
  GpReal x[2], y[2];
 
1123
 
 
1124
  if (e->px<e->qx) { x[0]= e->px;  x[1]= e->qx; }
 
1125
  else { x[0]= e->qx;  x[1]= e->px; }
 
1126
  if (e->py<e->qy) { y[0]= e->py;  y[1]= e->qy; }
 
1127
  else { y[0]= e->qy;  y[1]= e->py; }
 
1128
 
 
1129
  /* First, get log values if necessary, and set box */
 
1130
  if (flags & D_LOGX) {
 
1131
    e->el.box.xmin= SAFELOG(x[0]);
 
1132
    e->el.box.xmax= SAFELOG(x[1]);
 
1133
  } else {
 
1134
    e->el.box.xmin= x[0];
 
1135
    e->el.box.xmax= x[1];
 
1136
  }
 
1137
  if (flags & D_LOGY) {
 
1138
    e->el.box.ymin= SAFELOG(y[0]);
 
1139
    e->el.box.ymax= SAFELOG(y[1]);
 
1140
  } else {
 
1141
    e->el.box.ymin= y[0];
 
1142
    e->el.box.ymax= y[1];
 
1143
  }
 
1144
 
 
1145
  if (flags & D_XMIN) limits->xmin= e->el.box.xmin;
 
1146
  if (flags & D_XMAX) limits->xmax= e->el.box.xmax;
 
1147
  if (flags & D_YMIN) limits->ymin= e->el.box.ymin;
 
1148
  if (flags & D_YMAX) limits->ymax= e->el.box.ymax;
 
1149
 
 
1150
  return 0;
 
1151
}
 
1152
 
 
1153
static int PolysScan(void *el, int flags, GpBox *limits)
 
1154
{
 
1155
  GePolys *e= el;
 
1156
  GpReal *x, *y;
 
1157
  long i, ntot= 0;
 
1158
  long nndc= (e->n<2 || e->pn[1]>1)? 0 : e->pn[0];
 
1159
 
 
1160
  /* compute total number of points */
 
1161
  for (i=0 ; i<e->n ; i++) ntot+= e->pn[i];
 
1162
 
 
1163
  /* First, get log values if necessary, and set box */
 
1164
  if (flags & D_LOGX) {
 
1165
    if (!e->xlog && Get_LogZ(ntot, nndc, e->x, &e->xlog,
 
1166
                             &e->logBox.xmin, &e->logBox.xmax)) return 1;
 
1167
    e->el.box.xmin= e->logBox.xmin;
 
1168
    e->el.box.xmax= e->logBox.xmax;
 
1169
    x= e->xlog;
 
1170
  } else {
 
1171
    e->el.box.xmin= e->linBox.xmin;
 
1172
    e->el.box.xmax= e->linBox.xmax;
 
1173
    x= e->x;
 
1174
  }
 
1175
  if (flags & D_LOGY) {
 
1176
    if (!e->ylog && Get_LogZ(ntot, nndc, e->y, &e->ylog,
 
1177
                             &e->logBox.ymin, &e->logBox.ymax)) return 1;
 
1178
    e->el.box.ymin= e->logBox.ymin;
 
1179
    e->el.box.ymax= e->logBox.ymax;
 
1180
    y= e->ylog;
 
1181
  } else {
 
1182
    e->el.box.ymin= e->linBox.ymin;
 
1183
    e->el.box.ymax= e->linBox.ymax;
 
1184
    y= e->y;
 
1185
  }
 
1186
 
 
1187
  if (flags & D_RESTRICT) {
 
1188
    /* Scan points, restricting x limits to lie within fixed y limits
 
1189
       and vice-versa.  Assume that limits.min<limits.max.  */
 
1190
    ScanRXY(ntot-nndc, x+nndc, y+nndc, flags, limits, &e->el.box);
 
1191
  } else {
 
1192
    /* Unrestricted limits are either fixed or same as bounding box.  */
 
1193
    if (flags & D_XMIN) limits->xmin= e->el.box.xmin;
 
1194
    if (flags & D_XMAX) limits->xmax= e->el.box.xmax;
 
1195
    if (flags & D_YMIN) limits->ymin= e->el.box.ymin;
 
1196
    if (flags & D_YMAX) limits->ymax= e->el.box.ymax;
 
1197
  }
 
1198
 
 
1199
  return 0;
 
1200
}
 
1201
 
 
1202
static int MeshXYScan(void *vMeshEl, int flags, GpBox *limits, GpBox *box)
 
1203
{
 
1204
  GeMesh *meshEl= vMeshEl;
 
1205
  GaQuadMesh *mesh= &meshEl->mesh;
 
1206
  GpReal *x, *y;
 
1207
 
 
1208
  /* First, get log values if necessary, and set box */
 
1209
  if (flags & D_LOGX) {
 
1210
    long len= mesh->iMax*mesh->jMax;
 
1211
    int region= meshEl->region;
 
1212
    GpReal xmin, xmax;
 
1213
    long i, j, iMax= mesh->iMax;
 
1214
    int *reg= mesh->reg, first= 1;
 
1215
 
 
1216
    if (!meshEl->xlog && GetLogZ(len, mesh->x, &meshEl->xlog, 0, 0))
 
1217
      return 1;
 
1218
    for (i=0 ; i<len ; ) {
 
1219
      Gd_NextMeshBlock(&i, &j, len, iMax, reg, region);
 
1220
      if (i>=len) break;
 
1221
      Gd_ScanZ(j-i, meshEl->xlog+i, &xmin, &xmax);
 
1222
      if (first) {
 
1223
        meshEl->logBox.xmin= xmin;
 
1224
        meshEl->logBox.xmax= xmax;
 
1225
        first= 0;
 
1226
      } else {
 
1227
        if (xmin<meshEl->logBox.xmin) meshEl->logBox.xmin= xmin;
 
1228
        if (xmax>meshEl->logBox.xmax) meshEl->logBox.xmax= xmax;
 
1229
      }
 
1230
      i= j+1;
 
1231
    }
 
1232
    box->xmin= meshEl->logBox.xmin;
 
1233
    box->xmax= meshEl->logBox.xmax;
 
1234
    x= meshEl->xlog;
 
1235
  } else {
 
1236
    box->xmin= meshEl->linBox.xmin;
 
1237
    box->xmax= meshEl->linBox.xmax;
 
1238
    x= mesh->x;
 
1239
  }
 
1240
  if (flags & D_LOGY) {
 
1241
    long len= mesh->iMax*mesh->jMax;
 
1242
    int region= meshEl->region;
 
1243
    GpReal ymin, ymax;
 
1244
    long i, j, iMax= mesh->iMax;
 
1245
    int *reg= mesh->reg, first= 1;
 
1246
 
 
1247
    if (!meshEl->ylog && GetLogZ(len, mesh->y, &meshEl->ylog, 0, 0))
 
1248
      return 1;
 
1249
    for (i=0 ; i<len ; ) {
 
1250
      Gd_NextMeshBlock(&i, &j, len, iMax, reg, region);
 
1251
      if (i>=len) break;
 
1252
      Gd_ScanZ(j-i, meshEl->ylog+i, &ymin, &ymax);
 
1253
      if (first) {
 
1254
        meshEl->logBox.ymin= ymin;
 
1255
        meshEl->logBox.ymax= ymax;
 
1256
        first= 0;
 
1257
      } else {
 
1258
        if (ymin<meshEl->logBox.ymin) meshEl->logBox.ymin= ymin;
 
1259
        if (ymax>meshEl->logBox.ymax) meshEl->logBox.ymax= ymax;
 
1260
      }
 
1261
      i= j+1;
 
1262
    }
 
1263
    box->ymin= meshEl->logBox.ymin;
 
1264
    box->ymax= meshEl->logBox.ymax;
 
1265
    y= meshEl->ylog;
 
1266
  } else {
 
1267
    box->ymin= meshEl->linBox.ymin;
 
1268
    box->ymax= meshEl->linBox.ymax;
 
1269
    y= mesh->y;
 
1270
  }
 
1271
 
 
1272
  if (flags & D_RESTRICT) {
 
1273
    /* Scan points, restricting x limits to lie within fixed y limits
 
1274
       and vice-versa.  Assume that limits.min<limits.max.  */
 
1275
    long len= mesh->iMax*mesh->jMax;
 
1276
    int region= meshEl->region;
 
1277
    GpBox tbox;
 
1278
    long i, j, iMax= mesh->iMax;
 
1279
    int *reg= mesh->reg, first= 1;
 
1280
    tbox= *limits;
 
1281
    for (i=0 ; i<len ; ) {
 
1282
      Gd_NextMeshBlock(&i, &j, len, iMax, reg, region);
 
1283
      if (i>=len) break;
 
1284
      ScanRXY(j-i, x+i, y+i, flags, limits, &tbox);
 
1285
      if (first) { *box= tbox;  first= 0; }
 
1286
      else GpSwallow(box, &tbox);
 
1287
      i= j+1;
 
1288
    }
 
1289
  } else {
 
1290
    /* Unrestricted limits are either fixed or same as bounding box.  */
 
1291
    if (flags & D_XMIN) limits->xmin= box->xmin;
 
1292
    if (flags & D_XMAX) limits->xmax= box->xmax;
 
1293
    if (flags & D_YMIN) limits->ymin= box->ymin;
 
1294
    if (flags & D_YMAX) limits->ymax= box->ymax;
 
1295
  }
 
1296
 
 
1297
  return 0;
 
1298
}
 
1299
 
 
1300
static int MeshScan(void *el, int flags, GpBox *limits)
 
1301
{
 
1302
  GeMesh *e= el;
 
1303
  return MeshXYScan(el, flags, limits, &e->el.box);
 
1304
}
 
1305
 
 
1306
static int FilledScan(void *el, int flags, GpBox *limits)
 
1307
{
 
1308
  GeFill *e= el;
 
1309
  return MeshXYScan(el, flags, limits, &e->el.box);
 
1310
}
 
1311
 
 
1312
static int VectorsScan(void *el, int flags, GpBox *limits)
 
1313
{
 
1314
  GeVectors *e= el;
 
1315
  return MeshXYScan(el, flags, limits, &e->el.box);
 
1316
}
 
1317
 
 
1318
static int ContoursScan(void *el, int flags, GpBox *limits)
 
1319
{
 
1320
  GeContours *e= el;
 
1321
  GpBox lims= *limits;
 
1322
  GeLines *elx, *el0, **groups= e->groups;
 
1323
  int i, value= 0, none= 1;
 
1324
  for (i=0 ; i<e->nLevels ; i++) {
 
1325
    el0= *groups++;
 
1326
    if ((elx= el0)) do {
 
1327
      value|= LinesScan(elx, flags, &lims);
 
1328
      if (none) { *limits= lims;   e->el.box= lims; }
 
1329
      else { GpSwallow(limits, &lims);   GpSwallow(&e->el.box, &lims); }
 
1330
      none= 0;
 
1331
      elx= (GeLines *)elx->el.next;
 
1332
    } while (elx != el0);
 
1333
  }
 
1334
  if (none) value= MeshXYScan(el, flags, limits, &e->el.box);
 
1335
  return value;
 
1336
}
 
1337
 
 
1338
/* ARGSUSED */
 
1339
static int SystemScan(void *el, int flags, GpBox *limits)
 
1340
{
 
1341
  return 0;   /* cannot ever happen... */
 
1342
}
 
1343
 
 
1344
/* ------------------------------------------------------------------------ */
 
1345
/* Margin virtual function returns margin box */
 
1346
 
 
1347
/* ARGSUSED */
 
1348
static void NoMargin(void *el, GpBox *margin)
 
1349
{
 
1350
  margin->xmin= margin->xmax= margin->ymin= margin->ymax= 0.0;
 
1351
}
 
1352
 
 
1353
static void LinesMargin(void *el, GpBox *margin)
 
1354
{
 
1355
  /* This only accounts for line width, ignoring other decorations--
 
1356
     other decorations seem unlikely outside coordinate systems */
 
1357
  GeLines *lines= el;
 
1358
  margin->xmin= margin->xmax= margin->ymin= margin->ymax=
 
1359
    0.5*lines->l.width*DEFAULT_LINE_WIDTH;
 
1360
}
 
1361
 
 
1362
static void DisjointMargin(void *el, GpBox *margin)
 
1363
{
 
1364
  GeDisjoint *lines= el;
 
1365
  margin->xmin= margin->xmax= margin->ymin= margin->ymax=
 
1366
    0.5*lines->l.width*DEFAULT_LINE_WIDTH;
 
1367
}
 
1368
 
 
1369
static void TextMargin(void *el, GpBox *margin)
 
1370
{
 
1371
  /* The actual text box cannot be computed without text metric data--
 
1372
     the following is a crude guess based on character counts and an
 
1373
     assumed width/height ratio of 0.6 (as in 9x15) and descent/height
 
1374
     ratio of 0.2.  This should be close for Courier, but it probably
 
1375
     way off in width for the proportional fonts.  */
 
1376
  GeText *text= el;
 
1377
  GpReal width, x0, y0, dx, dy;
 
1378
  int alignH, alignV;
 
1379
  int nLines= GtTextShape(text->text, &text->t, (WidthFunction)0, &width);
 
1380
 
 
1381
  dx= text->t.height*width*0.6;
 
1382
  dy= text->t.height*((GpReal)nLines);
 
1383
 
 
1384
  GtGetAlignment(&text->t, &alignH, &alignV);
 
1385
  if (alignH==TH_LEFT) {
 
1386
    x0= 0.0;
 
1387
  } else if (alignH==TH_CENTER) {
 
1388
    x0= -0.5*dx;
 
1389
  } else {
 
1390
    x0= -dx;
 
1391
  }
 
1392
  if (alignV==TV_TOP || alignV==TV_CAP) {
 
1393
    y0= -dy;
 
1394
  } else if (alignH==TV_HALF) {
 
1395
    y0= -0.1*text->t.height - 0.5*dy;
 
1396
  } else if (alignH==TV_BASE) {
 
1397
    y0= -0.2*text->t.height;
 
1398
  } else {
 
1399
    y0= 0.0;
 
1400
  }
 
1401
 
 
1402
  if (gistA.t.orient==TX_RIGHT) {
 
1403
    margin->xmin= x0;
 
1404
    margin->xmax= x0 + dx;
 
1405
    margin->ymin= y0;
 
1406
    margin->ymax= y0 + dy;
 
1407
  } else if (gistA.t.orient==TX_LEFT) {
 
1408
    margin->xmin= x0 - dx;
 
1409
    margin->xmax= x0;
 
1410
    margin->ymin= y0 - dy;
 
1411
    margin->ymax= y0;
 
1412
  } else if (gistA.t.orient==TX_UP) {
 
1413
    margin->xmin= y0;
 
1414
    margin->xmax= y0 + dy;
 
1415
    margin->ymin= x0;
 
1416
    margin->ymax= x0 + dx;
 
1417
  } else {
 
1418
    margin->xmin= y0 - dy;
 
1419
    margin->xmax= y0;
 
1420
    margin->ymin= x0 - dx;
 
1421
    margin->ymax= x0;
 
1422
  }
 
1423
}
 
1424
 
 
1425
static void MeshMargin(void *el, GpBox *margin)
 
1426
{
 
1427
  GeMesh *mesh= el;
 
1428
  margin->xmin= margin->xmax= margin->ymin= margin->ymax=
 
1429
    0.5*mesh->l.width*DEFAULT_LINE_WIDTH;
 
1430
}
 
1431
 
 
1432
/* ARGSUSED */
 
1433
static void VectorsMargin(void *el, GpBox *margin)
 
1434
{
 
1435
  /* This is a wild guess-- otherwise must scan (u, v) --
 
1436
     should never arise in practice */
 
1437
  /* GeVectors *vec= el; */
 
1438
  margin->xmin= margin->xmax= margin->ymin= margin->ymax= 0.05;
 
1439
}
 
1440
 
 
1441
static void ContoursMargin(void *el, GpBox *margin)
 
1442
{
 
1443
  /* Should never actually happen */
 
1444
  GeContours *con= el;
 
1445
  margin->xmin= margin->xmax= margin->ymin= margin->ymax=
 
1446
    0.5*con->l.width*DEFAULT_LINE_WIDTH;
 
1447
}
 
1448
 
 
1449
/* ------------------------------------------------------------------------ */