#ifndef lint static char sccsid[] = "@(#)cscript.c 9.5 88/02/10"; #endif /* * Copyright (c) 1985 by Sun Microsystems, Inc. */ /*- Library to implement the PostScript imaging model in C cscript.c, Wed Sep 18 18:00:09 1985 */ #include #ifdef REF #include #include #endif #include "shape.h" #include "qalloc.h" #include "canvas.h" #include "fontcache.h" #include "cursor.h" #include "cscript.h" struct fpoint shape_point; /* The transformation & path building * operators sometimes communicate via * shape_point */ struct rpoint shape_rpoint; /* ditto here if the results are real */ cs_newpath(gc) register struct graphics_context *gc; { gc->path.used = gc->path.bottompos; gc->path.startpos = gc->path.bottompos; gc->hascurrentpoint = 0; if (gc->shape) { sh_decref(gc->shape); gc->shape = 0; } gc->path.straight = 1; if (gc->path.used == 0 && gc->path.size > 150) { free(gc->path.element); /* free paths that get large */ gc->path.size = 0; gc->path.element = 0; } } cs_erasepage(gc) register struct graphics_context *gc; { if (gc->clip != ((struct canvas *)gc->canvas)->lastclip && cv_is_canvas(gc->canvas)) cv_validate_clip(gc->canvas, gc->clip); cs_checkcursorcanvas((struct canvas *)gc->canvas); pr_rop((struct pixrect *) gc->canvas, 0, 0, 10000, 10000,/*((struct canvas *)gc->canvas)->pixrect.pr_width, ((struct canvas *)gc->canvas)->pixrect.pr_height,*/ pixrectopcode(gc->canvas, &white_color), 0, 0, 0); } sh_frmoveto(gc) register struct graphics_context *gc; { register struct path_element *p = gc->path.element + gc->path.used; if (gc->path.used <= gc->path.bottompos || p[-1].variation != MOVE_TO_FLAG) { if (gc->path.used >= gc->path.size) { if (gc->path.size) gc->path.element = (struct path_element *) snooprealloc ("cscript.c", gc->path.element, ((gc->path.size = gc->path.size * 3 / 2) * sizeof gc->path.element[0])); else gc->path.element = (struct path_element *) snoopalloc ("cscript.c", (gc->path.size = 20) * sizeof gc->path.element[0]); p = gc->path.element + gc->path.used; } p->variation = MOVE_TO_FLAG; p->pos.x = shape_point.x; p->pos.y = shape_point.y; gc->currentpoint = p->pos; gc->path.used++; } else { p[-1].pos.x = shape_point.x; p[-1].pos.y = shape_point.y; gc->currentpoint = p[-1].pos; } gc->hascurrentpoint = 1; } sh_frlineby(gc, variation) register struct graphics_context *gc; { register struct path_element *p; if (gc->path.used >= gc->path.size) { if (gc->path.size) gc->path.element = (struct path_element *) snooprealloc ("cscript.c", gc->path.element, (gc->path.size = gc->path.size * 3 / 2) * sizeof gc->path.element[0]); else gc->path.element = (struct path_element *) snoopalloc ("cscript.c", (gc->path.size = 20) * sizeof gc->path.element[0]); } p = gc->path.element + gc->path.used; if (p->variation = variation) gc->path.straight = 0; p->pos.x = shape_point.x; p->pos.y = shape_point.y; gc->currentpoint = p->pos; gc->hascurrentpoint = 1; gc->path.used++; } sh_closepath(gc) register struct graphics_context *gc; { register struct path_element *p; if (gc->path.used != gc->path.startpos && (p = gc->path.element + gc->path.used)[-1].variation != MOVE_TO_FLAG && p[-1].variation != CLOSEPATH_FLAG) { if (gc->path.used >= gc->path.size) { if (gc->path.size) gc->path.element = (struct path_element *) snooprealloc ("cscript.c", gc->path.element, (gc->path.size = gc->path.size * 3 / 2) * sizeof gc->path.element[0]); else gc->path.element = (struct path_element *) snoopalloc ("cscript.c", (gc->path.size = 20) * sizeof gc->path.element[0]); p = gc->path.element + gc->path.used; } p->pos.x = 0; p->pos.y = 0; p->variation = CLOSEPATH_FLAG; gc->path.used++; } gc->hascurrentpoint = 0; } struct graphics_context * cs_newcontext(canvas) struct pixrect *canvas; { register struct graphics_context *gc; qtalloc(gc, (struct graphics_context *)); cs_initcontext(gc, canvas, 0); return gc; } cs_initcontext(gc, canvas, retainpath) register struct graphics_context *gc; register struct pixrect *canvas; { gc->gsave_used = 0; if (!retainpath) { gc->gsave_size = 0; gc->gsaves = 0; gc->path.size = 0; gc->canvas = 0; gc->path.element = 0; gc->font = 0; gc->shape = 0; gc->clip = 0; } gc->path.used = 0; gc->path.straight = 1; gc->path.eorule = 0; gc->path.bottompos = 0; gc->path.startpos = 0; if (canvas) cs_setcanvas(gc, canvas); cs_initgraphics(gc); } cs_initgraphics(gc) register struct graphics_context *gc; { gc->linewidth = fracti(0); gc->linecap = cs_buttcap; gc->linejoin = cs_miterjoin; gc->miterlimit = fracti(10); gc->flatness = 2; gc->strokequality = -1; gc->texture[0] = 0; gc->currentpoint.x = 0; gc->currentpoint.y = 0; gc->hascurrentpoint = 0; gc->printermatch = 1; gc->pattern = 0; cs_frsetrgbcolor(gc, 0, 0, 0); cs_initmatrix(gc); cs_newpath(gc); cs_initclip(gc); } cs_setcanvas(gc, pr) register struct graphics_context *gc; register struct pixrect *pr; { gc->transform.floatexists = 0; if (gc->canvas != pr || gc->clip != ((struct canvas *) pr)->outerclip) { register struct pixrect *old; if (gc->clip && gc->clip->refcnt != STATIC_OBJ) sh_decref(gc->clip); old = gc->canvas; if (gc->canvas = pr) { if (cv_is_canvas(pr)) { cv_incref((struct canvas *) pr); gc->clip = ((struct canvas *) pr)->outerclip; sh_incref(gc->clip); } else gc->clip = &InfiniteShape; if (old == 0 || old->pr_depth != pr->pr_depth) cs_setcolor(gc, gc->color); } else gc->clip = &InvalidShape; if (old) { if (cv_is_canvas(old)) cv_decref((struct canvas *) old); } } cs_initmatrix(gc); cs_newpath(gc); } /* copies sgc to gc duplicating everything, including the * gsave/restore stack. gc is assumed to be set up */ cs_copy_context(sgc, gc) register struct graphics_context *sgc, *gc; { register struct path_element *p; if (gc->canvas && cv_is_canvas(gc->canvas)) cv_decref((struct canvas *) gc->canvas); { register struct graphics_context *g = gc->gsaves; register gs = gc->gsave_size; register ps = gc->path.size; p = gc->path.element; *gc = *sgc; gc->gsaves = g; gc->gsave_size = gs; gc->path.size = ps; gc->path.element = p; } if (gc->path.size==0 || gc->path.sizepath.used) { if (gc->path.element) free(gc->path.element); if ((gc->path.size = sgc->path.size)==0) gc->path.size = 10; gc->path.element = (struct path_element *) snoopalloc ("cscript.c", sizeof(struct path_element) * gc->path.size); } if (sgc->path.used>0) bcopy(sgc->path.element, gc->path.element, sizeof(struct path_element) * gc->path.used); if (gc->gsave_size < sgc->gsave_size) { if (gc->gsaves) free(gc->gsaves); gc->gsave_size = sgc->gsave_size; gc->gsaves = (struct graphics_context *) snoopalloc ("cscript.c", sizeof(struct graphics_context)*gc->gsave_size); } if (sgc->gsave_used) { register struct graphics_context *g; bcopy(sgc->gsaves, gc->gsaves, sizeof(struct graphics_context)*sgc->gsave_used); for (g = &gc->gsaves[gc->gsave_used]; --g>=gc->gsaves; ) { if (g->shape) sh_incref(g->shape); if (g->clip) sh_incref(g->clip); if (g->font) psf_incref(g->font); if (g->canvas && cv_is_canvas(g->canvas)) cv_incref((struct canvas *) g->canvas); } } if (gc->shape) sh_incref(gc->shape); if (gc->clip) sh_incref(gc->clip); if (gc->font) psf_incref(gc->font); if (gc->canvas && cv_is_canvas(gc->canvas)) cv_incref((struct canvas *) gc->canvas); } /* copies sgc to gc duplicating everything, but leaving the * gsave/restore stack intact. gc is assumed to be set up */ cs_copy_context_into(sgc, gc) register struct graphics_context *sgc, *gc; { cs_setcanvas(gc, 0); cs_newpath(gc); cs_setfont(gc, (struct psfont *) 0); { register struct path_element *p = gc->path.element; register struct graphics_context *g = gc->gsaves; register gs = gc->gsave_size; register gu = gc->gsave_used; register ps = gc->path.size; *gc = *sgc; gc->gsaves = g; gc->gsave_size = gs; gc->gsave_used = gu; gc->path.size = ps; gc->path.element = p; } if (gc->path.size==0 || gc->path.sizepath.used+gc->path.bottompos) { register struct path_element *old = gc->path.element; gc->path.size = sgc->path.used+gc->path.bottompos+10; gc->path.element = (struct path_element *) snoopalloc ("cscript.c", sizeof(struct path_element) * gc->path.size); if (gc->path.bottompos>0) bcopy(old, gc->path.element, gc->path.bottompos*sizeof(struct path_element)); if (old) free(old); } if (sgc->path.used>0) { bcopy(sgc->path.element, &gc->path.element[gc->path.bottompos], sizeof(struct path_element) * gc->path.used); gc->path.used = gc->path.bottompos + sgc->path.used; } if (gc->shape) sh_incref(gc->shape); if (gc->clip) sh_incref(gc->clip); if (gc->font) psf_incref(gc->font); if (gc->canvas && cv_is_canvas(gc->canvas)) cv_incref((struct canvas *) gc->canvas); } /* copies sgc to gc, ignoring the save/restore stack and assuming that gc is freshly malloced & contains rubbish */ cs_copy_context_to_empty(sgc, gc) register struct graphics_context *sgc, *gc; { register struct path_element *p; *gc = *sgc; gc->gsaves = 0; gc->gsave_size = 0; gc->gsave_used = 0; gc->path.size = gc->path.used - gc->path.startpos; gc->path.element = 0; if (gc->path.size > 0) { gc->path.element = (struct path_element *) snoopalloc ("cscript.c", sizeof(struct path_element) * gc->path.size); bcopy(&sgc->path.element[sgc->path.startpos], gc->path.element, sizeof(struct path_element) * gc->path.size); } gc->path.used = gc->path.size; gc->path.startpos = gc->path.bottompos = 0; if (gc->shape) sh_incref(gc->shape); if (gc->clip) sh_incref(gc->clip); if (gc->font) psf_incref(gc->font); if (gc->canvas && cv_is_canvas(gc->canvas)) cv_incref((struct canvas *) gc->canvas); } cs_setpath(gc, sh) register struct graphics_context *gc; register struct shape *sh; { cs_newpath(gc); if (gc->shape = sh) sh_incref(sh); } struct canvas * cs_locatecanvasinscene(scene, x, y) register struct scene *scene; register x, y; { register struct canvas *cv = scene->canvases, *bcv = 0; while (cv) { if (cv->mapped) { register lx = x - cv->pos.x, ly = y - cv->pos.y; if (cs_pointinshape(cv->outerclip, lx, ly)) { bcv = cv; x = lx; y = ly; cv = cv->topchild; } else cv = cv->prev; } else cv = cv->prev; } return bcv; } struct canvas * cs_nextcanvasforpoint(cv, x, y) register struct canvas *cv; int x, y; { register offsetx = 0, offsety = 0; register struct canvas *lcv = cv; if (cv == 0) return 0; while (lcv->parent != 0) { lcv = lcv->parent; offsetx += lcv->pos.x; offsety += lcv->pos.y; } while (cv) { if (cv->prev != 0) { cv = cv->prev; while (cv->topchild) { offsetx += cv->pos.x; offsety += cv->pos.y; cv = cv->topchild; } } else if (cv->parent != 0) { cv = cv->parent; offsetx -= cv->pos.x; offsety -= cv->pos.y; } else { return 0; } if (cv->mapped) { register lx = x - offsetx - cv->pos.x; register ly = y - offsety - cv->pos.y; if (cs_pointinshape(cv->outerclip, lx, ly)) break; } } return cv; } struct canvas *cs_bottomcanvas(cv) register struct canvas *cv; { while (cv->prev) cv = cv->prev; return cv; } struct spoint cs_abscanvaslocation(cv) register struct canvas *cv; { struct spoint pos; assert(cv_is_canvas(cv)); pos = cv->pos; while (cv = cv->parent) { pos.x += cv->pos.x; pos.y += cv->pos.y; } return pos; }