1 /* -*- tab-width: 4 -*-
2 *
3 * Electric(tm) VLSI Design System
4 *
5 * File: ioquickdraw.c
6 * Input/output analysis tool: plotter output on Macintosh
7 * Written by: Steven M. Rubin, Static Free Software
8 *
9 * Copyright (c) 2000 Static Free Software.
10 *
11 * Electric(tm) is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * Electric(tm) is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with Electric(tm); see the file COPYING. If not, write to
23 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
24 * Boston, Mass 02111-1307, USA.
25 *
26 * Static Free Software
27 * 4119 Alpine Road
28 * Portola Valley, California 94028
29 * info@staticfreesoft.com
30 */
31
32 #include "config.h"
33 #ifdef MACOS
34
35 #include "global.h"
36 #include "egraphics.h"
37 #include "eio.h"
38 #include "usr.h"
39 #include "efunction.h"
40
41 #include <Fonts.h>
42 #include <Printing.h>
43 #include <Scrap.h>
44 #include <QDOffscreen.h>
45
46 #define THRESH 2000000
47 #ifdef __MWERKS__
48 # if __MWERKS__ >= 0x2300
49 # define NEWCODEWARRIOR 1
50 # endif
51 #endif
52 #ifdef NEWCODEWARRIOR
53 # define EFONT kFontIDTimes
54 # define HFONT kFontIDHelvetica
55 #else
56 # define EFONT times
57 # define HFONT helvetica
58 #endif
59
60 GRAPHICS io_black = {LAYERO, BLACK, SOLIDC, SOLIDC,
61 {0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF}, NOVARIABLE, 0};
62 static WINDOWPART *io_plotwindow;
63 static INTBIG io_plotrevy;
64 static INTBIG io_slx, io_shx, io_sly, io_shy;
65 static INTBIG io_ulx, io_uhx, io_uly, io_uhy;
66 static WindowPtr io_plotwin;
67 static INTBIG io_thislayer, io_maxlayer;
68
69 void io_setplotlayer(INTBIG);
70 void io_setbounds(INTBIG, INTBIG, INTBIG, INTBIG, INTBIG, INTBIG, INTBIG, INTBIG, INTBIG, WindowPtr);
71 void io_plotpoly(POLYGON*, WINDOWPART*);
72 void io_plotdot(INTBIG, INTBIG);
73 void io_plotline(INTBIG, INTBIG, INTBIG, INTBIG, INTBIG);
74 void io_plotpolygon(INTBIG*, INTBIG*, INTBIG, INTBIG, GRAPHICS*);
75 void io_plottext(INTBIG, INTBIG, INTBIG, INTBIG, INTBIG, INTBIG, CHAR*);
76 void io_xform(INTBIG*, INTBIG*);
77 void io_maccopyhighlighted(void);
78
79 /*
80 * routine to write out a file to the Macintosh/Quickdraw system
81 */
io_writequickdrawlibrary(LIBRARY * lib)82 BOOLEAN io_writequickdrawlibrary(LIBRARY *lib)
83 {
84 REGISTER NODEPROTO *np;
85 INTBIG err, ix, swid, shei;
86 INTBIG hlx, hhx, hly, hhy, gridlx, gridly, gridx, gridy, cx, cy, prod1, prod2, i,
87 revy, slx, shx, sly, shy, ulx, uhx, uly, uhy, sxs, sys, dxs, dys, saver, saveg,
88 saveb, white, *curstate, lambda;
89 VARIABLE *var;
90 REGISTER VARIABLE *varred, *vargreen, *varblue;
91 static POLYGON *poly = NOPOLYGON;
92 static THPrint hPrint = 0;
93 TPPrPort plotwin;
94 TPrStatus prstat;
95 Rect sr, dr;
96 CGrafPtr window, gra_getoffscreen(WINDOWPART *);
97 REGISTER void *infstr;
98
99 np = lib->curnodeproto;
100 if (np == NONODEPROTO)
101 {
102 if ((el_curwindowpart->state&WINDOWTYPE) == EXPLORERWINDOW)
103 {
104 ttyputmsg(_("Cannot convert Explorer window to Quickdraw. Export PostScript instead"));
105 return(TRUE);
106 }
107 ttyputerr(_("No current cell to plot"));
108 return(TRUE);
109 }
110
111 /* cannot write text-only cells */
112 if ((np->cellview->viewstate&TEXTVIEW) != 0)
113 {
114 ttyputerr(_("Cannot write textual cells"));
115 return(TRUE);
116 }
117
118 /* get printing control bits */
119 curstate = io_getstatebits();
120
121 /* determine area to plot */
122 if (io_getareatoprint(np, &slx, &shx, &sly, ­, TRUE)) return(TRUE);
123
124 /* open the window (to the printer) */
125 PrOpen();
126 if ((err = PrError()) != noErr)
127 {
128 ttyputerr(_("Printer error %ld"), err);
129 return(TRUE);
130 }
131
132 /* see if any printing has already been done */
133 if (hPrint == 0)
134 {
135 /* this is the first print: create print record and do "Page Setup" dialog */
136 hPrint = (THPrint)NewHandle(sizeof (TPrint));
137 if (hPrint == 0)
138 {
139 ttyputerr(_("Cannot allocate print record"));
140 return(TRUE);
141 }
142 PrintDefault(hPrint);
143 if ((err = PrError()) != noErr)
144 {
145 ttyputerr(_("Printer error %ld"), err);
146 return(TRUE);
147 }
148 if (!PrStlDialog(hPrint)) return(TRUE);
149 } else
150 {
151 /* have already printed: validate print record */
152 PrValidate(hPrint);
153 if ((err = PrError()) != noErr)
154 {
155 ttyputerr(_("Printer error %ld"), err);
156 return(TRUE);
157 }
158 }
159
160 /* do the "Print..." dialog */
161 if (!PrJobDialog(hPrint)) return(TRUE);
162
163 /* open the pseudo-window to the printer */
164 plotwin = PrOpenDoc(hPrint, 0, 0);
165 PrOpenPage(plotwin, 0);
166 if (PrError())
167 {
168 ttyputerr(_("Error opening print page"));
169 return(TRUE);
170 }
171 SetPort((WindowPtr)plotwin);
172
173 /* save background color and make it white */
174 varred = getvalkey((INTBIG)us_tool, VTOOL, VINTEGER|VISARRAY, us_colormap_red_key);
175 vargreen = getvalkey((INTBIG)us_tool, VTOOL, VINTEGER|VISARRAY, us_colormap_green_key);
176 varblue = getvalkey((INTBIG)us_tool, VTOOL, VINTEGER|VISARRAY, us_colormap_blue_key);
177 if (varred == NOVARIABLE || vargreen == NOVARIABLE || varblue == NOVARIABLE) return(TRUE);
178 saver = ((INTBIG *)varred->addr)[0];
179 saveg = ((INTBIG *)vargreen->addr)[0];
180 saveb = ((INTBIG *)varblue->addr)[0];
181 white = 0xFF;
182 colormapload(&white, &white, &white, 0, 0);
183
184 /* see if the printer is color */
185 if ((plotwin->gPort.portBits.rowBytes & 0xC000) == 0xC000)
186 {
187 /* special case for color printing */
188 hlx = slx; hhx = shx;
189 hly = sly; hhy = shy;
190 (void)us_makescreen(&hlx, &hly, &hhx, &hhy, el_curwindowpart);
191 sr.left = hlx; sr.right = hhx;
192
193 getwindowframesize(el_curwindowpart->frame, &swid, &shei);
194 revy = shei - 1;
195
196 sr.top = revy - hhy; sr.bottom = revy - hly;
197 sr.bottom++;
198 dr = plotwin->gPort.portRect;
199
200 /* ensure that the destination has the same aspect ratio as the source */
201 sxs = hhx - hlx; sys = hhy - hly;
202 dxs = dr.right - dr.left; dys = dr.bottom - dr.top;
203 if (dxs*sys > dys*sxs)
204 {
205 i = dys * sxs / sys;
206 dr.left += (dxs-i) / 2;
207 dr.right = dr.left + i;
208 } else
209 {
210 i = dxs * sys / sxs;
211 dr.top += (dys-i) / 2;
212 dr.bottom = dr.top + i;
213 }
214
215 /* now copy the offscreen bits at "sr" to the print port at "dr" */
216 window = gra_getoffscreen(el_curwindowpart);
217 (void)LockPixels(window->portPixMap);
218 CopyBits((BitMap *)*(window->portPixMap), &plotwin->gPort.portBits,
219 &sr, &dr, srcCopy, 0L);
220 UnlockPixels(window->portPixMap);
221
222 PrClosePage(plotwin);
223 PrCloseDoc(plotwin);
224
225 /* print if spooled */
226 if ((*hPrint)->prJob.bJDocLoop == bSpoolLoop)
227 {
228 PrPicFile(hPrint, 0, 0, 0, &prstat);
229 if (PrError())
230 ttyputerr(_("Error queuing print page"));
231 }
232 PrClose();
233
234 /* restore background color */
235 colormapload(&saver, &saveg, &saveb, 0, 0);
236 return(FALSE);
237 }
238
239 TextFont(EFONT);
240
241 /* establish order of plotting layers */
242 io_maxlayer = io_setuptechorder(el_curtech);
243
244 /* determine scaling */
245 ulx = plotwin->gPort.portRect.left;
246 uly = plotwin->gPort.portRect.top;
247 uhx = plotwin->gPort.portRect.right;
248 uhy = plotwin->gPort.portRect.bottom;
249 revy = plotwin->gPort.portRect.bottom - plotwin->gPort.portRect.top;
250
251 prod1 = shx - slx;
252 prod2 = shy - sly;
253 if (prod1 > THRESH || prod2 > THRESH)
254 {
255 /* screen extents too large: scale them down please */
256 prod1 /= 1000; prod2 /= 1000;
257 }
258 prod1 *= uhy - uly;
259 prod2 *= uhx - ulx;
260 if (prod1 != prod2)
261 {
262 /* adjust the scale */
263 if (prod1 > prod2)
264 {
265 /* screen extent is too wide for window */
266 i = (shx - slx) / 20;
267 if (i == 0) i++;
268 shx += i; slx -= i;
269 i = muldiv(shx - slx, uhy - uly, uhx - ulx) - (shy - sly);
270 sly -= i/2;
271 shy += i/2;
272 } else
273 {
274 /* screen extent is too tall for window */
275 i = (shy - sly) / 20;
276 if (i == 0) i++;
277 shy += i; sly -= i;
278 i = muldiv(shy - sly, uhx - ulx, uhy - uly) - (shx - slx);
279 slx -= i/2;
280 shx += i/2;
281 }
282 }
283 io_setbounds(slx, shx, sly, shy, ulx, uhx, uly, uhy, revy, (WindowPtr)plotwin);
284
285 /* draw the grid if requested */
286 if ((el_curwindowpart->state&(GRIDON|GRIDTOOSMALL)) == GRIDON)
287 {
288 lambda = lib->lambda[np->tech->techindex];
289 gridx = muldiv(el_curwindowpart->gridx, lambda, WHOLE);
290 gridy = muldiv(el_curwindowpart->gridy, lambda, WHOLE);
291 var = getvalkey((INTBIG)us_tool, VTOOL, VINTEGER, us_gridfloatskey);
292 if (var == NOVARIABLE || var->addr == 0)
293 {
294 gridlx = np->lowx / gridx * gridx;
295 gridly = np->lowy / gridy * gridy;
296 } else
297 {
298 grabpoint(np, &gridlx, &gridly);
299 gridalign(&gridlx, &gridly, 1, np);
300 gridlx += gridlx / gridx * gridx;
301 gridly += gridly / gridy * gridy;
302 }
303
304 /* adjust to ensure that the first point is inside the range */
305 while (gridlx < slx) gridlx += gridx;
306 while (gridly < sly) gridly += gridy;
307
308 /* plot the loop to the printer */
309 for(cx = gridlx; cx <= shx; cx += gridx)
310 for(cy = gridly; cy <= shy; cy += gridy)
311 io_plotdot(cx, cy);
312 }
313
314 /* plot layers in this technology in proper order */
315 for(ix=0; ix<io_maxlayer; ix++)
316 {
317 /* first plot outlines around stipple layers */
318 io_setplotlayer(-(io_nextplotlayer(ix) + 1));
319 (void)asktool(us_tool, x_("display-to-routine"), io_plotpoly);
320
321 /* next plot layers */
322 io_setplotlayer(io_nextplotlayer(ix) + 1);
323 (void)asktool(us_tool, x_("display-to-routine"), io_plotpoly);
324 }
325
326 /* finally plot layers not in the technology */
327 io_setplotlayer(0);
328 (void)asktool(us_tool, x_("display-to-routine"), io_plotpoly);
329
330 /* put out dates if requested */
331 if ((curstate[0]&PLOTDATES) != 0)
332 {
333 /* create the polygon if it doesn't exist */
334 (void)needstaticpolygon(&poly, 1, io_tool->cluster);
335
336 /* plot cell name */
337 infstr = initinfstr();
338 formatinfstr(infstr, _("Cell: %s"), describenodeproto(np));
339 poly->string = returninfstr(infstr);
340 poly->xv[0] = np->highx;
341 poly->yv[0] = np->lowy;
342 poly->count = 1;
343 poly->style = TEXTBOTRIGHT;
344 TDCLEAR(poly->textdescript);
345 TDSETSIZE(poly->textdescript, TXTSETQLAMBDA(4));
346 poly->tech = el_curtech;
347 poly->desc = &io_black;
348 (void)io_plotpoly(poly, el_curwindowpart);
349
350 /* plot creation date */
351 infstr = initinfstr();
352 formatinfstr(infstr, _("Created: %s"), timetostring((time_t)np->creationdate));
353 poly->string = returninfstr(infstr);
354 poly->yv[0] = np->lowy + (np->highy-np->lowy) / 20;
355 (void)io_plotpoly(poly, el_curwindowpart);
356
357 /* plot revision date */
358 infstr = initinfstr();
359 formatinfstr(infstr, _("Revised: %s"), timetostring((time_t)np->revisiondate));
360 poly->string = returninfstr(infstr);
361 poly->yv[0] = np->lowy + (np->highy-np->lowy) / 10;
362 (void)io_plotpoly(poly, el_curwindowpart);
363 }
364
365 /* clean up */
366 PrClosePage(plotwin);
367 PrCloseDoc(plotwin);
368
369 /* print if spooled */
370 if ((*hPrint)->prJob.bJDocLoop == bSpoolLoop)
371 {
372 PrPicFile(hPrint, 0, 0, 0, &prstat);
373 }
374 PrClose();
375
376 /* restore background color */
377 colormapload(&saver, &saveg, &saveb, 0, 0);
378 return(FALSE);
379 }
380
381 /******************** LAYER ORDERING FOR GRAPHIC COPY/PRINT ********************/
382
383 /*
384 * Routine to set the current plotting layer to "i".
385 */
io_setplotlayer(INTBIG i)386 void io_setplotlayer(INTBIG i)
387 {
388 io_thislayer = i;
389 }
390
391 /******************** POLYGON DISPLAY FOR GRAPHIC COPY/PRINT ********************/
392
io_setbounds(INTBIG slx,INTBIG shx,INTBIG sly,INTBIG shy,INTBIG ulx,INTBIG uhx,INTBIG uly,INTBIG uhy,INTBIG revy,WindowPtr window)393 void io_setbounds(INTBIG slx, INTBIG shx, INTBIG sly, INTBIG shy, INTBIG ulx, INTBIG uhx,
394 INTBIG uly, INTBIG uhy, INTBIG revy, WindowPtr window)
395 {
396 static WINDOWPART plotwindow;
397
398 io_plotwindow = &plotwindow;
399 io_plotrevy = revy;
400 io_plotwin = window;
401 plotwindow.screenlx = io_slx = slx;
402 plotwindow.screenhx = io_shx = shx;
403 plotwindow.screenly = io_sly = sly;
404 plotwindow.screenhy = io_shy = shy;
405 plotwindow.uselx = io_ulx = ulx;
406 plotwindow.usehx = io_uhx = uhx;
407 plotwindow.usely = io_uly = uly;
408 plotwindow.usehy = io_uhy = uhy;
409 plotwindow.state = DISPWINDOW;
410 computewindowscale(&plotwindow);
411 }
412
413 /*
414 * routine to plot the polygon "poly"
415 */
io_plotpoly(POLYGON * poly,WINDOWPART * win)416 void io_plotpoly(POLYGON *poly, WINDOWPART *win)
417 {
418 REGISTER INTBIG k, type;
419 INTBIG xl, xh, yl, yh, x, y, listx[4], listy[4], size,
420 centerx, centery, x1p, y1p, x2p, y2p, xa, ya, xb, yb, radius;
421 INTBIG startangle, endangle, amt, style;
422 UCHAR1 pat[8];
423 Rect r;
424 static POLYGON *polyspline = NOPOLYGON;
425 REGISTER TECHNOLOGY *tech;
426
427 /* ignore null layers */
428 if (poly->desc->bits == LAYERN || poly->desc->col == ALLOFF) return;
429
430 /* only plot the desired layer */
431 if (io_thislayer < 0)
432 {
433 /* first outline filled areas in proper order */
434 if (poly->layer != -io_thislayer-1) return;
435 if (poly->style != FILLED && poly->style != FILLEDRECT) return;
436 if (isbox(poly, &xl, &xh, &yl, &yh))
437 {
438 if (xl == xh || yl == yh) return;
439 io_xform(&xl, &yl);
440 io_xform(&xh, &yh);
441 xl--; yh++;
442 SetPort(io_plotwin);
443 PenMode(patCopy);
444 PenPat(&qd.black);
445 MoveTo(xl, io_plotrevy-yl);
446 LineTo(xl, io_plotrevy-yh);
447 LineTo(xh, io_plotrevy-yh);
448 LineTo(xh, io_plotrevy-yl);
449 LineTo(xl, io_plotrevy-yl);
450 } else
451 {
452 /* outlining stipple: expand polygon */
453 if (poly->count <= 2) return;
454 centerx = centery = 0;
455 for(k=0; k<poly->count; k++)
456 {
457 centerx += poly->xv[k]; centery += poly->yv[k];
458 }
459 centerx /= poly->count; centery /= poly->count;
460 io_xform(¢erx, ¢ery);
461 for(k=0; k<poly->count; k++)
462 {
463 if (k == 0)
464 {
465 x1p = poly->xv[poly->count-1]; y1p = poly->yv[poly->count-1];
466 } else
467 {
468 x1p = poly->xv[k-1]; y1p = poly->yv[k-1];
469 }
470 x2p = poly->xv[k]; y2p = poly->yv[k];
471 io_xform(&x1p, &y1p);
472 io_xform(&x2p, &y2p);
473 if (x1p < centerx) x1p--;
474 if (y1p > centery) y1p++;
475 if (x2p < centerx) x2p--;
476 if (y2p > centery) y2p++;
477 SetPort(io_plotwin);
478 PenMode(patCopy);
479 PenPat(&qd.black);
480 MoveTo(x1p, io_plotrevy-y1p);
481 LineTo(x2p, io_plotrevy-y2p);
482 }
483 }
484 return;
485 }
486
487 if (io_thislayer > 0)
488 {
489 /* then draw layers in proper order */
490 if (poly->layer != io_thislayer-1) return;
491 } else
492 {
493 /* final pass: draw layers not in the technology */
494 for(k=0; k<io_maxlayer; k++) if (io_nextplotlayer(k) == poly->layer) return;
495 }
496
497 /* ignore grids */
498 if (poly->style == GRIDDOTS) return;
499 style = poly->desc->bwstyle;
500
501 switch (poly->style)
502 {
503 case FILLED:
504 case FILLEDRECT:
505 if (isbox(poly, &xl, &xh, &yl, &yh))
506 {
507 if (xl == xh)
508 {
509 if (yl == yh) io_plotdot(xl, yl); else
510 io_plotline(xl, yl, xl, yh, 0);
511 break;
512 } else if (yl == yh)
513 {
514 io_plotline(xl, yl, xh, yl, 0);
515 break;
516 }
517 listx[0] = xl; listy[0] = yl;
518 listx[1] = xl; listy[1] = yh;
519 listx[2] = xh; listy[2] = yh;
520 listx[3] = xh; listy[3] = yl;
521 io_plotpolygon(listx, listy, 4, style, poly->desc);
522 } else
523 {
524 if (poly->count == 1)
525 {
526 io_plotdot(poly->xv[0], poly->yv[0]);
527 break;
528 }
529 if (poly->count == 2)
530 {
531 io_plotline(poly->xv[0], poly->yv[0], poly->xv[1], poly->yv[1], 0);
532 break;
533 }
534 io_plotpolygon(poly->xv, poly->yv, poly->count, style, poly->desc);
535 }
536 break;
537
538 case CLOSED:
539 case CLOSEDRECT:
540 case OPENED:
541 case OPENEDT1:
542 case OPENEDT2:
543 case OPENEDT3:
544 switch (poly->style)
545 {
546 case OPENEDT1: type = 1; break;
547 case OPENEDT2: type = 2; break;
548 case OPENEDT3: type = 3; break;
549 default: type = 0; break;
550 }
551 if (isbox(poly, &xl, &xh, &yl, &yh))
552 {
553 io_plotline(xl, yl, xl, yh, type);
554 io_plotline(xl, yh, xh, yh, type);
555 io_plotline(xh, yh, xh, yl, type);
556 if (poly->style == CLOSED || poly->style == CLOSEDRECT)
557 io_plotline(xh, yl, xl, yl, type);
558 break;
559 }
560 for (k = 1; k < poly->count; k++)
561 io_plotline(poly->xv[k-1], poly->yv[k-1], poly->xv[k], poly->yv[k], type);
562 if (poly->style == CLOSED || poly->style == CLOSEDRECT)
563 {
564 k = poly->count - 1;
565 io_plotline(poly->xv[k], poly->yv[k], poly->xv[0], poly->yv[0], type);
566 }
567 break;
568
569 case VECTORS:
570 for(k=0; k<poly->count; k += 2)
571 io_plotline(poly->xv[k], poly->yv[k], poly->xv[k+1], poly->yv[k+1], 0);
572 break;
573
574 case CROSS:
575 case BIGCROSS:
576 getcenter(poly, &x, &y);
577 io_plotline(x-5, y, x+5, y, 0);
578 io_plotline(x, y+5, x, y-5, 0);
579 break;
580
581 case CROSSED:
582 getbbox(poly, &xl, &xh, &yl, &yh);
583 io_plotline(xl, yl, xl, yh, 0);
584 io_plotline(xl, yh, xh, yh, 0);
585 io_plotline(xh, yh, xh, yl, 0);
586 io_plotline(xh, yl, xl, yl, 0);
587 io_plotline(xh, yh, xl, yl, 0);
588 io_plotline(xh, yl, xl, yh, 0);
589 break;
590
591 case DISC:
592 /* filled disc: plot it and its outline (B&W) */
593 centerx = poly->xv[0]; centery = poly->yv[0];
594 xa = poly->xv[1]; ya = poly->yv[1];
595 io_xform(¢erx, ¢ery);
596 io_xform(&xa, &ya);
597 for(k=0; k<8; k++)
598 pat[k] = (style != PATTERNED ? 0xFF : poly->desc->raster[k]);
599 radius = computedistance(centerx, centery, xa, ya);
600 r.left = centerx - radius;
601 r.right = centerx + radius + 1;
602 r.top = io_plotrevy - centery - radius;
603 r.bottom = io_plotrevy - centery + radius + 1;
604 SetPort(io_plotwin);
605 PenMode(patCopy);
606 PenPat((PatPtr)pat);
607 PaintOval(&r);
608
609 case CIRCLE: case THICKCIRCLE:
610 centerx = poly->xv[0]; centery = poly->yv[0];
611 xa = poly->xv[1]; ya = poly->yv[1];
612 io_xform(¢erx, ¢ery);
613 io_xform(&xa, &ya);
614 radius = computedistance(centerx, centery, xa, ya);
615 r.left = centerx - radius;
616 r.right = centerx + radius + 1;
617 r.top = io_plotrevy - centery - radius;
618 r.bottom = io_plotrevy - centery + radius + 1;
619 SetPort(io_plotwin);
620 PenMode(patCopy);
621 PenPat(&qd.black);
622 FrameOval(&r);
623 break;
624
625 case CIRCLEARC: case THICKCIRCLEARC:
626 centerx = poly->xv[0]; centery = poly->yv[0];
627 xa = poly->xv[1]; ya = poly->yv[1];
628 xb = poly->xv[2]; yb = poly->yv[2];
629 io_xform(¢erx, ¢ery);
630 io_xform(&xa, &ya);
631 io_xform(&xb, &yb);
632
633 radius = computedistance(centerx, centery, xa, ya);
634 startangle = figureangle(centerx, centery, xa, ya);
635 endangle = figureangle(centerx, centery, xb, yb);
636 if (startangle > endangle) amt = (startangle - endangle + 5) / 10; else
637 amt = (startangle - endangle + 3600 + 5) / 10;
638 startangle = ((4500-startangle) % 3600 + 5) / 10;
639 r.left = centerx - radius;
640 r.right = centerx + radius + 1;
641 centery = io_plotrevy - centery;
642 r.top = centery - radius;
643 r.bottom = centery + radius + 1;
644 ya = io_plotrevy - ya; yb = io_plotrevy - yb;
645 if (centerx == xa)
646 {
647 if (abs(r.top-ya) < abs(r.bottom-ya)) r.top = ya; else r.bottom = ya+1;
648 }
649 if (centerx == xb)
650 {
651 if (abs(r.top-yb) < abs(r.bottom-yb)) r.top = yb; else r.bottom = yb+1;
652 }
653 if (centery == ya)
654 {
655 if (abs(r.left-xa) < abs(r.right-xa)) r.left = xa; else r.right = xa+1;
656 }
657 if (centery == yb)
658 {
659 if (abs(r.left-xb) < abs(r.right-xb)) r.left = xb; else r.right = xb+1;
660 }
661 SetPort(io_plotwin);
662 PenMode(patCopy);
663 PenPat(&qd.black);
664 FrameArc(&r, startangle, amt);
665 break;
666
667 case TEXTCENT:
668 case TEXTTOP:
669 case TEXTBOT:
670 case TEXTLEFT:
671 case TEXTRIGHT:
672 case TEXTTOPLEFT:
673 case TEXTBOTLEFT:
674 case TEXTTOPRIGHT:
675 case TEXTBOTRIGHT:
676 case TEXTBOX:
677 tech = win->curnodeproto->tech;
678 size = truefontsize(TDGETSIZE(poly->textdescript), io_plotwindow, tech);
679 getbbox(poly, &xl, &xh, &yl, &yh);
680 io_plottext(poly->style, xl, xh, yl, yh, size, poly->string);
681 break;
682 }
683 }
684
io_plotdot(INTBIG x,INTBIG y)685 void io_plotdot(INTBIG x, INTBIG y)
686 {
687 Rect r;
688
689 io_xform(&x, &y);
690
691 r.left = x; r.right = x+1;
692 r.top = io_plotrevy-y; r.bottom = io_plotrevy-y+1;
693 SetPort(io_plotwin);
694 FillRect(&r, &qd.black);
695 }
696
697 /* draw a line */
io_plotline(INTBIG x1,INTBIG y1,INTBIG x2,INTBIG y2,INTBIG pattern)698 void io_plotline(INTBIG x1, INTBIG y1, INTBIG x2, INTBIG y2, INTBIG pattern)
699 {
700 static UCHAR1 pat0[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
701 static UCHAR1 pat1h[] = {0xFF, 0, 0, 0, 0xFF, 0, 0, 0};
702 static UCHAR1 pat1v[] = {0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88};
703 static UCHAR1 pat2h[] = {0xFF, 0xFF, 0xFF, 0, 0, 0xFF, 0xFF, 0xFF};
704 static UCHAR1 pat2v[] = {0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7};
705 static UCHAR1 *patlisth[] = {pat0, pat1h, pat2h, pat0};
706 static UCHAR1 *patlistv[] = {pat0, pat1v, pat2v, pat0};
707
708 io_xform(&x1, &y1);
709 io_xform(&x2, &y2);
710
711 /* do it on the printer */
712 SetPort(io_plotwin);
713 PenMode(patCopy);
714 if (abs(x1-x2) > abs(y1-y2)) PenPat((PatPtr)patlistv[pattern]); else
715 PenPat((PatPtr)patlisth[pattern]);
716 if (pattern == 3) PenSize(3, 3);
717 MoveTo(x1, io_plotrevy-y1);
718 LineTo(x2, io_plotrevy-y2);
719 if (pattern == 3) PenSize(1, 1);
720 }
721
io_plotpolygon(INTBIG * x,INTBIG * y,INTBIG count,INTBIG style,GRAPHICS * desc)722 void io_plotpolygon(INTBIG *x, INTBIG *y, INTBIG count, INTBIG style, GRAPHICS *desc)
723 {
724 INTBIG i;
725 UCHAR1 pat[8];
726 PolyHandle polyhandle;
727 static INTBIG *myx, *myy;
728 static INTBIG len = 0;
729
730 if (count == 0) return;
731 if (count > len)
732 {
733 if (len != 0)
734 {
735 DisposePtr((Ptr)myx); DisposePtr((Ptr)myy);
736 }
737 len = 0;
738 myx = (INTBIG *)NewPtr(count * SIZEOFINTBIG);
739 myy = (INTBIG *)NewPtr(count * SIZEOFINTBIG);
740 if (myx == 0 || myy == 0) return;
741 len = count;
742 }
743 for(i=0; i<count; i++)
744 {
745 myx[i] = x[i];
746 myy[i] = y[i];
747 io_xform(&myx[i], &myy[i]);
748 }
749
750 for(i=0; i<8; i++)
751 pat[i] = (style != PATTERNED ? 0xFF : desc->raster[i]);
752 SetPort(io_plotwin);
753 polyhandle = OpenPoly();
754 MoveTo(myx[count-1], io_plotrevy-myy[count-1]);
755 for(i=0; i<count; i++) LineTo(myx[i], io_plotrevy-myy[i]);
756 ClosePoly();
757 PenMode(patOr);
758 PenPat((PatPtr)pat);
759 PaintPoly(polyhandle);
760 KillPoly(polyhandle);
761 }
762
io_plottext(INTBIG type,INTBIG lx,INTBIG ux,INTBIG ly,INTBIG uy,INTBIG size,CHAR * text)763 void io_plottext(INTBIG type, INTBIG lx, INTBIG ux, INTBIG ly, INTBIG uy, INTBIG size,
764 CHAR *text)
765 {
766 CHAR localstring[256];
767 INTBIG len, i, tsx, tsy, px, py, truesize;
768 FontInfo fontinfo;
769
770 io_xform(&lx, &ly);
771 io_xform(&ux, &uy);
772
773 len = estrlen(text);
774 for(i=0; i<len; i++) localstring[i] = text[i];
775 TextFont(HFONT);
776 if (type == TEXTBOX)
777 {
778 /* scan for a font that fits */
779 for(truesize = size; truesize >= 4; truesize--)
780 {
781 TextSize(truesize);
782 GetFontInfo(&fontinfo);
783 tsx = TextWidth(localstring, 0, len);
784 tsy = fontinfo.ascent + fontinfo.descent + fontinfo.leading;
785 if (tsx <= ux-lx && tsy <= uy-ly) break;
786 }
787
788 /* continue only if text fits in Y */
789 if (tsy <= uy-ly)
790 {
791 /* truncate in X if necessary */
792 while (len > 1 && tsx > ux-lx)
793 {
794 len--;
795 tsx = TextWidth(localstring, 0, len);
796 }
797
798 /* continue only if text fits */
799 if (tsx <= ux-lx)
800 {
801 /* draw the text */
802 MoveTo(lx+(ux-lx-tsx)/2, io_plotrevy-(ly+(uy-ly-tsy)/2)-fontinfo.descent);
803 TextMode(srcOr+64);
804 DrawText(localstring, 0, len);
805 }
806 }
807 } else
808 {
809 TextSize(size);
810 GetFontInfo(&fontinfo);
811 tsx = TextWidth(localstring, 0, len);
812 tsy = fontinfo.ascent + fontinfo.descent + fontinfo.leading;
813 switch (type)
814 {
815 case TEXTCENT:
816 px = maxi(io_ulx,(lx+ux-tsx)/2);
817 py = maxi(io_uly,(ly+uy-tsy)/2);
818 break;
819 case TEXTTOP:
820 px = maxi(io_ulx,(lx+ux-tsx)/2);
821 py = maxi(io_uly,uy-tsy);
822 break;
823 case TEXTBOT:
824 px = maxi(io_ulx,(lx+ux-tsx)/2);
825 py = ly;
826 break;
827 case TEXTLEFT:
828 px = lx;
829 py = maxi(io_uly,(ly+uy-tsy)/2);
830 break;
831 case TEXTRIGHT:
832 px = maxi(io_ulx,ux-tsx);
833 py = maxi(io_uly,(ly+uy-tsy)/2);
834 break;
835 case TEXTTOPLEFT:
836 px = lx;
837 py = maxi(io_uly,uy-tsy);
838 break;
839 case TEXTBOTLEFT:
840 px = lx;
841 py = ly;
842 break;
843 case TEXTTOPRIGHT:
844 px = maxi(io_ulx,ux-tsx);
845 py = maxi(io_uly,uy-tsy);
846 break;
847 case TEXTBOTRIGHT:
848 px = maxi(io_ulx,ux-tsx);
849 py = ly;
850 break;
851 }
852 MoveTo(px, io_plotrevy-py-fontinfo.descent);
853 TextMode(srcOr+64);
854 DrawText(localstring, 0, len);
855 }
856 }
857
858 /*
859 * Routine to convert the coordinates (x,y) for display. The coordinates for
860 * printing are placed back into (x,y) and the PostScript coordinates are placed
861 * in (psx,psy).
862 */
io_xform(INTBIG * x,INTBIG * y)863 void io_xform(INTBIG *x, INTBIG *y)
864 {
865 *x = muldiv(*x-io_slx, io_uhx-io_ulx, io_shx-io_slx) + io_ulx;
866 *y = muldiv(*y-io_sly, io_uhy-io_uly, io_shy-io_sly) + io_uly;
867 }
868
869 /******************** GRAPHIC COPY ********************/
870
871 /*
872 * routine to copy the highlighted graphics to the clipboard. Called from
873 * "usrcomtv.c:us_text()"
874 */
io_maccopyhighlighted(void)875 void io_maccopyhighlighted(void)
876 {
877 PicHandle picture;
878 INTBIG len, slx, shx, sly, shy, ulx, uhx, uly, uhy, revy;
879 INTBIG ix;
880 CGrafPtr realwindow;
881 extern CGrafPtr gra_getwindow(WINDOWPART *win);
882
883 /* initialize for copying */
884 ZeroScrap();
885 realwindow = gra_getwindow(el_curwindowpart);
886 SetPort((WindowPtr)realwindow);
887 ClipRect(&qd.thePort->portRect);
888 picture = OpenPicture(&realwindow->portRect);
889
890 /* establish order of plotting layers */
891 io_maxlayer = io_setuptechorder(el_curtech);
892
893 /* setup window for copy */
894 (void)us_getareabounds(&slx, &shx, &sly, ­);
895 ulx = slx; uhx = shx;
896 uly = sly; uhy = shy;
897 (void)us_makescreen(&ulx, &uly, &uhx, &uhy, el_curwindowpart);
898
899 #if 0 /* this will make a color copy in the clipboard */
900 {
901 Rect sr;
902 CGrafPtr window;
903 INTBIG revy, swid, shei;
904
905 window = gra_getoffscreen(el_curwindowpart);
906 getwindowframesize(el_curwindowpart->frame, &swid, &shei);
907 revy = shei - 1;
908
909 sr.left = ulx; sr.right = uhx;
910 sr.top = revy - uhy; sr.bottom = revy - uly;
911
912 /* now copy the offscreen bits at "sr" to the print port at "dr" */
913 (void)LockPixels(window->portPixMap);
914 CopyBits((BitMap *)*(window->portPixMap), (BitMap *)*(realwindow->portPixMap),
915 &sr, &sr, srcCopy, 0L);
916 UnlockPixels(window->portPixMap);
917
918 ClosePicture();
919 HLock((Handle)picture);
920 len = (*picture)->picSize;
921 PutScrap(len, 'PICT', (Ptr)(*picture));
922 HUnlock((Handle)picture);
923 KillPicture(picture);
924 return(0);
925 }
926 #endif
927
928 uhx -= ulx; uhy -= uly; ulx = uly = 0;
929 revy = uhy;
930 io_setbounds(slx, shx, sly, shy, ulx, uhx, uly, uhy, revy, (WindowPtr)realwindow);
931 io_plotwindow = el_curwindowpart;
932
933 /* plot layers in this technology in proper order */
934 for(ix=0; ix<io_maxlayer; ix++)
935 {
936 /* first plot outlines around stipple layers */
937 io_setplotlayer(-(io_nextplotlayer(ix) + 1));
938 (void)asktool(us_tool, x_("display-highlighted-to-routine"), io_plotpoly);
939
940 /* next plot layers */
941 io_setplotlayer(io_nextplotlayer(ix) + 1);
942 (void)asktool(us_tool, x_("display-highlighted-to-routine"), io_plotpoly);
943 }
944
945 /* finally plot layers not in the technology */
946 io_setplotlayer(0);
947 (void)asktool(us_tool, x_("display-highlighted-to-routine"), io_plotpoly);
948
949 ClosePicture();
950 HLock((Handle)picture);
951 len = (*picture)->picSize;
952 PutScrap(len, 'PICT', (Ptr)(*picture));
953 HUnlock((Handle)picture);
954 KillPicture(picture);
955 }
956
957 #endif /* MACOS - at top */
958