#ifndef lint static char sccsid[] = "@(#)gensh_text.c 9.2 88/01/19 Copyright 1984 Sun Micro"; #endif /* * Copyright (c) 1984 by Sun Microsystems, Inc. */ /*- Paint a string in a pixrect clipped to a shape gensh_text.c, Mon May 13 10:24:35 1985 James Gosling, Sun Microsystems */ #include #ifdef REF #include #include #endif #include "shape.h" #include "font.h" #include extern struct pixrectops mem_ops; static struct mpr_data data; static struct pixrect pix = {&mem_ops, 9999, 9999, 1, (caddr_t) &data}; generic_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 n; { register short temp, sizey; register struct glyph *g; int ret = -1; if (shape == 0) return 0; if (op & PIX_DONTCLIP || shape == &InfiniteShape) for (; --n>=0; p++) { g = p->g; data.md_image = (short *) p->bits; data.md_linebytes = ((g->size.x + 15) >> 4) << 1; pr_rop(pixrect, cfloorfr(p->pos.x) - g->origin.x, cfloorfr(p->pos.y) - g->origin.y, g->size.x, g->size.y, op, &pix, 0, 0); } else { short top, bottom, left, right; top = max(0, shape->pos.y); left = max(0, shape->pos.x); bottom = min(pixrect->pr_size.y, shape->pos.y + shape->size.y); right = min(pixrect->pr_size.x, shape->pos.x + shape->size.x); if (top >= bottom || left >= right) return 0; if (!shape->is_rect) return pst_subdivide_text(pixrect, op, font, shape, shape->trapset, p, n); op |= PIX_DONTCLIP; for (; --n>=0; p++) { register t; register dx = cfloorfr(p->pos.x) - (g=p->g)->origin.x; register dy = cfloorfr(p->pos.y) - g->origin.y; int px = 0, py = 0, sx = g->size.x, sy = g->size.y; data.md_image = (short *) p->bits; data.md_linebytes = ((g->size.x + 15) >> 4) << 1; if ((t = dy - top) < 0) { sy += t; py = -t; dy = top; } if ((t = dx - left) < 0) { sx += t; px = -t; dx = left; } if ((t = dy + sy - bottom) > 0) sy -= t; if ((t = dx + sx - right) > 0) sx -= t; pr_rop(pixrect, dx, dy, sx, sy, op, &pix, px, py); } } } #define SHAPEROP() { \ struct pixrect pix2; \ data.md_image = (short *) ri->bits; \ data.md_linebytes = ((g->size.x + 15) >> 4) << 1; \ pix2.pr_ops = &mem_ops; \ pix2.pr_depth = 1; \ pix2.pr_data = (caddr_t) &data; \ pix2.pr_size.x = g->size.x; \ pix2.pr_size.y = g->size.y; \ pr_shaperop(pixrect, shape, op, \ &pix2, \ cfloorfr(ri->pos.x) - g->origin.x, \ cfloorfr(ri->pos.y) - g->origin.y); \ } pst_subdivide_text(pixrect, op, font, shape, t, ri, ri_size) struct pixrect *pixrect; int op; struct font *font; struct shape *shape; register struct shape_trapezon *t; register struct rendering_info *ri; int ri_size; { register short temp; short stop, sbottom, sleft, sright; register struct glyph *g; if (ri_size <= 1) { if (ri_size == 1) { g = ri->g; SHAPEROP(); } return 0; } if (shape == 0) return 0; if (shape->is_rect || t == 0) abort(); g = ri->g; if (font->left_to_right) { stop = cfloorfr(ri->pos.y) - font->origin.y; sbottom = stop + font->size.y; sleft = cfloorfr(ri->pos.x) - g->origin.x; g = ri[ri_size - 1].g; sright = cfloorfr(ri[ri_size - 1].pos.x) - g->origin.x + g->size.x; } else { register struct rendering_info *tri; register t; stop = cfloorfr(ri->pos.y) - font->origin.y; sbottom = stop + font->size.y; if (stop > sbottom) t = stop, stop = sbottom, sbottom = t; sleft = cfloorfr(ri->pos.x) - g->origin.x; sright = sleft + g->size.x; if (sleft > sright) t = sleft, sleft = sright, sright = t; tri = &ri[ri_size - 1]; g = tri->g; t = cfloorfr(tri->pos.y) - font->origin.y; if (t < stop) stop = t; t += font->size.y; if (t > sbottom) sbottom = t; t = cfloorfr(tri->pos.x) - g->origin.x; if (t < sleft) sleft = t; t += g->size.x; if (t > sright) sright = t; } { short leftout = 0, leftin = 0, rightin = pixrect->pr_width, rightout = rightin; register struct font *f = font; short top = 0; short bottom = pixrect->pr_height; int allslow = 0; if ((temp = shape->pos.x) > leftout) { leftout = temp; leftin = temp; } if ((temp = shape->pos.x + shape->size.x) < rightin) { rightin = temp; rightout = temp; } if ((temp = shape->pos.y) > top) top = temp; if ((temp = shape->pos.y + shape->size.y) < bottom) bottom = temp; { register min1, max1, min2, max2; register struct shape_trapseg *tps; if (t->top > top) top = t->top; if (t->bottom < bottom) bottom = t->bottom; if (stop <= t->top) { if (stop < t->top) allslow = 1; tps = t->segs; } else { register lo, hi; lo = 0; hi = t->used - 1; while (lo < hi) { register mid; mid = (hi + lo + 1) >> 1; if (t->segs[mid].y <= stop) lo = mid; else hi = mid - 1; } tps = &t->segs[lo]; } if (sbottom > t->bottom) { sbottom = t->bottom; allslow = 1; } min1 = tps->x1; max1 = min1; min2 = tps->x2; max2 = min2; while ((++tps)->y < sbottom) { if ((temp = tps->x1) < min1) min1 = temp; if (temp > max1) max1 = temp; if ((temp = tps->x2) < min2) min2 = temp; if (temp > max2) max2 = temp; } if (allslow || max1 >= min2) { if (min1 > leftout) leftout = min1; if (max2 < rightin) rightin = max2; leftin = rightin; rightout = rightin; } else { leftout = min1; leftin = max1; rightin = min2; rightout = max2; } } if (leftout >= rightout || stop >= bottom || sbottom <= top || sright <= leftout || sleft >= rightout) return t->next ? pst_subdivide_text(pixrect, op, font, shape, t->next, ri, ri_size) : 0; if (leftin <= sleft && sright <= rightin) { pr_shapetext(pixrect, op | PIX_DONTCLIP, font, &InfiniteShape, ri, ri_size); return 0; } if (allslow) { while (--ri_size >= 0) { g = ri->g; SHAPEROP(); ri++; } return 0; } if (font->left_to_right) { struct rendering_info *ri0 = ri; int ri0_size = 0; while (ri_size) { register short x; g = ri->g; x = cfloorfr(ri->pos.x) - g->origin.x + g->size.x; if (x > leftout) break; ri_size--; ri0_size++; ri++; } if (ri0_size && t->next) pst_subdivide_text(pixrect, op, font, shape, t->next, ri0, ri0_size); while (ri_size) { register short x; g = ri->g; x = cfloorfr(ri->pos.x) - g->origin.x; if (x >= leftin) break; SHAPEROP(); ri++; ri_size--; } ri0 = ri; ri0_size = 0; while (ri_size) { register short x; g = ri->g; x = cfloorfr(ri->pos.x) - g->origin.x + g->size.x; if (x > rightin) break; ri++; ri_size--; ri0_size++; } if (ri0_size) pr_shapetext(pixrect, op | PIX_DONTCLIP, font, &InfiniteShape, ri0, ri0_size); while (ri_size) { register short x; g = ri->g; x = cfloorfr(ri->pos.x) - g->origin.x; if (x >= rightout) break; SHAPEROP(); ri++; ri_size--; } if (ri_size && t->next) pst_subdivide_text(pixrect, op, font, shape, t->next, ri, ri_size); } else { pst_subdivide_text(pixrect, op, font, shape, t, ri, temp = ri_size >> 1); pst_subdivide_text(pixrect, op, font, shape, t, ri + temp, ri_size - temp); } } }