#ifndef lint static char sccsid[] = "@(#)mem_shtext.c 6.2 87/03/13 Copyright 1984 Sun Micro"; #endif /* * Copyright (c) 1984 by Sun Microsystems, Inc. */ /*- Paint a string in a memory pixrect clipped to a shape The shape must be rectangular. mem_shtext.c, Mon May 13 10:24:35 1985 James Gosling, Sun Microsystems */ #include #include "shape.h" #include #include #include #include "font.h" extern char pr_reversedst[]; extern struct pixrectops mem_ops; #define sadd(a,b) ((short)(((short)(a))+((short)(b)))) #define ssub(a,b) ((short)(((short)(a))-((short)(b)))) /* Copied from memvar.h and modified to deal with shorts: */ #undef mprd_addr #undef mprd8_addr #undef mprd_skew #define mprd_addr(mprd, xo, yo) \ ((short *)( \ (int)(mprd)->md_image \ + pr_product((mprd)->md_linebytes,sadd((mprd)->md_offset.y,(yo))) \ + ((sadd((mprd)->md_offset.x,(xo))) >> 3) &~ 1)) #define mprd8_addr(mprd, xo, yo, d) \ ((unsigned char *)( \ (int)(mprd)->md_image \ + pr_product((mprd)->md_linebytes,sadd((mprd)->md_offset.y,(yo))) \ + (pr_product(sadd((mprd)->md_offset.x,(xo)), (d)) >> 3) ) ) #define mprd_skew(mprd, xo, yo) \ ((sadd((mprd)->md_offset.x, (xo))) & 15) /******/ /* The inner loop of depth 1 memory pixrect rendering */ #define MEM1LOOP(func, op) \ if (font->narrow) { \ MEM1LOOPA(func,op,); \ } else { \ MEM1LOOPA(func,op,DoWidthcheck); \ } #define MEM1LOOPA(func, op, widthcheck) \ if (dontclip) { \ MEM1LOOPB(func,op,widthcheck,); \ } else if (inlineclip) { \ MEM1LOOPB(func,op,widthcheck,HardClipTest); \ } else { \ MEM1LOOPB(func,op,widthcheck,EasyClipTest); \ } #define DoWidthcheck \ if (ip->h.size.x > 16) goto one_slow; #define EasyClipTest \ if (sadd(temp, ip->h.size.x) > rightedge) \ { n++; goto hard; } #define HardClipTest \ if (sadd(temp, ip->h.size.x) > rightedge) \ if (temp>=rightedge) continue; \ else goto one_slow; \ if (temph.size.x)<=leftedge) continue; \ else goto one_slow; \ if ((skew = ssub(cfloorfr(p->pos.y), ip->h.origin.y)) \ 0) \ sizey -= skew; /* * NOTE that assignments to ip below (after "if (sadd..." and after the * declaration of "register nskew") assume that 'src' is set by * "#define src ((unsigned short *) ip)". If the definition of 'src' * changes, these will be wrong! BJB */ #define MEM1LOOPB(func, op, widthcheck, cliptest) \ for( ; ; p++) { \ register unsigned char *dst; \ /* sgi register unsigned short shvalue; */ \ /* register unsigned int intvalue; */ \ if (--n<0) \ break; \ ip = (struct generic_glyph *) p->g; \ widthcheck; \ sizey = ip->h.size.y; \ temp = cfloorfr(p->pos.x) - ip->h.origin.x; \ cliptest; \ temp += lxpos; \ dst = idst + ((temp>>3)&~1)+offsets[ip->h.origin.y]; \ skew = temp & 017; \ if (--sizey>=0) \ if (sadd(skew, ip->h.size.x) <= 16) { \ register unsigned short shiftbits; \ ip = (struct generic_glyph *) p->bits; \ do { \ /*sgi shvalue =*/ /* *((unsigned short *)dst) func= */ \ /* op (*src >> skew);*/ \ shiftbits = op (*src >> skew); \ *(dst+1) func= shiftbits & 0xff; \ *dst func= shiftbits >> 8; \ /* *((unsigned short *)dst) = shvalue; */ \ ip = (struct generic_glyph *) ((unsigned short*)ip + 1); \ dst += vert; \ } while(--sizey != -1); \ } else if ((int)dst & 2) { \ register nskew; \ register unsigned short shiftbits; \ ip = (struct generic_glyph *) p->bits; \ nskew = 16 - skew; \ do { \ shiftbits = op (*src >> skew); \ *(dst+1) func= shiftbits & 0xff; \ *dst func= shiftbits >> 8; \ shiftbits = op (*src << nskew); \ *(dst+3) func= shiftbits & 0xff; \ *(dst+2) func= shiftbits >> 8; \ /* *((unsigned short *)dst) func= op (*src >> skew); */ \ /* *(((unsigned short *)dst)+1) func= op (*src << nskew); */ \ ip = (struct generic_glyph *) ((unsigned short*)ip + 1); \ dst += vert; \ } while (--sizey != -1); \ } else { \ register nskew; \ register unsigned long shiftbits; \ ip = (struct generic_glyph *) p->bits; \ nskew = 16 - skew; \ do { \ shiftbits = op (*(src) << nskew); \ *(dst) func= (shiftbits>>24) & 0xff; \ *(dst+1) func= (shiftbits>>16) & 0xff; \ *(dst+2) func= (shiftbits>>8) & 0xff; \ *(dst+3) func= shiftbits & 0xff; \ /* *((unsigned long *)dst) func= op (*src << nskew); */ \ ip = (struct generic_glyph *) ((unsigned short*)ip + 1); \ dst += vert; \ } while (--sizey != -1); \ } \ } mem_shapetext(pixrect, op, font, shape, p, n) struct pixrect *pixrect; short op; struct font *font; struct shape *shape; register struct rendering_info *p; { register short temp, sizey; static struct mpr_data data; struct pixrect pix; extern mem_rop(); short leftedge, rightedge; register struct font *f = font; register struct generic_glyph *ip; short top = 0; short bottom = pixrect->pr_height; short y0 = cfloorfr(p->pos.y) - font->origin.y; short y1 = y0 + font->size.y; short inlineclip = 0; short dontclip = op & PIX_DONTCLIP; if (shape == 0) return 0; if (!shape->is_rect) { pst_subdivide_text(pixrect, op, font, shape, shape->trapset, rendering_info, rendering_info_length); return 0; } if (!dontclip) { leftedge = 0; rightedge = pixrect->pr_width; if ((temp = shape->pos.x) > leftedge) leftedge = temp; if ((temp = shape->pos.x + shape->size.x) < rightedge) rightedge = temp; if ((temp = shape->pos.y) > top) top = temp; if ((temp = shape->pos.y + shape->size.y) < bottom) bottom = temp; if (leftedge >= rightedge || y1 <= top || y0 >= bottom) return 0; temp = cfloorfr(p->pos.x) - f->origin.x; if (!f->left_to_right || y0 < top || y1 > bottom) inlineclip = 1; else if (temp >= leftedge && cfloorfr(p[n - 1].pos.x) + f->size.x <= rightedge) dontclip++; if (temp < leftedge) { /* clip off the left */ pix.pr_depth = 1; pix.pr_data = (caddr_t) & data; pix.pr_ops = &mem_ops; while (1) { if (--n < 0) return 0; ip = (struct generic_glyph *) p->g; if (cfloorfr(p->pos.x) + f->size.x - f->origin.x >= leftedge) { if (cfloorfr(p->pos.x) - f->origin.x >= leftedge) { n++; break; /* switch to fast drawing */ } data.md_image = (short *) p->bits; data.md_linebytes = ((ip->h.size.x + 15) >> 3) & ~1; pix.pr_size.x = ip->h.size.x; pix.pr_size.y = ip->h.size.y; pr_shaperop(pixrect, shape, op, &pix, cfloorfr(p->pos.x) - ip->h.origin.x, cfloorfr(p->pos.y) - ip->h.origin.y); } p++; } } } if (pixrect->pr_depth == 1) { register struct mpr_data *mprd = mpr_d(pixrect); register short vert = mprd->md_linebytes; register short skew; register lxpos = mprd->md_offset.x; static int *OFFSETS, *offsets; static int offsize; static short lvert, loy, lsy; unsigned char *idst; idst = (unsigned char *) ((int) mprd->md_image + pr_product(mprd->md_linebytes, sadd(mprd->md_offset.y, cfloorfr(p->pos.y)))); if (lvert != vert || loy < font->origin.y || lsy-loy < font->size.y - font->origin.y) { register short i; register int *offp; i = font->size.y; if (i < font->origin.y) i = font->origin.y; if (offsize < i+4) { offsize = i + 10; if (OFFSETS) free(OFFSETS); OFFSETS = (int *) snoopalloc("mem_shtest.c", offsize * sizeof(int)); } offsets = OFFSETS + i - font->origin.y + 2; i = font->origin.y; offp = offsets; lvert = vert; loy = i; lsy = font->size.y; temp = 0; do { *offp++ = temp; temp -= vert; } while (--i >= 0); temp = vert; i = font->size.y - font->origin.y; offp = offsets; do { *--offp = temp; temp += vert; } while (--i >= 0); } #define src ((unsigned short *)ip) restart: switch (op & 0x1E) { case PIX_SRC ^ PIX_DST: case PIX_NOT(PIX_DST): MEM1LOOP(^,); break; case PIX_SRC: case PIX_SET: case PIX_SRC | PIX_DST: MEM1LOOP(|,); break; case PIX_NOT(PIX_SRC) & PIX_DST: case PIX_NOT(PIX_SRC): case PIX_CLR: MEM1LOOP(&,~); break; case PIX_DST: break; default: goto hard; } return 0; #undef src /* This code needs to be within the scope of the local * variables defined under "depth == 1". */ one_slow: data.md_image = (short *) p->bits; data.md_linebytes = ((ip->h.size.x + 15) >> 3) & ~1; pix.pr_size.x = ip->h.size.x; pix.pr_size.y = ip->h.size.y; pix.pr_depth = 1; pix.pr_data = (caddr_t) & data; pix.pr_ops = &mem_ops; pr_shaperop(pixrect, shape, op, &pix, cfloorfr(p->pos.x) - ip->h.origin.x, cfloorfr(p->pos.y) - ip->h.origin.y); /*- pr_rop(pixrect, cfloorfr(p->pos.x) - ip->h.origin.x, cfloorfr(p->pos.y) - ip->h.origin.y, ip->h.size.x, ip->h.size.y, op, &pix, 0, 0); */ p++; goto restart; } /* end depth == 1 */ else { hard: pix.pr_depth = 1; pix.pr_data = (caddr_t) & data; pix.pr_ops = &mem_ops; for (;; p++) { if (--n < 0) return 0; ip = (struct generic_glyph *) p->g; if (!dontclip && cfloorfr(p->pos.x) - font->origin.x >= rightedge) if (font->left_to_right) break; else continue; data.md_image = (short *) p->bits; data.md_linebytes = ((ip->h.size.x + 15) >> 3) & ~1; pix.pr_size.x = ip->h.size.x; pix.pr_size.y = ip->h.size.y; pr_shaperop(pixrect, shape, op, &pix, cfloorfr(p->pos.x) - ip->h.origin.x, cfloorfr(p->pos.y) - ip->h.origin.y); } } return 0; }