#ifndef lint static char sccsid[] = "@(#)text.c 9.3 88/01/19"; #endif /* * Copyright (c) 1985 by Sun Microsystems, Inc. */ /*- Routines for dealing with text text.c, Sun Nov 17 11:39:13 1985 */ #ifdef REF #include #include #endif #include "cscript.h" #include "cursor.h" extern char *newshome; struct text_modifiers show_modifiers; struct text_modifiers ashow_modifiers; struct text_modifiers widthshow_modifiers; struct text_modifiers awidthshow_modifiers; static char *fontpath; char textopmap[] = { PIX_DST & PIX_NOT(PIX_SRC), /* PIX_CLR */ PIX_DST & PIX_NOT(PIX_SRC), /* PIX_CLR | PIX_DONTCLIP */ PIX_DST, /* PIX_NOT(PIX_DST|PIX_SRC) */ PIX_DST, /* PIX_NOT(PIX_DST|PIX_SRC) | PIX_DONTCLIP */ PIX_DST & PIX_NOT(PIX_SRC), /* PIX_DST&PIX_NOT(PIX_SRC) */ PIX_DST & PIX_NOT(PIX_SRC), /* PIX_DST&PIX_NOT(PIX_SRC) | PIX_DONTCLIP */ PIX_DST & PIX_NOT(PIX_SRC), /* PIX_NOT(PIX_SRC) */ PIX_DST & PIX_NOT(PIX_SRC), /* PIX_NOT(PIX_SRC) | PIX_DONTCLIP */ PIX_DST, /* PIX_NOT(PIX_DST)&PIX_SRC */ PIX_DST, /* PIX_NOT(PIX_DST)&PIX_SRC | PIX_DONTCLIP */ PIX_SRC ^ PIX_DST, /* PIX_NOT(PIX_DST) */ PIX_SRC ^ PIX_DST, /* PIX_NOT(PIX_DST) | PIX_DONTCLIP */ PIX_DST ^ PIX_SRC, /* PIX_DST^PIX_SRC */ PIX_DST ^ PIX_SRC, /* PIX_DST^PIX_SRC | PIX_DONTCLIP */ PIX_DST, /* PIX_NOT(PIX_DST&PIX_SRC) */ PIX_DST, /* PIX_NOT(PIX_DST&PIX_SRC) | PIX_DONTCLIP */ PIX_DST, /* PIX_DST&PIX_SRC */ PIX_DST, /* PIX_DST&PIX_SRC | PIX_DONTCLIP */ PIX_DST, /* PIX_NOT(PIX_DST^PIX_SRC) */ PIX_DST, /* PIX_NOT(PIX_DST^PIX_SRC) | PIX_DONTCLIP */ PIX_DST, /* PIX_DST */ PIX_DST, /* PIX_DST | PIX_DONTCLIP */ PIX_DST, /* PIX_DST|PIX_NOT(PIX_SRC) */ PIX_DST, /* PIX_DST|PIX_NOT(PIX_SRC) | PIX_DONTCLIP */ PIX_DST | PIX_SRC, /* PIX_SRC */ PIX_DST | PIX_SRC, /* PIX_SRC | PIX_DONTCLIP */ PIX_DST, /* PIX_NOT(PIX_DST)|PIX_SRC */ PIX_DST, /* PIX_NOT(PIX_DST)|PIX_SRC | PIX_DONTCLIP */ PIX_DST | PIX_SRC, /* PIX_DST|PIX_SRC */ PIX_DST | PIX_SRC, /* PIX_DST|PIX_SRC | PIX_DONTCLIP */ PIX_DST | PIX_SRC, /* PIX_SET */ PIX_DST | PIX_SRC, /* PIX_SET | PIX_DONTCLIP */ }; #ifdef PREVIEW #include #include <../server/PostScript.h> struct execution_environment *curee; int preview_show; int watchforfont; int preview_y1; int preview_y2; #endif cv_show(gc, str, len, info) register struct graphics_context *gc; char *str; register struct text_modifiers *info; { extern struct font *cs_concretefont(); register int func = gc->func; if (len != 0) { struct font *f = cs_concretefont(gc); register struct rendering_info *ri; extern struct fpoint rendering_info_fmin; extern struct fpoint rendering_info_fmax; extern short rendering_info_left, rendering_info_top, rendering_info_width, rendering_info_height; #ifdef PREVIEW if (watchforfont) { getfontht(&curee->gontext, &preview_y1, &preview_y2); watchforfont = 0; } preview_show = 1; #endif (*f->u.ops->get_rendering_info) (f, str, len, gc->currentpoint.x, gc->currentpoint.y, info, gc->font->remap); if (gc->clip != ((struct canvas *) gc->canvas)->lastclip && cv_is_canvas(gc->canvas)) cv_validate_clip(gc->canvas, gc->clip); /* Figure out text bbox */ cs_checkcursordims(gc->canvas, rendering_info_left, rendering_info_top, rendering_info_width, rendering_info_height); pr_shapetext(gc->canvas, textopmap[func & 0x1E] | func & ~0x1F, f, &InfiniteShape, rendering_info, rendering_info_length); shape_point = rendering_info[rendering_info_length].pos; sh_frmoveto(gc); } } cv_stringwidth(gc, str, len) register struct graphics_context *gc; char *str; { extern struct font *cs_concretefont(); struct font *f = cs_concretefont(gc); (*f->u.ops->get_stringwidth) (f, str, len, gc->font->remap); cs_fridtransform(gc, shape_point.x, shape_point.y, &shape_point.x, &shape_point.y); } char * cs_fontpath() { if (fontpath == 0 && (fontpath = (char *) getenv("FONTPATH")) == 0) #ifndef PREVIEW if (newshome) { static char fontdirbuf[300]; sprintf(fontdirbuf, "%s/fonts", newshome); fontpath = fontdirbuf; } else #endif #ifdef FONTDIR fontpath = FONTDIR; #else #ifdef PREVIEW fontpath = "/usr/doctools/font/devNeWS"; #else fontpath = "/usr/NeWS/fonts"; #endif #endif return fontpath; } /* Obsolete */ #ifdef undef struct psfont * cs_findfont(name, nml) char *name; { static struct fontfamily **families; static nfamilies; static sizefamilies; register i; register struct fontfamily *fam; register struct psfont *font; if (nml <= 0) nml = strlen(name); for (i = 0; i < nfamilies; i++) { fam = families[i]; if (fam->FamilyName && name[0] == fam->FamilyName[0] && fam->FamilyName[nml] == 0 && strncmp(name, fam->FamilyName, nml) == 0) break; } if (i >= nfamilies) { extern struct fontfamily *cst_readfamily(); register char *s, *p; if (nfamilies >= sizefamilies) if (sizefamilies == 0) families = (struct fontfamily **) snoopalloc("text.c", (sizefamilies = 10) * sizeof(struct fontfamily *)); else families = (struct fontfamily **) snooprealloc("text.c", families, (sizefamilies *= 2) * sizeof(struct fontfamily *)); if (fontpath == 0) cs_fontpath(); for (s = fontpath; *s; s = p + 1) { char buf[300]; p = s; while (*p != ':' && *p) p++; sprintf(buf, s == p ? "%.*s%s.ffam" : "%.*s/%.*s.ffam", p - s, s, nml, name); if ((fam = cst_readfamily(buf)) != 0) { families[nfamilies] = fam; if (fam->FamilyName == 0 || strncmp(name, fam->FamilyName) != 0) { fam->FamilyName = (char *) snoopalloc("text.c", nml + 1); strncpy(fam->FamilyName, name, nml); fam->FamilyName[nml] = 0; } break; } if (*p == 0) return 0; } nfamilies++; } qtalloc(font, (struct psfont *)); font->family = families[i]; font->matrix[0][0] = fracti(1); font->matrix[1][0] = fracti(0); font->matrix[0][1] = fracti(0); font->matrix[1][1] = fracti(1); font->simplescale = 1; font->revision = -1; font->lasthit = 0; font->refcnt = 1; font->remap = 0; return font; } #endif /* * Given the name of a font family file, read it it and return a PostScript * font handle that represents it */ struct psfont * cs_findfilefont(name, nml) char *name; { register struct fontfamily *fam; register struct psfont *font; extern struct fontfamily *cst_readfamily(); extern bitmap_buildchar(); register char *s, *p; if (nml < 0) nml = strlen(name); if (name[0] == '/') { char buf[300]; bcopy(name, buf, nml); buf[nml] = 0; if ((fam = cst_readfamily(buf)) == 0) return 0; } else { if (fontpath == 0) cs_fontpath(); for (s = fontpath; *s; s = p + 1) { char buf[300]; p = s; while (*p != ':' && *p) p++; sprintf(buf, s == p ? "%.*s%s.ffam" : "%.*s/%.*s.ffam", p - s, s, nml, name); if ((fam = cst_readfamily(buf)) != 0) { if (fam->FamilyName == 0 || strncmp(name, fam->FamilyName) != 0) { fam->FamilyName = (char *) snoopalloc("text.c", nml + 1); strncpy(fam->FamilyName, name, nml); fam->FamilyName[nml] = 0; } break; } if (*p == 0) return 0; } } fam->m.buildchar = bitmap_buildchar; qtalloc(font, (struct psfont *)); font->family = fam; font->remap = 0; font->matrix[0][0] = fracti(1); font->matrix[1][0] = fracti(0); font->matrix[0][1] = fracti(0); font->matrix[1][1] = fracti(1); font->simplescale = 1; font->revision = -1; font->lasthit = 0; font->refcnt = 1; return font; } /* * Register a font that has a buildchar proc */ struct psfont * cs_definefont(name, nml, buildchar, udata) char *name; int (*buildchar)(); char *udata; { register struct fontfamily *fam; register struct psfont *font; if (nml < 0) nml = strlen(name); fam = (struct fontfamily *) snoopalloc("text.c", sizeof *fam); bzero(fam, sizeof *fam); fam->m.buildchar = buildchar; fam->directory = udata; fam->FamilyName = (char *) snoopalloc("text.c", nml+1); bcopy(name, fam->FamilyName, nml); fam->FamilyName[nml] = 0; qtalloc(font, (struct psfont *)); font->family = fam; font->remap = 0; font->matrix[0][0] = fracti(1); font->matrix[1][0] = fracti(0); font->matrix[0][1] = fracti(0); font->matrix[1][1] = fracti(1); font->simplescale = 1; font->revision = -1; font->lasthit = 0; font->refcnt = 1; return font; } struct psfont * cs_frscalefont(font, scale) register struct psfont *font; fract scale; { register struct psfont *nfont; if (font == 0) return 0; qtalloc(nfont, (struct psfont *)); nfont->family = font->family; nfont->revision = -1; nfont->lasthit = 0; nfont->refcnt = 1; nfont->remap = font->remap; nfont->matrix[0][0] = frmul(font->matrix[0][0], scale); if (nfont->simplescale = font->simplescale) { nfont->matrix[1][1] = nfont->matrix[0][0]; nfont->matrix[0][1] = font->matrix[0][1]; nfont->matrix[1][0] = font->matrix[1][0]; } else { nfont->matrix[0][1] = frmul(font->matrix[0][1], scale); nfont->matrix[1][0] = frmul(font->matrix[1][0], scale); nfont->matrix[1][1] = frmul(font->matrix[1][1], scale); } return nfont; } struct psfont * cs_frmakefont(font, matrix) register struct psfont *font; FMATRIX matrix; { register struct psfont *nfont; qtalloc(nfont, (struct psfont *)); nfont->family = font->family; nfont->revision = -1; nfont->lasthit = 0; nfont->refcnt = 1; nfont->remap = font->remap; nfont->matrix[0][0] = frmul(font->matrix[0][0], matrix[0][0]) + frmul(font->matrix[0][1], matrix[1][0]); nfont->matrix[0][1] = frmul(font->matrix[0][0], matrix[0][1]) + frmul(font->matrix[0][1], matrix[1][1]); nfont->matrix[1][0] = frmul(font->matrix[1][0], matrix[0][0]) + frmul(font->matrix[1][1], matrix[1][0]); nfont->matrix[1][1] = frmul(font->matrix[1][0], matrix[0][1]) + frmul(font->matrix[1][1], matrix[1][1]); nfont->simplescale = nfont->matrix[1][0] == 0 && nfont->matrix[0][1] == 0 && nfont->matrix[0][0] == nfont->matrix[1][1]; return nfont; } struct shape * cs_cstringbbox(gc, str, len) register struct graphics_context *gc; char *str; { extern struct font *cs_concretefont(); register int func = gc->func; register struct shape *sh; qtalloc(sh, (struct shape *)); sh->is_rect = 1; sh->trapset = 0; sh->refcnt = 1; if (len != 0) { register minx, maxx, miny, maxy; struct font *f = cs_concretefont(gc); register struct rendering_info *ri; (*f->u.ops->get_rendering_info) (f, str, len, gc->currentpoint.x, gc->currentpoint.y, 0, 0); if (rendering_info_length == 0) goto no_chars; minx = cfloorfr(rendering_info[0].pos.x) - rendering_info[0].g->origin.x; miny = cfloorfr(rendering_info[0].pos.y) - rendering_info[0].g->origin.y; maxx = minx; maxy = miny; for (ri = rendering_info + rendering_info_length; --ri >= rendering_info;) { register fract T; T = cfloorfr(ri->pos.x) - ri->g->origin.x; if (T < minx) minx = T; T += ri->g->size.x; if (T > maxx) maxx = T; T = cfloorfr(ri->pos.y) - ri->g->origin.y; if (T < miny) miny = T; T += ri->g->size.y; if (T > maxy) maxy = T; } sh->pos.x = minx; sh->pos.y = miny; sh->size.x = maxx - minx; sh->size.y = maxy - miny; } else { no_chars: sh->size.x = 0; sh->size.y = 0; sh->pos.x = 0; sh->pos.y = 0; } return sh; }