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

« back to all changes in this revision

Viewing changes to Lib/xplt/src/gist/engine.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
 * ENGINE.C
 
3
 *
 
4
 * $Id: engine.c,v 1.1 2003/03/08 15:26:45 travo Exp $
 
5
 *
 
6
 * Implement common properties of all GIST engines
 
7
 *
 
8
 */
 
9
/*    Copyright (c) 1994.  The Regents of the University of California.
 
10
                    All rights reserved.  */
 
11
 
 
12
#include "gist.h"
 
13
#include "engine.h"
 
14
#include "draw.h"
 
15
#include "pstdlib.h"
 
16
 
 
17
Engine *gistEngines= 0;
 
18
Engine *gistActive= 0;
 
19
Engine *gistPreempt= 0;
 
20
 
 
21
#include <string.h>
 
22
 
 
23
static void DefaultClearArea(Engine *engine, GpBox *box);
 
24
static void MoreScratch(long np, long ns);
 
25
 
 
26
/* ------------------------------------------------------------------------ */
 
27
 
 
28
/* ARGSUSED */
 
29
static void DefaultClearArea(Engine *engine, GpBox *box)
 
30
{
 
31
  /* Default ClearArea triggers complete redraw */
 
32
  engine->Clear(engine, CONDITIONALLY);
 
33
  engine->lastDrawn= -1;
 
34
  engine->systemsSeen[0]= engine->systemsSeen[1]= 0;
 
35
  engine->damaged= engine->inhibit= 0;
 
36
}
 
37
 
 
38
Engine *GpNewEngine(long size, char *name, char *type,
 
39
                    GpTransform *transform, int landscape,
 
40
  void (*Kill)(Engine*), int (*Clear)(Engine*,int), int (*Flush)(Engine*),
 
41
  void (*ChangeMap)(Engine*), int (*ChangePalette)(Engine*),
 
42
  int (*DrawLines)(Engine*,long,const GpReal*,const GpReal*,int,int),
 
43
  int (*DrawMarkers)(Engine*,long,const GpReal*,const GpReal *),
 
44
  int (*DrwText)(Engine*e,GpReal,GpReal,const char*),
 
45
  int (*DrawFill)(Engine*,long,const GpReal*,const GpReal*),
 
46
  int (*DrawCells)(Engine*,GpReal,GpReal,GpReal,GpReal,
 
47
                   long,long,long,const GpColor*),
 
48
  int (*DrawDisjoint)(Engine*,long,const GpReal*,const GpReal*,
 
49
                      const GpReal*,const GpReal*))
 
50
{
 
51
  long lname= name? strlen(name) : 0;
 
52
  Engine *engine;
 
53
  /* For Electric Fence package and maybe others, it is nice to ensure
 
54
     that size of block allocated for Engine is a multiple of the size
 
55
     of the most restrictively aligned object which can be in any
 
56
     Engine; assume this is a double.  */
 
57
  lname= (lname/sizeof(double) + 1)*sizeof(double);  /* >= lname+1 */
 
58
  engine= (Engine *)p_malloc(size+lname);
 
59
  if (!engine) return 0;
 
60
 
 
61
  /* Fill in Engine properties, link into gistEngines list */
 
62
  engine->next= gistEngines;
 
63
  gistEngines= engine;
 
64
  engine->nextActive= 0;
 
65
  engine->name= (char *)engine + size;
 
66
  strcpy(name? engine->name : "", name);
 
67
  engine->type= type;
 
68
  engine->active= 0;
 
69
  engine->marked= 0;
 
70
 
 
71
  engine->transform= *transform;
 
72
  engine->landscape= landscape? 1 : 0;
 
73
  GpDeviceMap(engine);
 
74
  /* (a proper map will be installed when the engine is activated) */
 
75
  engine->map.x.scale= engine->map.y.scale= 1.0;
 
76
  engine->map.x.offset= engine->map.y.offset= 0.0;
 
77
 
 
78
  /* No pseudocolor map initially */
 
79
  engine->colorChange= 0;
 
80
  engine->colorMode= 0;
 
81
  engine->nColors= 0;
 
82
  engine->palette= 0;
 
83
 
 
84
  /* No associated drawing initially */
 
85
  engine->drawing= 0;
 
86
  engine->lastDrawn= -1;
 
87
  engine->systemsSeen[0]= engine->systemsSeen[1]= 0;
 
88
  engine->inhibit= 0;
 
89
  engine->damaged= 0;  /* causes Clear if no ClearArea virtual function */
 
90
  engine->damage.xmin= engine->damage.xmax=
 
91
    engine->damage.ymin= engine->damage.ymax= 0.0;
 
92
 
 
93
  /* Fill in virtual function table */
 
94
  engine->Kill= Kill;
 
95
  engine->Clear= Clear;
 
96
  engine->Flush= Flush;
 
97
  engine->ChangeMap= ChangeMap;
 
98
  engine->ChangePalette= ChangePalette;
 
99
  engine->DrawLines= DrawLines;
 
100
  engine->DrawMarkers= DrawMarkers;
 
101
  engine->DrwText= DrwText;
 
102
  engine->DrawFill= DrawFill;
 
103
  engine->DrawCells= DrawCells;
 
104
  engine->DrawDisjoint= DrawDisjoint;
 
105
  engine->ClearArea= &DefaultClearArea;   /* damage causes complete redraw */
 
106
 
 
107
  return engine;
 
108
}
 
109
 
 
110
void GpDelEngine(Engine *engine)
 
111
{
 
112
  Engine *eng= gistEngines;
 
113
  if (!engine) return;
 
114
 
 
115
  /* Unlink from gistEngines list */
 
116
  if (engine->active) GpDeactivate(engine);
 
117
  if (eng==engine) gistEngines= engine->next;
 
118
  else {
 
119
    /* Because of recursive deletes necessary to deal with X window
 
120
       deletions (see xbasic.c:ShutDown, hlevel.c:ShutDownDev), if
 
121
       the engine has already been removed from the list, it means that
 
122
       this routine is being called for the second time for this engine,
 
123
       and p_free must NOT be called.  Fix this someday.  */
 
124
    while (eng && eng->next!=engine) eng= eng->next;
 
125
    if (!eng) return;
 
126
    eng->next= engine->next;
 
127
  }
 
128
 
 
129
  p_free(engine);
 
130
}
 
131
 
 
132
/* ------------------------------------------------------------------------ */
 
133
 
 
134
void GpKillEngine(Engine *engine)
 
135
{
 
136
  if (engine) engine->Kill(engine);
 
137
}
 
138
 
 
139
int GpActivate(Engine *engine)
 
140
{
 
141
  if (!engine) return 1;
 
142
  if (!engine->active) {
 
143
    engine->active= 1;
 
144
    engine->nextActive= gistActive;
 
145
    gistActive= engine;
 
146
    engine->ChangeMap(engine);
 
147
  }
 
148
  return 0;
 
149
}
 
150
 
 
151
int GpDeactivate(Engine *engine)
 
152
{
 
153
  if (!engine) return 1;
 
154
  if (engine->active) {
 
155
    Engine *active= gistActive;
 
156
    engine->active= 0;
 
157
    if (active==engine) gistActive= engine->nextActive;
 
158
    else {
 
159
      while (active->nextActive!=engine) active= active->nextActive;
 
160
      active->nextActive= engine->nextActive;
 
161
    }
 
162
  }
 
163
  return 0;
 
164
}
 
165
 
 
166
int GpPreempt(Engine *engine)
 
167
{
 
168
  gistPreempt= engine;
 
169
  if (engine && !engine->active) engine->ChangeMap(engine);
 
170
  return 0;
 
171
}
 
172
 
 
173
int GpActive(Engine *engine)
 
174
{
 
175
  if (!engine) return 0;
 
176
  return engine==gistPreempt? 1 : engine->active;
 
177
}
 
178
 
 
179
int GpClear(Engine *engine, int flag)
 
180
{
 
181
  int value= 0;
 
182
  if (!engine) {
 
183
    for (engine=GpNextActive(0) ; engine ; engine=GpNextActive(engine)) {
 
184
      engine->damaged= engine->inhibit= 0;
 
185
      engine->lastDrawn= -1;
 
186
      engine->systemsSeen[0]= engine->systemsSeen[1]= 0;
 
187
      value|= engine->Clear(engine, flag);
 
188
    }
 
189
  } else {
 
190
    engine->damaged= engine->inhibit= 0;
 
191
    engine->lastDrawn= -1;
 
192
    engine->systemsSeen[0]= engine->systemsSeen[1]= 0;
 
193
    value= engine->Clear(engine, flag);
 
194
  }
 
195
  return value;
 
196
}
 
197
 
 
198
int GpFlush(Engine *engine)
 
199
{
 
200
  if (!engine) {
 
201
    int value= 0;
 
202
    for (engine=GpNextActive(0) ; engine ; engine=GpNextActive(engine))
 
203
      value|= engine->Flush(engine);
 
204
    return value;
 
205
  }
 
206
  return engine->Flush(engine);
 
207
}
 
208
 
 
209
Engine *GpNextEngine(Engine *engine)
 
210
{
 
211
  return engine? engine->next : gistEngines;
 
212
}
 
213
 
 
214
Engine *GpNextActive(Engine *engine)
 
215
{
 
216
  if (gistPreempt) return engine? 0 : gistPreempt;
 
217
  else return engine? engine->nextActive : gistActive;
 
218
}
 
219
 
 
220
/* ------------------------------------------------------------------------ */
 
221
 
 
222
int GpSetTrans(const GpTransform *trans)
 
223
{
 
224
  Engine *engine;
 
225
 
 
226
  if (trans!=&gistT) gistT= *trans;
 
227
 
 
228
  for (engine=GpNextActive(0) ; engine ; engine=GpNextActive(engine))
 
229
    engine->ChangeMap(engine);
 
230
 
 
231
  return 0;
 
232
}
 
233
 
 
234
int GpLandscape(Engine *engine, int landscape)
 
235
{
 
236
  if (!engine) {
 
237
    for (engine=GpNextActive(0) ; engine ; engine=GpNextActive(engine))
 
238
      engine->landscape= landscape;
 
239
  } else {
 
240
    engine->landscape= landscape;
 
241
  }
 
242
  return 0;
 
243
}
 
244
 
 
245
void GpSetMap(const GpBox *src, const GpBox *dst, GpXYMap *map)
 
246
{
 
247
  map->x.scale= (dst->xmax-dst->xmin)/(src->xmax-src->xmin);
 
248
  map->x.offset=  dst->xmin - map->x.scale*src->xmin;
 
249
  map->y.scale= (dst->ymax-dst->ymin)/(src->ymax-src->ymin);
 
250
  map->y.offset=  dst->ymin - map->y.scale*src->ymin;
 
251
}
 
252
 
 
253
void GpDeviceMap(Engine *engine)
 
254
{
 
255
  GpSetMap(&engine->transform.viewport, &engine->transform.window,
 
256
           &engine->devMap);
 
257
}
 
258
 
 
259
void GpComposeMap(Engine *engine)
 
260
{
 
261
  GpMap *devx= &engine->devMap.x;
 
262
  GpMap *devy= &engine->devMap.y;
 
263
  GpMap *mapx= &engine->map.x;
 
264
  GpMap *mapy= &engine->map.y;
 
265
  mapx->scale=
 
266
    devx->scale*(gistT.viewport.xmax-gistT.viewport.xmin)/
 
267
                (gistT.window.xmax-gistT.window.xmin);
 
268
  mapx->offset= devx->offset + devx->scale*gistT.viewport.xmin -
 
269
                mapx->scale*gistT.window.xmin;
 
270
  mapy->scale=
 
271
    devy->scale*(gistT.viewport.ymax-gistT.viewport.ymin)/
 
272
                (gistT.window.ymax-gistT.window.ymin);
 
273
  mapy->offset= devy->offset + devy->scale*gistT.viewport.ymin -
 
274
                mapy->scale*gistT.window.ymin;
 
275
}
 
276
 
 
277
/* ------------------------------------------------------------------------ */
 
278
 
 
279
/* Scratch space used by GpIntPoints and GpIntSegs */
 
280
static void *scratch= 0;
 
281
static long scratchPoints= 0, scratchSegs= 0;
 
282
 
 
283
static void MoreScratch(long np, long ns)
 
284
{
 
285
  if (scratch) p_free(scratch);
 
286
  if (np) {
 
287
    np+= 64;
 
288
    scratch= (void *)p_malloc(sizeof(GpPoint)*np);
 
289
    scratchPoints= np;
 
290
    scratchSegs= (sizeof(GpPoint)*np)/sizeof(GpSegment);
 
291
  } else {
 
292
    ns+= 32;
 
293
    scratch= (void *)p_malloc(sizeof(GpSegment)*ns);
 
294
    scratchSegs= ns;
 
295
    scratchPoints= (sizeof(GpSegment)*ns)/sizeof(GpPoint);
 
296
  }
 
297
}
 
298
 
 
299
long GpIntPoints(const GpXYMap *map, long maxPoints, long n,
 
300
                 const GpReal *x, const GpReal *y, GpPoint **result)
 
301
{
 
302
  GpReal scalx= map->x.scale, offx= map->x.offset;
 
303
  GpReal scaly= map->y.scale, offy= map->y.offset;
 
304
  long i, np= maxPoints<n? maxPoints : n;
 
305
  GpPoint *point;
 
306
 
 
307
  if (np+1>scratchPoints) MoreScratch(np+1, 0); /* allow for closure pt */
 
308
  *result= point= scratch;
 
309
 
 
310
  for (i=0 ; i<np ; i++) {
 
311
    point[i].x= (short)(scalx*x[i]+offx);
 
312
    point[i].y= (short)(scaly*y[i]+offy);
 
313
  }
 
314
 
 
315
  return np;
 
316
}
 
317
 
 
318
long GpIntSegs(const GpXYMap *map, long maxSegs, long n,
 
319
               const GpReal *x1, const GpReal *y1,
 
320
               const GpReal *x2, const GpReal *y2, GpSegment **result)
 
321
{
 
322
  GpReal scalx= map->x.scale, offx= map->x.offset;
 
323
  GpReal scaly= map->y.scale, offy= map->y.offset;
 
324
  long i, ns= maxSegs<n? maxSegs : n;
 
325
  GpSegment *seg;
 
326
 
 
327
  if (ns>scratchSegs) MoreScratch(0, ns);
 
328
  *result= seg= scratch;
 
329
 
 
330
  for (i=0 ; i<ns ; i++) {
 
331
    seg[i].x1= (short)(scalx*x1[i]+offx);
 
332
    seg[i].y1= (short)(scaly*y1[i]+offy);
 
333
    seg[i].x2= (short)(scalx*x2[i]+offx);
 
334
    seg[i].y2= (short)(scaly*y2[i]+offy);
 
335
  }
 
336
 
 
337
  return ns;
 
338
}
 
339
 
 
340
/* ------------------------------------------------------------------------ */
 
341
 
 
342
void GpPutGray(int nColors, GpColorCell *palette)
 
343
{
 
344
  /*
 
345
  while (nColors--) {
 
346
    palette->gray=
 
347
      ((int)palette->red+(int)palette->green+(int)palette->blue)/3;
 
348
    palette++;
 
349
  }
 
350
  */
 
351
}
 
352
 
 
353
void GpPutNTSC(int nColors, GpColorCell *palette)
 
354
{
 
355
  /*
 
356
  while (nColors--) {
 
357
    palette->gray=
 
358
      (30*(int)palette->red+59*(int)palette->green+11*(int)palette->blue)/100;
 
359
    palette++;
 
360
  }
 
361
  */
 
362
}
 
363
 
 
364
void GpPutRGB(int nColors, GpColorCell *palette)
 
365
{
 
366
  /*
 
367
  while (nColors--) {
 
368
    palette->red= palette->green= palette->blue= palette->gray;
 
369
    palette++;
 
370
  }
 
371
  */
 
372
}
 
373
 
 
374
int GpSetPalette(Engine *engine, GpColorCell *palette, int nColors)
 
375
{
 
376
  if (!engine) return 0;
 
377
  if (nColors<0) {
 
378
    palette= 0;
 
379
    nColors= 0;
 
380
  }
 
381
  engine->palette= palette;
 
382
  engine->nColors= nColors;
 
383
  engine->colorChange= 1;
 
384
  return engine->ChangePalette(engine);
 
385
}
 
386
 
 
387
int GpGetPalette(Engine *engine, GpColorCell **palette)
 
388
{
 
389
  *palette= engine? engine->palette : 0;
 
390
  return engine? engine->nColors : 0;
 
391
}
 
392
 
 
393
int GpDumpColors(Engine *engine, int colorMode)
 
394
{
 
395
  if (!engine) {
 
396
    for (engine=GpNextActive(0) ; engine ; engine=GpNextActive(engine))
 
397
      { engine->colorMode= colorMode;   engine->colorChange= 1; }
 
398
  } else {
 
399
    engine->colorMode= colorMode;   engine->colorChange= 1;
 
400
  }
 
401
  return 0;
 
402
}
 
403
 
 
404
/* ------------------------------------------------------------------------ */
 
405
 
 
406
long GpClipCells(GpMap *map, GpReal *px, GpReal *qx,
 
407
                 GpReal xmin, GpReal xmax, long ncells, long *off)
 
408
{
 
409
  long imin, imax;
 
410
  GpReal p, q, dx;
 
411
  GpReal scale= map->scale;
 
412
  GpReal offset= map->offset;
 
413
 
 
414
  xmin= xmin*scale+offset;
 
415
  xmax= xmax*scale+offset;
 
416
  if (xmin>xmax) {GpReal tmp=xmin; xmin=xmax; xmax=tmp;}
 
417
  p= (*px)*scale+offset;
 
418
  q= (*qx)*scale+offset;
 
419
 
 
420
  if (p<q && q>=xmin && p<=xmax) {
 
421
    dx= (q-p)/(GpReal)ncells;
 
422
    if (p<xmin) {
 
423
      imin= (long)((xmin-p)/dx);
 
424
      p+= dx*(GpReal)imin;
 
425
    } else {
 
426
      imin= 0;
 
427
    }
 
428
    if (q>xmax) {
 
429
      imax= (long)((q-xmax)/dx);
 
430
      q-= dx*(GpReal)imax;
 
431
      imax= ncells-imax;
 
432
    } else {
 
433
      imax= ncells;
 
434
    }
 
435
    if (imax-imin<2) {
 
436
      if (imax==imin) {
 
437
        if (p<xmin) p= xmin;
 
438
        if (q>xmax) q= xmax;
 
439
      } else {
 
440
        if (p<xmin && q>xmax) {
 
441
          if (q-xmax > xmin-p) { q-= xmin-p;  p= xmin; }
 
442
          else { p+= q-xmax;  q= xmax; }
 
443
        }
 
444
      }
 
445
    }
 
446
  } else if (p>q && p>=xmin && q<=xmax) {
 
447
    dx= (p-q)/(GpReal)ncells;
 
448
    if (q<xmin) {
 
449
      imax= (long)((xmin-q)/dx);
 
450
      q+= dx*(GpReal)imax;
 
451
      imax= ncells-imax;
 
452
    } else {
 
453
      imax= ncells;
 
454
    }
 
455
    if (p>xmax) {
 
456
      imin= (long)((p-xmax)/dx);
 
457
      p-= dx*(GpReal)imin;
 
458
    } else {
 
459
      imin= 0;
 
460
    }
 
461
    if (imax-imin<2) {
 
462
      if (imax==imin) {
 
463
        if (q<xmin) q= xmin;
 
464
        if (p>xmax) p= xmax;
 
465
      } else {
 
466
        if (q<xmin && p>xmax) {
 
467
          if (p-xmax > xmin-q) { p-= xmin-q;  q= xmin; }
 
468
          else { q+= p-xmax;  p= xmax; }
 
469
        }
 
470
      }
 
471
    }
 
472
  } else {
 
473
    imin= 0;
 
474
    imax= -1;
 
475
  }
 
476
 
 
477
  *px= p;
 
478
  *qx= q;
 
479
  *off= imin;
 
480
 
 
481
  return imax-imin;
 
482
}
 
483
 
 
484
/* ------------------------------------------------------------------------ */
 
485
 
 
486
int GpIntersect(const GpBox *box1, const GpBox *box2)
 
487
{
 
488
  /* Algorithm assumes min<max for x and y in both boxes */
 
489
  return box1->xmin<=box2->xmax && box1->xmax>=box2->xmin &&
 
490
         box1->ymin<=box2->ymax && box1->ymax>=box2->ymin;
 
491
}
 
492
 
 
493
int GpContains(const GpBox *box1, const GpBox *box2)
 
494
{
 
495
  /* Algorithm assumes min<max for x and y in both boxes */
 
496
  return box1->xmin<=box2->xmin && box1->xmax>=box2->xmax &&
 
497
         box1->ymin<=box2->ymin && box1->ymax>=box2->ymax;
 
498
}
 
499
 
 
500
void GpSwallow(GpBox *preditor, const GpBox *prey)
 
501
{
 
502
  /* Algorithm assumes min<max for x and y in both boxes */
 
503
  if (preditor->xmin>prey->xmin) preditor->xmin= prey->xmin;
 
504
  if (preditor->xmax<prey->xmax) preditor->xmax= prey->xmax;
 
505
  if (preditor->ymin>prey->ymin) preditor->ymin= prey->ymin;
 
506
  if (preditor->ymax<prey->ymax) preditor->ymax= prey->ymax;
 
507
}
 
508
 
 
509
/* ------------------------------------------------------------------------ */
 
510
 
 
511
/* These recondite routines are required to handle editing a drawing
 
512
   on one or more interactive engines.  The restriction to few
 
513
   routines builds in certain inefficiencies; if every drawing were always
 
514
   associated with one interactive engine some of the inefficiency could
 
515
   be reduced.  These are not intended for external use.  */
 
516
 
 
517
extern int gdNowRendering, gdMaxRendered;
 
518
int gdNowRendering= -1;
 
519
int gdMaxRendered= -1;
 
520
 
 
521
int GdBeginDr(Drauing *drawing, GpBox *damage, int landscape)
 
522
{
 
523
  int needToRedraw= 0;
 
524
  Engine *eng;
 
525
 
 
526
  if (damage) {
 
527
    /* If drawing has incurred damage, report damage to ALL engines
 
528
       interested in the drawing (not just active engines).  */
 
529
    for (eng=GpNextEngine(0) ; eng ; eng=GpNextEngine(eng))
 
530
      if (eng->drawing==drawing) GpDamage(eng, drawing, damage);
 
531
  }
 
532
 
 
533
  /* Loop on active engines to alert them that drawing is coming.  */
 
534
  for (eng=GpNextActive(0) ; eng ; eng=GpNextActive(eng)) {
 
535
    if (eng->drawing!=drawing) {
 
536
      /* This engine is not marked as interested in this drawing.
 
537
         Mark it, and reset damaged and lastDrawn flags so that no
 
538
         elements will be inhibited.  */
 
539
      eng->drawing= drawing;
 
540
      eng->lastDrawn= -1;
 
541
      eng->damaged= 0;
 
542
      if (landscape != eng->landscape) {
 
543
        eng->landscape= landscape;
 
544
        /* This change will be detected and acted upon by the first call
 
545
           to the ChangeMap method (GpSetTrans).  */
 
546
      }
 
547
      /* The semantics here are subtle --
 
548
         After a ClearDrawing, GdDetach zeroes eng->drawing in order to
 
549
         communicate that the drawing has been cleared.  Thus, the code
 
550
         gets here on a GdDraw after the drawing has been cleared, so
 
551
         the time has come to carry out the deferred clearing of this
 
552
         engine's plotting surface.  */
 
553
      GpClear(eng, CONDITIONALLY);
 
554
      needToRedraw= 1;
 
555
 
 
556
    } else if (eng->damaged) {
 
557
      /* This engine was interested in the drawing, which has been
 
558
         damaged.  Clear damaged area in preparation for repair work.
 
559
         (This is redundant if the damage was due to an X windows
 
560
          expose event, but the resulting inefficiency is very small.)  */
 
561
      eng->ClearArea(eng, &eng->damage);
 
562
      needToRedraw= 1;
 
563
 
 
564
    } else if (eng->lastDrawn<drawing->nElements-1) {
 
565
      needToRedraw= 1;
 
566
    }
 
567
  }
 
568
 
 
569
  gdNowRendering= gdMaxRendered= -1;
 
570
  return needToRedraw;
 
571
}
 
572
 
 
573
int GdBeginSy(GpBox *tickOut, GpBox *tickIn, GpBox *viewport,
 
574
              int number, int sysIndex)
 
575
{
 
576
  Engine *eng;
 
577
  int value= 0;
 
578
  long sysMask;
 
579
 
 
580
  /* Note that this is harmless if sysIndex>2*sizeof(long)--
 
581
     just slightly inefficient in that ticks and elements will ALWAYS
 
582
     be drawn...  This shouldn't be a practical problem.  */
 
583
  if (sysIndex>sizeof(long)) {
 
584
    sysMask= 1 << (sysIndex-sizeof(long));
 
585
    sysIndex= 1;
 
586
  } else {
 
587
    sysMask= 1 << sysIndex;
 
588
    sysIndex= 0;
 
589
  }
 
590
 
 
591
  /* Loop on active engines to determine whether any require ticks or
 
592
     elements to be drawn.  Set inhibit switches for ticks.  */
 
593
  for (eng=GpNextActive(0) ; eng ; eng=GpNextActive(eng)) {
 
594
    if ( ! (eng->systemsSeen[sysIndex] & sysMask) ) {
 
595
      /* this engine has never seen this system */
 
596
      value|= 3;
 
597
      eng->inhibit= 0;
 
598
      eng->systemsSeen[sysIndex]|= sysMask;
 
599
 
 
600
    } else if (eng->damaged && GpIntersect(tickOut, &eng->damage)) {
 
601
      /* engine damage touches this coordinate system--
 
602
         redraw ticks if region between tickIn and tickOut damaged,
 
603
         redraw elements if viewport damaged */
 
604
      if (!tickIn || !GpContains(tickIn, &eng->damage)) {
 
605
        value|= 2;
 
606
        eng->inhibit= 0;
 
607
      } else eng->inhibit= 1;
 
608
      if (number>eng->lastDrawn || GpIntersect(viewport, &eng->damage))
 
609
        value|= 1;
 
610
 
 
611
    } else {
 
612
      /* engine undamaged or damage doesn't touch this system--
 
613
         redraw elements if any new ones, don't redraw ticks */
 
614
      eng->inhibit= 1;
 
615
      if (number>eng->lastDrawn) value|= 1;
 
616
    }
 
617
  }
 
618
 
 
619
  return value;
 
620
}
 
621
 
 
622
int GdBeginEl(GpBox *box, int number)
 
623
{
 
624
  Engine *eng;
 
625
  int value= 0;
 
626
 
 
627
  /* Loop on active engines to determine whether any require this
 
628
     element to be drawn, and to set inhibit switches so that some
 
629
     may draw it and others not.  */
 
630
  for (eng=GpNextActive(0) ; eng ; eng=GpNextActive(eng)) {
 
631
    if (number>eng->lastDrawn) {
 
632
      /* this engine hasn't seen this element before */
 
633
      eng->inhibit= 0;
 
634
      value= 1;
 
635
      if (eng->damaged && gdMaxRendered<=eng->lastDrawn) {
 
636
        /* If this is the first new element, the damage flag
 
637
           must be reset, and ChangeMap must be called to set the
 
638
           clip rectangle back to its undamaged boundary.  */
 
639
        eng->damaged= 0;
 
640
        eng->ChangeMap(eng);
 
641
      }
 
642
 
 
643
    } else if (box && eng->damaged && GpIntersect(box, &eng->damage)) {
 
644
      /* engine damage touches this element */
 
645
      eng->inhibit= 0;
 
646
      value= 1;
 
647
 
 
648
    } else {
 
649
      /* this element has been seen before and hasn't been damaged */
 
650
      eng->inhibit= 1;
 
651
    }
 
652
 
 
653
    /* set number of element currently being drawn for GdEndDr */
 
654
    gdNowRendering= number;
 
655
    if (gdMaxRendered<gdNowRendering) gdMaxRendered= gdNowRendering;
 
656
  }
 
657
 
 
658
  return value;
 
659
}
 
660
 
 
661
void GdEndDr(void)
 
662
{
 
663
  Engine *eng;
 
664
  /* Done with this drawing- reset inhibit, damaged, and lastDrawn flags */
 
665
  for (eng=GpNextActive(0) ; eng ; eng=GpNextActive(eng)) {
 
666
    if (eng->lastDrawn<gdMaxRendered) eng->lastDrawn= gdMaxRendered;
 
667
    eng->inhibit= eng->damaged= 0;
 
668
  }
 
669
}
 
670
 
 
671
void GpDamage(Engine *eng, Drauing *drawing, GpBox *box)
 
672
{
 
673
  if (eng->drawing!=drawing || !eng->marked) return;
 
674
  if (eng->ClearArea==&DefaultClearArea) {
 
675
    /* This engine doesn't need to record the damage box */
 
676
    eng->damaged= 1;
 
677
  } else if (eng->damaged) {
 
678
    /* drawing is already damaged on this engine */
 
679
    if (eng->damage.xmin>box->xmin) eng->damage.xmin= box->xmin;
 
680
    if (eng->damage.xmax<box->xmax) eng->damage.xmax= box->xmax;
 
681
    if (eng->damage.ymin>box->ymin) eng->damage.ymin= box->ymin;
 
682
    if (eng->damage.ymax<box->ymax) eng->damage.ymax= box->ymax;
 
683
  } else {
 
684
    /* drawing is currently undamaged on this engine */
 
685
    eng->damaged= 1;
 
686
    eng->damage= *box;
 
687
  }
 
688
}
 
689
 
 
690
void GdDetach(Drauing *drawing, Engine *engine)
 
691
{
 
692
  Engine *eng;
 
693
  for (eng=GpNextEngine(0) ; eng ; eng=GpNextEngine(eng)) {
 
694
    if (!drawing || eng->drawing==drawing) {
 
695
      eng->drawing= 0;
 
696
      eng->inhibit= eng->damaged= 0;
 
697
      eng->lastDrawn= -1;
 
698
    }
 
699
  }
 
700
}
 
701
 
 
702
/* ------------------------------------------------------------------------ */