Exemplo n.º 1
0
static int
bbox_fill_mask(gx_device * dev,
	       const byte * data, int dx, int raster, gx_bitmap_id id,
	       int x, int y, int w, int h,
	       const gx_drawing_color * pdcolor, int depth,
	       gs_logical_operation_t lop, const gx_clip_path * pcpath)
{
    gx_device_bbox *const bdev = (gx_device_bbox *) dev;
    gx_device *tdev = bdev->target;
    /* Skip the call if there is no target. */
    int code =
	(tdev == 0 ? 0 :
	 dev_proc(tdev, fill_mask)
	 (tdev, data, dx, raster, id, x, y, w, h,
	  pdcolor, depth, lop, pcpath));

    if (pcpath != NULL &&
	!gx_cpath_includes_rectangle(pcpath, int2fixed(x), int2fixed(y),
				     int2fixed(x + w),
				     int2fixed(y + h))
	) {
	/* Let the target do the drawing, but break down the */
	/* image into pieces for computing the bounding box. */
	bdev->target = NULL;
	gx_default_fill_mask(dev, data, dx, raster, id, x, y, w, h,
			     pdcolor, depth, lop, pcpath);
	bdev->target = tdev;
    } else {
	/* Just use the mask bounding box. */
	BBOX_ADD_INT_RECT(bdev, x, y, x + w, y + h);
    }
    return code;
}
Exemplo n.º 2
0
static void mark_line(fz_context *ctx, fz_edgebuffer *eb, fixed sx, fixed sy, fixed ex, fixed ey)
{
	int base_y = eb->super.clip.y0;
	int height = eb->super.clip.y1 - eb->super.clip.y0;
	int *table = eb->table;
	int *index = eb->index;
	int delta;
	int iy, ih;
	fixed clip_sy, clip_ey;
	int dirn = DIRN_UP;
	int *row;

	if (fixed2int(sy + fixed_half-1) == fixed2int(ey + fixed_half-1))
		return;
	if (sy > ey) {
		int t;
		t = sy; sy = ey; ey = t;
		t = sx; sx = ex; ex = t;
		dirn = DIRN_DOWN;
	}

	if (fixed2int(sx) < eb->super.bbox.x0)
		eb->super.bbox.x0 = fixed2int(sx);
	if (fixed2int(sx + fixed_1 - 1) > eb->super.bbox.x1)
		eb->super.bbox.x1 = fixed2int(sx + fixed_1 - 1);
	if (fixed2int(ex) < eb->super.bbox.x0)
		eb->super.bbox.x0 = fixed2int(ex);
	if (fixed2int(ex + fixed_1 - 1) > eb->super.bbox.x1)
		eb->super.bbox.x1 = fixed2int(ex + fixed_1 - 1);

	if (fixed2int(sy) < eb->super.bbox.y0)
		eb->super.bbox.y0 = fixed2int(sy);
	if (fixed2int(ey + fixed_1 - 1) > eb->super.bbox.y1)
		eb->super.bbox.y1 = fixed2int(ey + fixed_1 - 1);

	/* Lines go from sy to ey, closed at the start, open at the end. */
	/* We clip them to a region to make them closed at both ends. */
	/* Thus the unset scanline marked (>= sy) is: */
	clip_sy = ((sy + fixed_half - 1) & ~(fixed_1-1)) | fixed_half;
	/* The last scanline marked (< ey) is: */
	clip_ey = ((ey - fixed_half - 1) & ~(fixed_1-1)) | fixed_half;
	/* Now allow for banding */
	if (clip_sy < int2fixed(base_y) + fixed_half)
		clip_sy = int2fixed(base_y) + fixed_half;
	if (ey <= clip_sy)
		return;
	if (clip_ey > int2fixed(base_y + height - 1) + fixed_half)
		clip_ey = int2fixed(base_y + height - 1) + fixed_half;
	if (sy > clip_ey)
		return;
	delta = clip_sy - sy;
	if (delta > 0)
	{
		int dx = ex - sx;
		int dy = ey - sy;
		int advance = (int)(((int64_t)dx * delta + (dy>>1)) / dy);
		sx += advance;
		sy += delta;
	}
Exemplo n.º 3
0
static inline int
set_x_gradient_nowedge(trap_gradient *xg, const trap_gradient *lg, const trap_gradient *rg, 
	     const trap_line *l, const trap_line *r, int il, int ir, int num_components)
{
    /* Ignoring the ending coordinats fractions, 
       so the gridient is slightly shifted to the left (in <1 'fixed' unit). */
    int32_t xl = l->x - (l->xf == -l->h ? 1 : 0) - fixed_half; /* Revert the GX_FILL_TRAPEZOID shift. */
    int32_t xr = r->x - (r->xf == -r->h ? 1 : 0) - fixed_half; /* Revert the GX_FILL_TRAPEZOID shift. */
    /* The pixel span boundaries : */
    int32_t x0 = int2fixed(il) + fixed_half; /* Shift to the pixel center. */
    int32_t x1 = int2fixed(ir) - fixed_half; /* The center of the last pixel to paint. */
    int i;

#   ifdef DEBUG
	if (arith_rshift_1(xr) - arith_rshift_1(xl) >= 0x3FFFFFFE) /* Can overflow ? */
	    return_error(gs_error_unregistered); /* Must not happen. */
#   endif
    /* We cannot compute the color of the 'ir' pixel 
       because it can overflow 'c1' due to the pixel ir center
       may be greater that r->x .
       Therefore we base the proportion on the pixel index ir-1 (see comment to 'x1').
       Debugged with CET 12-14O.PS SpecialTestJ02Test12.
     */
    xg->den = fixed2int(x1 - x0);
    if (xg->den <= 0) {
	/* The span contains a single pixel, will construct a degenerate gradient. */
	xg->den = 1; /* Safety (against zerodivide). */
    }
    for (i = 0; i < num_components; i++) {
	/* Ignoring the ending colors fractions, 
	   so the color gets a slightly smaller value
	   (in <1 'frac31' unit), but it's not important due to 
	   the further conversion to [0, 1 << cinfo->comp_bits[j]], 
	   which drops the fraction anyway. */
	int32_t cl = lg->c[i];
	int32_t cr = rg->c[i];
	int32_t c0 = (int32_t)(cl + ((int64_t)cr - cl) * (x0 - xl) / (xr - xl));
	int32_t c1 = (int32_t)(cl + ((int64_t)cr - cl) * (x1 - xl) / (xr - xl));

	xg->c[i] = c0;
	xg->f[i] = 0; /* Insufficient bits to compute it better. 
	                 The color so the color gets a slightly smaller value
			 (in <1 'frac31' unit), but it's not important due to 
			 the further conversion to [0, 1 << cinfo->comp_bits[j]], 
			 which drops the fraction anyway. 
			 So setting 0 appears pretty good and fast. */
	xg->num[i] = c1 - c0;
    }
    return 0;
}
Exemplo n.º 4
0
int mandelbrot() {
	int i, j, tid;
    int count = 0;
    int temp[NUM_ACCELS] = {0};

    #pragma omp parallel for num_threads(NUM_ACCELS) private(i, j, tid)
	for (j = 0; j < HEIGHT; j++) {
		for (i = 0; i < WIDTH; i++) {

            tid = omp_get_thread_num();
			int x_0 = int2fixed(-2) + ((((3 << 20) * i/WIDTH) ) << 8);
			int y_0 = int2fixed(-1) + ((((2 << 20) * j/HEIGHT) ) << 8);

			int x = 0;
			int y = 0;
			int xtmp;
			unsigned char iter;
			unsigned char fiter = 0;

            for (iter = 0; iter < MAX_ITER; iter++) {
                long long abs_squared = fixedmul(x,x) + fixedmul(y,y);

				xtmp = fixedmul(x,x) - fixedmul(y,y) + x_0;
				y = fixedmul(int2fixed(2), fixedmul(x,y)) + y_0;
				x = xtmp;
                
				fiter  +=  abs_squared <= int2fixed(4);
			}

			//get black or white
            unsigned char colour = (fiter >= MAX_ITER) ? 0 : 1;
			//accumulate colour
            //count += colour;
            temp[tid] += colour;
			//update image
			img[i][j] = colour;
		}
	}

    for (i=0; i<NUM_ACCELS; i++) {
        count += temp[i];
    }

	return count;
}
Exemplo n.º 5
0
/* Write a clipping path by calling the path procedures. */
int
gdev_vector_write_clip_path(gx_device_vector * vdev,
                            const gx_clip_path * pcpath)
{
    const gx_clip_rect *prect;
    gx_clip_rect page_rect;
    int code;

    if (pcpath == 0) {
        /* There's no special provision for initclip. */
        /* Write a rectangle that covers the entire page. */
        page_rect.xmin = page_rect.ymin = 0;
        page_rect.xmax = vdev->width;
        page_rect.ymax = vdev->height;
        page_rect.next = 0;
        prect = &page_rect;
    } else if (pcpath->path_valid) {
        return (*vdev_proc(vdev, dopath))
            (vdev, &pcpath->path,
             (pcpath->rule <= 0 ?
              gx_path_type_clip | gx_path_type_winding_number :
              gx_path_type_clip | gx_path_type_even_odd),
             NULL);
    } else {
        const gx_clip_list *list = gx_cpath_list(pcpath);

        prect = list->head;
        if (prect == 0)
            prect = &list->single;
    }
    /* Write out the rectangles. */
    code = (*vdev_proc(vdev, beginpath)) (vdev, gx_path_type_clip);
    for (; code >= 0 && prect != 0; prect = prect->next)
        if (prect->xmax > prect->xmin && prect->ymax > prect->ymin)
            code = gdev_vector_write_rectangle
                (vdev, int2fixed(prect->xmin), int2fixed(prect->ymin),
                 int2fixed(prect->xmax), int2fixed(prect->ymax),
                 false, gx_rect_x_first);
    if (code >= 0)
        code = (*vdev_proc(vdev, endpath)) (vdev, gx_path_type_clip);
    return code;
}
Exemplo n.º 6
0
void *mandelbrot(void *threadarg) {
	int i, j, tid;
    int count = 0;
	struct thread_data* arg = (struct thread_data*) threadarg;
	int startidx = arg->startidx;
	int maxidx = arg->maxidx;

	for (j = startidx; j < maxidx; j++) {
		for (i = 0; i < WIDTH; i++) {

			int x_0 = int2fixed(-2) + ((((3 << 20) * i/WIDTH) ) << 8);
			int y_0 = int2fixed(-1) + ((((2 << 20) * j/HEIGHT) ) << 8);

			int x = 0;
			int y = 0;
			int xtmp;
			unsigned char iter;
			unsigned char fiter = 0;
			
            for (iter = 0; iter < MAX_ITER; iter++) {
                long long abs_squared = fixedmul(x,x) + fixedmul(y,y);

				xtmp = fixedmul(x,x) - fixedmul(y,y) + x_0;
				y = fixedmul(int2fixed(2), fixedmul(x,y)) + y_0;
				x = xtmp;
                
				fiter  +=  abs_squared <= int2fixed(4);
			}

			//get black or white
            unsigned char colour = (fiter >= MAX_ITER) ? 0 : 1;
			//accumulate colour
            count += colour;
			//update image
			img[i][j] = colour;
		}
	}

	pthread_exit((void*)count);
}
Exemplo n.º 7
0
/* Scale an existing path by a power of 2 (positive or negative).
 * Currently the path drawing routines can't handle values
 * close to the edge of the representable space.
 * Also see clamp_point() in gspath.c .
 */
void
gx_point_scale_exp2(gs_fixed_point * pt, int sx, int sy)
{
    int v;

    if (sx > 0) {
        v = (max_int - int2fixed(1000)) >> sx; /* arbitrary */
        if (pt->x > v)
            pt->x = v;
        else if (pt->x < -v)
            pt->x = -v;
        pt->x <<= sx;
    } else
Exemplo n.º 8
0
/* Compute ldi, ldf, and xf similarly. */
static inline void
compute_ldx(trap_line *tl, fixed ys)
{
    int di = tl->di;
    fixed df = tl->df;
    fixed h = tl->h;

    if ( df < YMULT_LIMIT ) {
	 if ( df == 0 )		/* vertical edge, worth checking for */
	     tl->ldi = int2fixed(di), tl->ldf = 0, tl->xf = -h;
	 else {
	     tl->ldi = int2fixed(di) + int2fixed(df) / h;
	     tl->ldf = int2fixed(df) % h;
	     tl->xf =
		 (ys < fixed_1 ? ys * df % h : fixed_mult_rem(ys, df, h)) - h;
	 }
    }
    else {
	tl->ldi = int2fixed(di) + fixed_mult_quo(fixed_1, df, h);
	tl->ldf = fixed_mult_rem(fixed_1, df, h);
	tl->xf = fixed_mult_rem(ys, df, h) - h;
    }
}
Exemplo n.º 9
0
/* WARNING: This function doesn't account the shading BBox
   to allow the clipent to optimize the clipping
   with changing the order of clip paths and rects.
   The client must clip with the shading BBox before calling this function. */
static int
gx_dc_pattern2_fill_rectangle(const gx_device_color * pdevc, int x, int y,
                              int w, int h, gx_device * dev,
                              gs_logical_operation_t lop,
                              const gx_rop_source_t * source)
{
    if (dev_proc(dev, dev_spec_op)(dev, gxdso_pattern_is_cpath_accum, NULL, 0)) {
        /* Performing a conversion of imagemask into a clipping path.
           Fall back to the device procedure. */
        return dev_proc(dev, fill_rectangle)(dev, x, y, w, h, (gx_color_index)0/*any*/);
    } else {
        gs_fixed_rect rect;
        gs_pattern2_instance_t *pinst =
            (gs_pattern2_instance_t *)pdevc->ccolor.pattern;

        rect.p.x = int2fixed(x);
        rect.p.y = int2fixed(y);
        rect.q.x = int2fixed(x + w);
        rect.q.y = int2fixed(y + h);
        return gs_shading_do_fill_rectangle(pinst->templat.Shading, &rect, dev,
                                    (gs_imager_state *)pinst->saved, !pinst->shfill);
    }
}
Exemplo n.º 10
0
int main(int argc, char* argv[])
{
	int i;
	for (i = 1000; i > 0; --i) {
		float f1 = fixed2float(fixsqrt(int2fixed(i)));
		float f2 = sqrtf(i);
		float diff = f1 - f2;
		printf("%d\t%.2f\t%.2f\t%.2f\n", i, f1, f2, diff);
		assert(fabsf(diff) < fixed2float(2));
	}
	TIMEIT(1000, for (i = 1000; i > 0; --i) fixsqrt(int2fixed(i)));
	system("pause");
	return 0;
}
Exemplo n.º 11
0
static inline int process_h_sect(line_list * ll, margin_set * set, active_line * hlp0,
    active_line * plp, active_line * flp, int side, fixed y0, fixed y1)
{
    active_line *hlp = hlp0;
    fixed y = hlp->start.y;
    fixed x0 = (plp != 0 ? (y == y0 ? plp->x_current : y == y1 ? plp->x_next : AL_X_AT_Y(plp, y))
                         : int2fixed(ll->bbox_left));
    fixed x1 = (flp != 0 ? (y == y0 ? flp->x_current : y == y1 ? flp->x_next : AL_X_AT_Y(flp, y))
                         : int2fixed(ll->bbox_left + ll->bbox_width));
    int code;

    for (; hlp != 0; hlp = hlp->next) {
        fixed xx0 = max(x0, min(hlp->start.x, hlp->end.x));
        fixed xx1 = min(x1, max(hlp->start.x, hlp->end.x));

        if (xx0 < xx1) {
            vd_bar(xx0, y, xx1, y, 1, RGB(255, 0, 255));
            code =  margin_boundary(ll, set, 0, xx0, xx1, y, y, side, 0, 0);
            if (code < 0)
                return code;
        }
    }
    return 0;
}
Exemplo n.º 12
0
static inline int mark_margin_interior(line_list * ll, margin_set * set, active_line * flp, active_line * alp, fixed y, fixed y0, fixed y1)
{
    section *sect = set->sect;
    fixed x0 = (y == y0 ? flp->x_current : y == y1 ? flp->x_next : AL_X_AT_Y(flp, y));
    fixed x1 = (y == y0 ? alp->x_current : y == y1 ? alp->x_next : AL_X_AT_Y(alp, y));
    int i0 = fixed2int(x0), ii0, ii1, i, code;

    if (int2fixed(i0) + fixed_half < x0)
        i0++;
    ii0 = i0 - ll->bbox_left;
    ii1 = fixed2int_var_pixround(x1) - ll->bbox_left;
    if (ii0 < ii1) {
        if (ii0 < 0 || ii1 > ll->bbox_width)
            return_error(gs_error_unregistered); /* Must not happen. */
        for (i = ii0; i < ii1; i++) {
            sect[i].y0 = sect[i].y1 = -2;
            vd_circle(int2fixed(i + ll->bbox_left) + fixed_half, y, 3, RGB(255, 0, 0));
        }
        code = store_margin(ll, set, ii0, ii1);
        if (code < 0)
            return code;
    }
    return 0;
}
Exemplo n.º 13
0
int mandelbrot() {
	int i, j;
    int count = 0;

	for (j = 0; j < HEIGHT; j++) {
		for (i = 0; i < WIDTH; i++) {

			int x_0 = int2fixed(-2) + ((((3 << 20) * i/WIDTH) ) << 8);
			int y_0 = int2fixed(-1) + ((((2 << 20) * j/HEIGHT) ) << 8);

			int x = 0;
			int y = 0;
			int xtmp;
			unsigned char iter;
			unsigned char fiter = 0;

            for (iter = 0; iter < MAX_ITER; iter++) {
                long long abs_squared = fixedmul(x,x) + fixedmul(y,y);

				xtmp = fixedmul(x,x) - fixedmul(y,y) + x_0;
				y = fixedmul(int2fixed(2), fixedmul(x,y)) + y_0;
				x = xtmp;
                
				fiter  +=  abs_squared <= int2fixed(4);
			}

			//get black or white
            unsigned char colour = (fiter >= MAX_ITER) ? 0 : 1;
			//accumulate colour
            count += colour;
			//update image
			img[i][j] = colour;
		}
	}
	return count;
}
Exemplo n.º 14
0
int continue_margin_common(line_list * ll, margin_set * set, active_line * flp, active_line * alp, fixed y0, fixed y1)
{   int code;
#   if ADJUST_SERIF
    section *sect = set->sect;
    fixed yy0 = max(max(y0, alp->start.y), set->y);
    fixed yy1 = min(min(y1, alp->end.y), set->y + fixed_1);

    if (yy0 <= yy1) {
        fixed x00 = (yy0 == y0 ? flp->x_current : AL_X_AT_Y(flp, yy0));
        fixed x10 = (yy0 == y0 ? alp->x_current : AL_X_AT_Y(alp, yy0));
        fixed x01 = (yy1 == y1 ? flp->x_next : AL_X_AT_Y(flp, yy1));
        fixed x11 = (yy1 == y1 ? alp->x_next : AL_X_AT_Y(alp, yy1));
        fixed xmin = min(x00, x01), xmax = max(x10, x11);

        int i0 = fixed2int(xmin) - ll->bbox_left, i;
        int i1 = fixed2int_ceiling(xmax) - ll->bbox_left;

        for (i = i0; i < i1; i++) {
            section *s = &sect[i];
            int x_pixel = int2fixed(i + ll->bbox_left);
            int xl = max(xmin - x_pixel, 0);
            int xu = min(xmax - x_pixel, fixed_1);

            s->x0 = min(s->x0, xl);
            s->x1 = max(s->x1, xu);
            x_pixel+=0; /* Just a place for breakpoint */
        }
        code = store_margin(ll, set, i0, i1);
        if (code < 0)
            return code;
        /* fixme : after ADJUST_SERIF becames permanent,
         * don't call margin_boundary if yy0 > yy1.
         */
    }
#   endif

    code = margin_boundary(ll, set, flp, 0, 0, yy0, yy1, 1, y0, y1);
    if (code < 0)
        return code;
    return margin_boundary(ll, set, alp, 0, 0, yy0, yy1, -1, y0, y1);
}
Exemplo n.º 15
0
/* We must be very careful to follow the center-of-pixel rule in all cases. */
int
gx_default_fill_parallelogram(gx_device * dev,
		 fixed px, fixed py, fixed ax, fixed ay, fixed bx, fixed by,
		  const gx_device_color * pdevc, gs_logical_operation_t lop)
{
    fixed t;
    fixed qx, qy, ym;
    dev_proc_fill_trapezoid((*fill_trapezoid));
    gs_fixed_edge left, right;
    int code;

    /* Make a special fast check for rectangles. */
    if (PARALLELOGRAM_IS_RECT(ax, ay, bx, by)) {
	gs_int_rect r;

	INT_RECT_FROM_PARALLELOGRAM(&r, px, py, ax, ay, bx, by);
	vd_rect(int2fixed(r.p.x), int2fixed(r.p.y), int2fixed(r.q.x), int2fixed(r.q.y),
		    1, (int)pdevc->colors.pure);
	return gx_fill_rectangle_device_rop(r.p.x, r.p.y, r.q.x - r.p.x,
					    r.q.y - r.p.y, pdevc, dev, lop);
    }
    /*
     * Not a rectangle.  Ensure that the 'a' line is to the left of
     * the 'b' line.  Testing ax <= bx is neither sufficient nor
     * necessary: in general, we need to compare the slopes.
     */
    /* Ensure ay >= 0, by >= 0. */
    if (ay < 0)
	px += ax, py += ay, ax = -ax, ay = -ay;
    if (by < 0)
	px += bx, py += by, bx = -bx, by = -by;
    qx = px + ax + bx;
    if ((ax ^ bx) < 0) {	/* In this case, the test ax <= bx is sufficient. */
	if (ax > bx)
	    SWAP(ax, bx, t), SWAP(ay, by, t);
    } else {			/*
				 * Compare the slopes.  We know that ay >= 0, by >= 0,
				 * and ax and bx have the same sign; the lines are in the
				 * correct order iff
				 *          ay/ax >= by/bx, or
				 *          ay*bx >= by*ax
				 * Eventually we can probably find a better way to test this,
				 * without using floating point.
				 */
	if ((double)ay * bx < (double)by * ax)
	    SWAP(ax, bx, t), SWAP(ay, by, t);
    }
    fill_trapezoid = dev_proc(dev, fill_trapezoid);
    qy = py + ay + by;
    left.start.x = right.start.x = px;
    left.start.y = right.start.y = py;
    left.end.x = px + ax;
    left.end.y = py + ay;
    right.end.x = px + bx;
    right.end.y = py + by;
#define ROUNDED_SAME(p1, p2)\
  (fixed_pixround(p1) == fixed_pixround(p2))
    if (ay < by) {
	if (!ROUNDED_SAME(py, left.end.y)) {
	    code = (*fill_trapezoid) (dev, &left, &right, py, left.end.y,
				      false, pdevc, lop);
	    if (code < 0)
		return code;
	}
	left.start = left.end;
	left.end.x = qx, left.end.y = qy;
	ym = right.end.y;
	if (!ROUNDED_SAME(left.start.y, ym)) {
	    code = (*fill_trapezoid) (dev, &left, &right, left.start.y, ym,
				      false, pdevc, lop);
	    if (code < 0)
		return code;
	}
	right.start = right.end;
	right.end.x = qx, right.end.y = qy;
    } else {
	if (!ROUNDED_SAME(py, right.end.y)) {
	    code = (*fill_trapezoid) (dev, &left, &right, py, right.end.y,
				      false, pdevc, lop);
	    if (code < 0)
		return code;
	}
	right.start = right.end;
	right.end.x = qx, right.end.y = qy;
	ym = left.end.y;
	if (!ROUNDED_SAME(right.start.y, ym)) {
	    code = (*fill_trapezoid) (dev, &left, &right, right.start.y, ym,
				      false, pdevc, lop);
	    if (code < 0)
		return code;
	}
	left.start = left.end;
	left.end.x = qx, left.end.y = qy;
    }
    if (!ROUNDED_SAME(ym, qy))
	return (*fill_trapezoid) (dev, &left, &right, ym, qy,
				  false, pdevc, lop);
    else
	return 0;
#undef ROUNDED_SAME
}
Exemplo n.º 16
0
int 
gx_default_fill_linear_color_scanline(gx_device *dev, const gs_fill_attributes *fa,
	int i0, int j, int w,
	const frac31 *c0, const int32_t *c0f, const int32_t *cg_num, int32_t cg_den)
{
    /* This default implementation decomposes the area into constant color rectangles.
       Devices may supply optimized implementations with
       the inversed nesting of the i,k cicles,
       i.e. with enumerating planes first, with a direct writing to the raster,
       and with a fixed bits per component.
     */
    frac31 c[GX_DEVICE_COLOR_MAX_COMPONENTS];
    ulong f[GX_DEVICE_COLOR_MAX_COMPONENTS];
    int i, i1 = i0 + w, bi = i0, k;
    gx_color_index ci0 = 0, ci1;
    const gx_device_color_info *cinfo = &dev->color_info;
    int n = cinfo->num_components;
    int si, ei, code;

    if (j < fixed2int(fa->clip->p.y) ||
	    j > fixed2int_ceiling(fa->clip->q.y)) /* Must be compatible to the clipping logic. */
	return 0;
    for (k = 0; k < n; k++) {
	int shift = cinfo->comp_shift[k];
	int bits = cinfo->comp_bits[k];

	c[k] = c0[k];
	f[k] = c0f[k];
	ci0 |= (gx_color_index)(c[k] >> (sizeof(c[k]) * 8 - 1 - bits)) << shift;
    }
    for (i = i0 + 1; i < i1; i++) {
	ci1 = 0;
	for (k = 0; k < n; k++) {
	    int shift = cinfo->comp_shift[k];
	    int bits = cinfo->comp_bits[k];
	    int32_t m = f[k] + cg_num[k];

	    c[k] += m / cg_den;
	    m -= m / cg_den * cg_den;
	    if (m < 0) {
		c[k]--;
		m += cg_den;
	    }
	    f[k] = m;
	    ci1 |= (gx_color_index)(c[k] >> (sizeof(c[k]) * 8 - 1 - bits)) << shift;
	}
	if (ci1 != ci0) {
	    si = max(bi, fixed2int(fa->clip->p.x));	    /* Must be compatible to the clipping logic. */
	    ei = min(i, fixed2int_ceiling(fa->clip->q.x));  /* Must be compatible to the clipping logic. */
	    if (si < ei) {
		
		if (fa->swap_axes) {
		    vd_rect(int2fixed(j), int2fixed(si), int2fixed(j + 1), int2fixed(ei), 1, (ulong)ci0);
		    code = dev_proc(dev, fill_rectangle)(dev, j, si, 1, ei - si, ci0);
		} else {
		    vd_rect(int2fixed(si), int2fixed(j), int2fixed(ei), int2fixed(j + 1), 1, (ulong)ci0);
		    code = dev_proc(dev, fill_rectangle)(dev, si, j, ei - si, 1, ci0);
		}
		if (code < 0)
		    return code;
	    }
	    bi = i;
	    ci0 = ci1;
	}
    }
    si = max(bi, fixed2int(fa->clip->p.x));	    /* Must be compatible to the clipping logic. */
    ei = min(i, fixed2int_ceiling(fa->clip->q.x));  /* Must be compatible to the clipping logic. */
    if (si < ei) {
	if (fa->swap_axes) {
	    vd_rect(int2fixed(j), int2fixed(si), int2fixed(j + 1), int2fixed(ei), 1, (ulong)ci0);
	    return dev_proc(dev, fill_rectangle)(dev, j, si, 1, ei - si, ci0);
	} else {
	    vd_rect(int2fixed(si), int2fixed(j), int2fixed(ei), int2fixed(j + 1), 1, (ulong)ci0);
	    return dev_proc(dev, fill_rectangle)(dev, si, j, ei - si, 1, ci0);
	}
    }
    return 0;
}
Exemplo n.º 17
0
/*
 * If a Type 1 character is defined with 'seac', store the character codes
 * in chars[0] and chars[1] and return 1; otherwise, return 0 or <0.
 * This is exported only for the benefit of font copying.
 */
int
gs_type1_piece_codes(/*const*/ gs_font_type1 *pfont,
		     const gs_glyph_data_t *pgd, gs_char *chars)
{
    gs_type1_data *const pdata = &pfont->data;
    /*
     * Decode the CharString looking for seac.  We have to process
     * callsubr, callothersubr, and return operators, but if we see
     * any other operators other than [h]sbw, pop, hint operators,
     * or endchar, we can return immediately.  We have to include
     * endchar because it is an (undocumented) equivalent for seac
     * in Type 2 CharStrings: see the cx_endchar case in
     * gs_type2_interpret in gstype2.c.
     *
     * It's really unfortunate that we have to duplicate so much parsing
     * code, but factoring out the parser from the interpreter would
     * involve more restructuring than we're prepared to do right now.
     */
    bool encrypted = pdata->lenIV >= 0;
    fixed cstack[ostack_size];
    fixed *csp;
    ip_state_t ipstack[ipstack_size + 1];
    ip_state_t *ipsp = &ipstack[0];
    const byte *cip;
    crypt_state state;
    int c;
    int code;
    
    CLEAR_CSTACK(cstack, csp);
    cip = pgd->bits.data;
 call:
    state = crypt_charstring_seed;
    if (encrypted) {
	int skip = pdata->lenIV;

	/* Skip initial random bytes */
	for (; skip > 0; ++cip, --skip)
	    decrypt_skip_next(*cip, state);
    }
 top:
    for (;;) {
	uint c0 = *cip++;

	charstring_next(c0, state, c, encrypted);
	if (c >= c_num1) {
	    /* This is a number, decode it and push it on the stack. */
	    if (c < c_pos2_0) {	/* 1-byte number */
		decode_push_num1(csp, cstack, c);
	    } else if (c < cx_num4) {	/* 2-byte number */
		decode_push_num2(csp, cstack, c, cip, state, encrypted);
	    } else if (c == cx_num4) {	/* 4-byte number */
		long lw;

		decode_num4(lw, cip, state, encrypted);
		CS_CHECK_PUSH(csp, cstack);
		*++csp = int2fixed(lw);
	    } else		/* not possible */
		return_error(gs_error_invalidfont);
	    continue;
	}
#define cnext CLEAR_CSTACK(cstack, csp); goto top
	switch ((char_command) c) {
	default:
	    goto out;
	case c_callsubr:
	    c = fixed2int_var(*csp) + pdata->subroutineNumberBias;
	    code = pdata->procs.subr_data
		(pfont, c, false, &ipsp[1].cs_data);
	    if (code < 0)
		return_error(code);
	    --csp;
	    ipsp->ip = cip, ipsp->dstate = state;
	    ++ipsp;
	    cip = ipsp->cs_data.bits.data;
	    goto call;
	case c_return:
	    gs_glyph_data_free(&ipsp->cs_data, "gs_type1_piece_codes");
	    --ipsp;
	    cip = ipsp->ip, state = ipsp->dstate;
	    goto top;
	case cx_hstem:
	case cx_vstem:
	case c1_hsbw:
	    cnext;
	case cx_endchar:
	    if (csp < cstack + 3)
		goto out;	/* not seac */
	do_seac:
	    /* This is the payoff for all this code! */
	    chars[0] = fixed2int(csp[-1]);
	    chars[1] = fixed2int(csp[0]);
	    return 1;
	case cx_escape:
	    charstring_next(*cip, state, c, encrypted);
	    ++cip;
	    switch ((char1_extended_command) c) {
	    default:
		goto out;
	    case ce1_vstem3:
	    case ce1_hstem3:
	    case ce1_sbw:
		cnext;
	    case ce1_pop:
		/*
		 * pop must do nothing, since it is used after
		 * subr# 1 3 callothersubr.
		 */
		goto top;
	    case ce1_seac:
		goto do_seac;
	    case ce1_callothersubr:
		switch (fixed2int_var(*csp)) {
		default:
		    goto out;
		case 3:
		    csp -= 2;
		    goto top;
		case 12:
		case 13:
		case 14:
		case 15:
		case 16:
		case 17:
		case 18:
		    cnext;
		}
	    }
	}
#undef cnext
    }
 out:
    return 0;
}
Exemplo n.º 18
0
int main() {
    int i, j, m, n;

    // gaussian low pass filter
    const float gaussFloat[SIZE][SIZE] = {
        {0.1019, 0.1154, 0.1019},
        {0.1154, 0.1308, 0.1154},
        {0.1019, 0.1154, 0.1019}
    };

    int gauss[SIZE][SIZE];
    for (m = 0; m < SIZE; m++) {
        for (n = 0; n < SIZE; n++) {
            gauss[m][n] = gaussFloat[m][n] * int2fixed(1);
        }
    }

    /*
    const float gauss[SIZE][SIZE] = {
        {1, 2, 1},
        {2, 5, 2},
        {1, 2, 1},
    };
    */

    unsigned char blur[width-2][height-2];

    int count = 0;

    /*
     * Non-striped memory version
    for (j = 0; j < height-2; j++) {
        for (i = 0; i < width-2; i++) {
#ifdef FLOAT
            float sumFloat = 0;
#endif
            int sum = 0;
            for (m = 0; m < SIZE; m++) {
                for (n = 0; n < SIZE; n++) {
#ifdef FLOAT
                    sumFloat += gaussFloat[m][n]*img[i+m][j+n];
#endif
                    sum += fixedmul(gauss[m][n], int2fixed(img[i+m][j+n]));
                }
            }
            blur[i][j] = fixed2int(sum);
            count += blur[i][j];
            //blur[i+1][j+1] = sum/17;
#ifdef FLOAT
            float diff = fabs((float)blur[i][j]-sumFloat);
            assert (diff < 1.2);
            printf("fixed: %d expected: %f diff: %f\n", blur[i][j], sumFloat, diff);
#endif
        }
    }
    */



    int order = 0;
    int j_stride = 0;
    for (j = 0; j < height-2; j++) {
        // im00 im10 im20
        // im01 im11 im21
        // im02 im12 im22
        unsigned char im00, im01, im02, im10, im11, im12, im20, im21, im22;
        unsigned char tmp00, tmp10, tmp01, tmp11, tmp20, tmp21;
        i = 0;
        int j1, j2, j3;
        if (order == 0) {
            j1 = j2 = j3 = j_stride;
        } else if (order == 1) {
            j2 = j3 = j_stride;
            j1 = j_stride+1;
        } else {
            j3 = j_stride;
            j1 = j2 = j_stride+1;
        }

        im00 = img1[i][j1]; im10 = img1[i+1][j1];
        //assert(img[i][j]==im00);
        im01 = img2[i][j2]; im11 = img2[i+1][j2];
        im02 = img3[i][j3]; im12 = img3[i+1][j3];

        if (order == 0) {
        } else if (order == 1) {
            tmp00 = im00; tmp10 = im10;
            // first row from img2
            im00 = im01; im10 = im11;
            // second row from img3
            im01 = im02; im11 = im12;
            // third row from img1
            im02 = tmp00; im12 = tmp10;
        } else {
            tmp00 = im00; tmp10 = im10;
            tmp01 = im01; tmp11 = im11;
            // first row from img3
            im00 = im02; im10 = im12;
            // second row from img1
            im01 = tmp00; im11 = tmp10;
            // third row from img2
            im02 = tmp01; im12 = tmp11;
        }

        for (i = 0; i < width-2; i++) {
            im20 = img1[i+2][j1];
            im21 = img2[i+2][j2];
            im22 = img3[i+2][j3];

            int pred1 = (order == 1);
            tmp20 = im20;
            // first row from img2
            im20 = (pred1) ? im21 : im20;
            // second row from img3
            im21 = (pred1) ? im22: im21;
            // third row from img1
            im22 = (pred1) ? tmp20: im22;

            tmp20 = im20;
            tmp21 = im21;
            int pred2 = (order == 2);

            // first row from img3
            im20 = (pred2) ? im22 : im20;
            // second row from img1
            im21 = (pred2) ? tmp20 : im21;
            // third row from img2
            im22 = (pred2) ? tmp21 : im22;

            int sum = 0;
            //assert(img[i][j]==im00);
            sum += fixedmul(gauss[0][0], int2fixed(im00));
            sum += fixedmul(gauss[0][1], int2fixed(im01));
            sum += fixedmul(gauss[0][2], int2fixed(im02));
            sum += fixedmul(gauss[1][0], int2fixed(im10));
            sum += fixedmul(gauss[1][1], int2fixed(im11));
            sum += fixedmul(gauss[1][2], int2fixed(im12));
            sum += fixedmul(gauss[2][0], int2fixed(im20));
            sum += fixedmul(gauss[2][1], int2fixed(im21));
            sum += fixedmul(gauss[2][2], int2fixed(im22));

            blur[i][j] = fixed2int(sum);
            //blur[i+1][j+1] = sum/17;
            count += blur[i][j];

#ifdef FLOAT
            float sumFloat = 0;
            for (m = 0; m < SIZE; m++) {
                for (n = 0; n < SIZE; n++) {
                    sumFloat += gaussFloat[m][n]*img[i+m][j+n];
                }
            }
            float diff = fabs((float)blur[i][j]-sumFloat);
            assert (diff < 1.2);
            printf("fixed: %d expected: %f diff: %f\n", blur[i][j], sumFloat, diff);
#endif

            // shift over to the right by 1
            im00 = im10; im10 = im20;
            im01 = im11; im11 = im21;
            im02 = im12; im12 = im22;
        }

        if (order == 2) {
            order = 0;
            j_stride++;
        } else {
            order++;
        }
    }

#ifdef PRINT_IMG
    //print_image(width, height, 255, img);
    print_image(width-2, height-2, 255, blur);
#else

    printf("count: %d\n", count);
    if (count == 1931186) {
        printf(" _____         _____ _____ ______ _____  \n");
        printf("|  __ \\ /\\    / ____/ ____|  ____|  __ \\ \n");
        printf("| |__) /  \\  | (___| (___ | |__  | |  | |\n");
        printf("|  ___/ /\\ \\  \\___ \\\\___ \\|  __| | |  | |\n");
        printf("| |  / ____ \\ ____) |___) | |____| |__| |\n");
        printf("|_| /_/    \\_\\_____/_____/|______|_____/ \n");
    } else {
        printf(" ______      _____ _      ______ _____  \n");
        printf("|  ____/\\   |_   _| |    |  ____|  __ \\ \n");
        printf("| |__ /  \\    | | | |    | |__  | |  | |\n");
        printf("|  __/ /\\ \\   | | | |    |  __| | |  | |\n");
        printf("| | / ____ \\ _| |_| |____| |____| |__| |\n");
        printf("|_|/_/    \\_\\_____|______|______|_____/ \n");
    }

#endif

    return count;
}
Exemplo n.º 19
0
/*
 * Continue interpreting a Type 1 charstring.  If str != 0, it is taken as
 * the byte string to interpret.  Return 0 on successful completion, <0 on
 * error, or >0 when client intervention is required (or allowed).  The int*
 * argument is where the othersubr # is stored for callothersubr.
 */
int
gs_type1_interpret(gs_type1_state * pcis, const gs_glyph_data_t *pgd,
		   int *pindex)
{
    gs_font_type1 *pfont = pcis->pfont;
    gs_type1_data *pdata = &pfont->data;
    t1_hinter *h = &pcis->h;
    bool encrypted = pdata->lenIV >= 0;
    fixed cstack[ostack_size];

#define cs0 cstack[0]
#define ics0 fixed2int_var(cs0)
#define cs1 cstack[1]
#define ics1 fixed2int_var(cs1)
#define cs2 cstack[2]
#define ics2 fixed2int_var(cs2)
#define cs3 cstack[3]
#define ics3 fixed2int_var(cs3)
#define cs4 cstack[4]
#define ics4 fixed2int_var(cs4)
#define cs5 cstack[5]
#define ics5 fixed2int_var(cs5)
    cs_ptr csp;
#define clear CLEAR_CSTACK(cstack, csp)
    ip_state_t *ipsp = &pcis->ipstack[pcis->ips_count - 1];
    register const byte *cip;
    register crypt_state state;
    register int c;
    int code = 0;
    fixed ftx = pcis->origin.x, fty = pcis->origin.y;

    switch (pcis->init_done) {
	case -1:
	    t1_hinter__init(h, pcis->path);
	    break;
	case 0:
	    gs_type1_finish_init(pcis);	/* sets origin */
	    ftx = pcis->origin.x, fty = pcis->origin.y;
            code = t1_hinter__set_mapping(h, &pcis->pis->ctm,
			    &pfont->FontMatrix, &pfont->base->FontMatrix,
			    pcis->scale.x.log2_unit, pcis->scale.x.log2_unit,
			    pcis->scale.x.log2_unit - pcis->log2_subpixels.x,
			    pcis->scale.y.log2_unit - pcis->log2_subpixels.y,
			    pcis->origin.x, pcis->origin.y, 
			    gs_currentaligntopixels(pfont->dir));
	    if (code < 0)
	    	return code;
	    code = t1_hinter__set_font_data(h, 1, pdata, pcis->no_grid_fitting);
	    if (code < 0)
	    	return code;
	    break;
	default /*case 1 */ :
	    break;
    }
    INIT_CSTACK(cstack, csp, pcis);

    if (pgd == 0)
	goto cont;
    ipsp->cs_data = *pgd;
    cip = pgd->bits.data;
  call:state = crypt_charstring_seed;
    if (encrypted) {
	int skip = pdata->lenIV;

	/* Skip initial random bytes */
	for (; skip > 0; ++cip, --skip)
	    decrypt_skip_next(*cip, state);
    }
    goto top;
  cont:cip = ipsp->ip;
    state = ipsp->dstate;
  top:for (;;) {
	uint c0 = *cip++;

	charstring_next(c0, state, c, encrypted);
	if (c >= c_num1) {
	    /* This is a number, decode it and push it on the stack. */

	    if (c < c_pos2_0) {	/* 1-byte number */
		decode_push_num1(csp, cstack, c);
	    } else if (c < cx_num4) {	/* 2-byte number */
		decode_push_num2(csp, cstack, c, cip, state, encrypted);
	    } else if (c == cx_num4) {	/* 4-byte number */
		long lw;

		decode_num4(lw, cip, state, encrypted);
		CS_CHECK_PUSH(csp, cstack);
		*++csp = int2fixed(lw);
		if (lw != fixed2long(*csp)) {
		    /*
		     * We handle the only case we've ever seen that
		     * actually uses such large numbers specially.
		     */
		    long denom;

		    c0 = *cip++;
		    charstring_next(c0, state, c, encrypted);
		    if (c < c_num1)
			return_error(gs_error_rangecheck);
		    if (c < c_pos2_0)
			decode_num1(denom, c);
		    else if (c < cx_num4)
			decode_num2(denom, c, cip, state, encrypted);
		    else if (c == cx_num4)
			decode_num4(denom, cip, state, encrypted);
		    else
			return_error(gs_error_invalidfont);
		    c0 = *cip++;
		    charstring_next(c0, state, c, encrypted);
		    if (c != cx_escape)
			return_error(gs_error_rangecheck);
		    c0 = *cip++;
		    charstring_next(c0, state, c, encrypted);
		    if (c != ce1_div)
			return_error(gs_error_rangecheck);
		    *csp = float2fixed((double)lw / denom);
		}
	    } else		/* not possible */
		return_error(gs_error_invalidfont);
	  pushed:if_debug3('1', "[1]%d: (%d) %f\n",
		      (int)(csp - cstack), c, fixed2float(*csp));
	    continue;
	}
#ifdef DEBUG
	if (gs_debug['1']) {
	    static const char *const c1names[] =
	    {char1_command_names};

	    if (c1names[c] == 0)
		dlprintf2("[1]0x%lx: %02x??\n", (ulong) (cip - 1), c);
	    else
		dlprintf3("[1]0x%lx: %02x %s\n", (ulong) (cip - 1), c,
			  c1names[c]);
	}
#endif
	switch ((char_command) c) {
#define cnext clear; goto top
#define inext goto top

		/* Commands with identical functions in Type 1 and Type 2, */
		/* except for 'escape'. */

	    case c_undef0:
	    case c_undef2:
	    case c_undef17:
		return_error(gs_error_invalidfont);
	    case c_callsubr:
		c = fixed2int_var(*csp) + pdata->subroutineNumberBias;
		code = pdata->procs.subr_data
		    (pfont, c, false, &ipsp[1].cs_data);
		if (code < 0)
		    return_error(code);
		--csp;
		ipsp->ip = cip, ipsp->dstate = state;
		++ipsp;
		cip = ipsp->cs_data.bits.data;
		goto call;
	    case c_return:
		gs_glyph_data_free(&ipsp->cs_data, "gs_type1_interpret");
		--ipsp;
		goto cont;
	    case c_undoc15:
		/* See gstype1.h for information on this opcode. */
		cnext;

		/* Commands with similar but not identical functions */
		/* in Type 1 and Type 2 charstrings. */

	    case cx_hstem:
                code = t1_hinter__hstem(h, cs0, cs1);
		if (code < 0)
		    return code;
		cnext;
	    case cx_vstem:
                code = t1_hinter__vstem(h, cs0, cs1);
		if (code < 0)
		    return code;
		cnext;
	    case cx_vmoveto:
		cs1 = cs0;
		cs0 = 0;
	      move:		/* cs0 = dx, cs1 = dy for hint checking. */
                code = t1_hinter__rmoveto(h, cs0, cs1);
		goto cc;
	    case cx_rlineto:
	      line:		/* cs0 = dx, cs1 = dy for hint checking. */
                code = t1_hinter__rlineto(h, cs0, cs1);
	      cc:if (code < 0)
		    return code;
		cnext;
	    case cx_hlineto:
		cs1 = 0;
		goto line;
	    case cx_vlineto:
		cs1 = cs0;
		cs0 = 0;
		goto line;
	    case cx_rrcurveto:
                code = t1_hinter__rcurveto(h, cs0, cs1, cs2, cs3, cs4, cs5);
		goto cc;
	    case cx_endchar:
                code = t1_hinter__endchar(h, (pcis->seac_accent >= 0));
		if (code < 0)
		    return code;
                if (pcis->seac_accent < 0) {
                    code = t1_hinter__endglyph(h);
		    if (code < 0)
			return code;
		    code = gx_setcurrentpoint_from_path(pcis->pis, pcis->path);
		    if (code < 0)
			return code;
		}
		code = gs_type1_endchar(pcis);
		if (code == 1) {
		    /* do accent of seac */
		    ipsp = &pcis->ipstack[pcis->ips_count - 1];
		    cip = ipsp->cs_data.bits.data;
		    goto call;
		}
		return code;
	    case cx_rmoveto:
		goto move;
	    case cx_hmoveto:
		cs1 = 0;
		goto move;
	    case cx_vhcurveto:
                code = t1_hinter__rcurveto(h, 0, cs0, cs1, cs2, cs3, 0);
		goto cc;
	    case cx_hvcurveto:
                code = t1_hinter__rcurveto(h, cs0, 0, cs1, cs2, 0, cs3);
		goto cc;

		/* Commands only recognized in Type 1 charstrings, */
		/* plus 'escape'. */

	    case c1_closepath:
                code = t1_hinter__closepath(h);
		goto cc;
	    case c1_hsbw:
                if (!h->seac_flag) {
		    fixed sbx = cs0, sby = fixed_0, wx = cs1, wy = fixed_0;

		    if (pcis->sb_set) {
			sbx = pcis->lsb.x;
			sby = pcis->lsb.y;
		    }
		    if (pcis->width_set) {
			wx = pcis->width.x;
			wy = pcis->width.y;
		    }
		    code = t1_hinter__sbw(h, sbx, sby, wx, wy);
                } else
                    code = t1_hinter__sbw_seac(h, pcis->adxy.x, pcis->adxy.y);
		if (code < 0)
		    return code;
		gs_type1_sbw(pcis, cs0, fixed_0, cs1, fixed_0);
		cs1 = fixed_0;
rsbw:		/* Give the caller the opportunity to intervene. */
		pcis->os_count = 0;	/* clear */
		ipsp->ip = cip, ipsp->dstate = state;
		pcis->ips_count = ipsp - &pcis->ipstack[0] + 1;
		/* If we aren't in a seac, do nothing else now; */
		/* finish_init will take care of the rest. */
		if (pcis->init_done < 0) {
		    /* Finish init when we return. */
		    pcis->init_done = 0;
		} else {
		    /*
		     * Accumulate the side bearing now, but don't do it
		     * a second time for the base character of a seac.
		     */
		    if (pcis->seac_accent >= 0) {
			/*
			 * As a special hack to work around a bug in
			 * Fontographer, we deal with the (illegal)
			 * situation in which the side bearing of the
			 * accented character (save_lsbx) is different from
			 * the side bearing of the base character (cs0/cs1).
			 */
			fixed dsbx = cs0 - pcis->save_lsb.x;
			fixed dsby = cs1 - pcis->save_lsb.y;

			if (dsbx | dsby) {
			    pcis->lsb.x += dsbx;
			    pcis->lsb.y += dsby;
			    pcis->save_adxy.x -= dsbx;
			    pcis->save_adxy.y -= dsby;
			}
		    }
		}
		return type1_result_sbw;
	    case cx_escape:
		charstring_next(*cip, state, c, encrypted);
		++cip;
#ifdef DEBUG
		if (gs_debug['1'] && c < char1_extended_command_count) {
		    static const char *const ce1names[] =
		    {char1_extended_command_names};

		    if (ce1names[c] == 0)
			dlprintf2("[1]0x%lx: %02x??\n", (ulong) (cip - 1), c);
		    else
			dlprintf3("[1]0x%lx: %02x %s\n", (ulong) (cip - 1), c,
				  ce1names[c]);
		}
#endif
		switch ((char1_extended_command) c) {
		    case ce1_dotsection:
                        code = t1_hinter__dotsection(h);
			if (code < 0)
			    return code;
			cnext;
		    case ce1_vstem3:
                        code = t1_hinter__vstem3(h, cs0, cs1, cs2, cs3, cs4, cs5);
			if (code < 0)
			    return code;
			cnext;
		    case ce1_hstem3:
                        code = t1_hinter__hstem3(h, cs0, cs1, cs2, cs3, cs4, cs5);
			if (code < 0)
			    return code;
			cnext;
		    case ce1_seac:
			code = gs_type1_seac(pcis, cstack + 1, cstack[0],
					     ipsp);
			if (code != 0) {
			    *pindex = ics3;
			    return code;
			}
			clear;
			cip = ipsp->cs_data.bits.data;
			goto call;
		    case ce1_sbw:
                        if (!h->seac_flag)
                            code = t1_hinter__sbw(h, cs0, cs1, cs2, cs3);
                        else
                            code = t1_hinter__sbw_seac(h, cs0 + pcis->adxy.x , cs1 + pcis->adxy.y);
			if (code < 0)
			    return code;
			gs_type1_sbw(pcis, cs0, cs1, cs2, cs3);
			goto rsbw;
		    case ce1_div:
			csp[-1] = float2fixed((double)csp[-1] / (double)*csp);
			--csp;
			goto pushed;
		    case ce1_undoc15:
			/* See gstype1.h for information on this opcode. */
			cnext;
		    case ce1_callothersubr:
			{
			    int num_results;
			    /* We must remember to pop both the othersubr # */
			    /* and the argument count off the stack. */
			    switch (*pindex = fixed2int_var(*csp)) {
				case 0:
				    {	
					fixed fheight = csp[-4];
					/* Assume the next two opcodes */
					/* are `pop' `pop'.  Unfortunately, some */
					/* Monotype fonts put these in a Subr, */
					/* so we can't just look ahead in the */
					/* opcode stream. */
					pcis->ignore_pops = 2;
					csp[-4] = csp[-3] - pcis->asb_diff;
					csp[-3] = csp[-2];
					csp -= 3;
					code = t1_hinter__flex_end(h, fheight);
				    }
				    if (code < 0)
					return code;
				    pcis->flex_count = flex_max;	/* not inside flex */
				    inext;
				case 1:
				    code = t1_hinter__flex_beg(h);
				    if (code < 0)
					return code;
				    pcis->flex_count = 1;
				    csp -= 2;
				    inext;
				case 2:
				    if (pcis->flex_count >= flex_max)
					return_error(gs_error_invalidfont);
				    code = t1_hinter__flex_point(h);
				    if (code < 0)
					return code;
				    csp -= 2;
				    inext;
				case 3:
				    /* Assume the next opcode is a `pop'. */
				    /* See above as to why we don't just */
				    /* look ahead in the opcode stream. */
				    pcis->ignore_pops = 1;
                                    code = t1_hinter__drop_hints(h);
				    if (code < 0)
					return code;
				    csp -= 2;
				    inext;
				case 12:
				case 13:
				    /* Counter control isn't implemented. */
				    cnext;
				case 14:
				    num_results = 1;
				  blend:
				    code = gs_type1_blend(pcis, csp,
							  num_results);
				    if (code < 0)
					return code;
				    csp -= code;
				    inext;
				case 15:
				    num_results = 2;
				    goto blend;
				case 16:
				    num_results = 3;
				    goto blend;
				case 17:
				    num_results = 4;
				    goto blend;
				case 18:
				    num_results = 6;
				    goto blend;
			    }
			}
			/* Not a recognized othersubr, */
			/* let the client handle it. */
			{
			    int scount = csp - cstack;
			    int n;

			    /* Copy the arguments to the caller's stack. */
			    if (scount < 1 || csp[-1] < 0 ||
				csp[-1] > int2fixed(scount - 1)
				)
				return_error(gs_error_invalidfont);
			    n = fixed2int_var(csp[-1]);
			    code = (*pdata->procs.push_values)
				(pcis->callback_data, csp - (n + 1), n);
			    if (code < 0)
				return_error(code);
			    scount -= n + 1;
			    /* Exit to caller */
			    ipsp->ip = cip, ipsp->dstate = state;
			    pcis->os_count = scount;
			    pcis->ips_count = ipsp - &pcis->ipstack[0] + 1;
			    if (scount)
				memcpy(pcis->ostack, cstack, scount * sizeof(fixed));
			    return type1_result_callothersubr;
			}
		    case ce1_pop:
			/* Check whether we're ignoring the pops after */
			/* a known othersubr. */
			if (pcis->ignore_pops != 0) {
			    pcis->ignore_pops--;
			    inext;
			}
			CS_CHECK_PUSH(csp, cstack);
			++csp;
			code = (*pdata->procs.pop_value)
			    (pcis->callback_data, csp);
			if (code < 0)
			    return_error(code);
			goto pushed;
		    case ce1_setcurrentpoint:
			t1_hinter__setcurrentpoint(h, cs0, cs1);
			cs0 += pcis->adxy.x;
			cs1 += pcis->adxy.y;
			cnext;
		    default:
			return_error(gs_error_invalidfont);
		}
		/*NOTREACHED */

		/* Fill up the dispatch up to 32. */

	      case_c1_undefs:
	    default:		/* pacify compiler */
		return_error(gs_error_invalidfont);
	}
    }
}
Exemplo n.º 20
0
/* Draw a one-pixel-wide line. */
int
gx_default_draw_thin_line(gx_device * dev,
                          fixed fx0, fixed fy0, fixed fx1, fixed fy1,
                    const gx_device_color * pdevc, gs_logical_operation_t lop,
                          fixed adjustx, fixed adjusty)
{
    int ix, iy, itox, itoy;
    int epsilon;

    return_if_interrupt(dev->memory);

    /* This function was updated in revision 10391 to fix problems with
     * mispositioned thin lines. This introduced a regression (see bug
     * 691030). The code was then reworked to behave in what we believe is
     * the correct manner, but this causes unacceptable problems with PCL
     * output. While the current PCL work is underway, we have therefore
     * amended this code to take note of the fill adjust values; if non-
     * zero (i.e. postscript) we do "the correct thing". If zero, we do
     * what we used to.
     *
     * The one case where this doesn't work is in the case where our PCL
     * implementation thickens lines slightly to try and approximate HP
     * printer behaviour. Here we do use a non-zero fill_adjust and hence
     * have differences; tests show that these are acceptable though.
     *
     * It is hoped that this difference in behaviour will be short lived.
     */

    epsilon = ((adjustx | adjusty) == 0 ? fixed_epsilon : 0);

    {
        fixed h = fy1 - fy0;
        fixed w = fx1 - fx0;
        fixed tf;
        bool swap_axes;
        gs_fixed_edge left, right;

        if ((w < 0 ? -w : w) <= (h < 0 ? -h : h)) {
            /* A "mostly-vertical" line */
            if (h < 0)
                SWAP(fx0, fx1, tf), SWAP(fy0, fy1, tf),
                    h = -h;
            /* So we are plotting a trapezoid with horizontal thin edges.
             * If we are drawing a non-axis aligned trap, then we check
             * for whether a triangular extension area on the end covers an
             * additional pixel centre; if so, we fill an extra pixel.
             * If we are drawing an axis aligned trap and fill adjust is 0,
             * then we shouldn't need to do this.
             * If we are drawing an axis aligned trap, and fill adjust is non
             * zero, then perform the check, but with a "butt cap" rather than
             * a "triangle cap" region.
             * See bug 687721 and bug 693212 for this history of this.
             */
            if (w == 0 && adjusty) {
                int deltay;
                deltay = int2fixed(fixed2int_var(fy1)) + fixed_half -fy1;

                if ((deltay > 0) && (deltay <= fixed_half))
                {
                    int c = gx_fill_rectangle_device_rop(fixed2int_var(fx1),
                                                         fixed2int_var(fy1),
                                                         1,1,pdevc,dev,lop);
                    if (c < 0) return c;
                }
                deltay = int2fixed(fixed2int_var(fy0)) + fixed_half -fy0;

                if ((deltay < 0) && (deltay >= -fixed_half))
                {
                    int c = gx_fill_rectangle_device_rop(fixed2int_var(fx0),
                                                         fixed2int_var(fy0),
                                                         1,1,pdevc,dev,lop);
                    if (c < 0) return c;
                }
            } else if (w != 0) {
                int deltax, deltay;
                deltay = int2fixed(fixed2int_var(fy1)) + fixed_half -fy1;
                deltax = int2fixed(fixed2int_var(fx1)) + fixed_half -fx1;

                if (deltax < 0) deltax=-deltax;
                if ((deltay > 0) && (deltay <= fixed_half) &&
                    (deltay+deltax <= fixed_half))
                {
                    int c = gx_fill_rectangle_device_rop(fixed2int_var(fx1),
                                                         fixed2int_var(fy1),
                                                         1,1,pdevc,dev,lop);
                    if (c < 0) return c;
                }
                deltay = int2fixed(fixed2int_var(fy0)) + fixed_half -fy0;
                deltax = int2fixed(fixed2int_var(fx0)) + fixed_half -fx0;

                if (deltax < 0) deltax=-deltax;
                if ((deltay < 0) && (deltay >= -fixed_half) &&
                    (-deltay+deltax <= fixed_half))
                {
                    int c = gx_fill_rectangle_device_rop(fixed2int_var(fx0),
                                                         fixed2int_var(fy0),
                                                         1,1,pdevc,dev,lop);
                    if (c < 0) return c;
                }
            }
            /* Can we treat it as a vertical rectangle? */
            ix   = fixed2int_var(fx0-epsilon);
            itox = fixed2int_var(fx1-epsilon);
            if (itox == ix) {
                /* Figure out the start/height, allowing for our "covers
                 * centre of pixel" rule. */
                iy   = fixed2int_var(fy0+fixed_half-fixed_epsilon);
                itoy = fixed2int_var(fy1+fixed_half-fixed_epsilon);
                itoy = itoy - iy;
                if (itoy <= 0) {
                    /* Zero height; drawing this as a trapezoid wouldn't
                     * fill any pixels, so just exit. */
                    return 0;
                }
                return gx_fill_rectangle_device_rop(ix, iy, 1, itoy,
                                                    pdevc, dev, lop);
            }
            left.start.x = fx0 - fixed_half + fixed_epsilon - epsilon;
            right.start.x = left.start.x + fixed_1;
            left.end.x = fx1 - fixed_half + fixed_epsilon - epsilon;
            right.end.x = left.end.x + fixed_1;
            left.start.y = right.start.y = fy0;
            left.end.y = right.end.y = fy1;
            swap_axes = false;
        } else {
            /* A "mostly-horizontal" line */
            if (w < 0)
                SWAP(fx0, fx1, tf), SWAP(fy0, fy1, tf),
                    w = -w;
            /* So we are plotting a trapezoid with vertical thin edges
             * Check for whether a triangular extension area on the end
             * covers an additional pixel centre. */
            if (h == 0 && adjustx) {
                int deltax;
                deltax = int2fixed(fixed2int_var(fx1)) + fixed_half -fx1;

                if ((deltax > 0) && (deltax <= fixed_half))
                {
                    int c = gx_fill_rectangle_device_rop(fixed2int_var(fx1),
                                                         fixed2int_var(fy1),
                                                         1,1,pdevc,dev,lop);
                    if (c < 0) return c;
                }
                deltax = int2fixed(fixed2int_var(fx0)) + fixed_half -fx0;

                if ((deltax < 0) && (deltax >= -fixed_half))
                {
                    int c = gx_fill_rectangle_device_rop(fixed2int_var(fx0),
                                                         fixed2int_var(fy0),
                                                         1,1,pdevc,dev,lop);
                    if (c < 0) return c;
                }
            } else if (h != 0) {
                int deltax, deltay;
                deltax = int2fixed(fixed2int_var(fx1)) + fixed_half -fx1;
                deltay = int2fixed(fixed2int_var(fy1)) + fixed_half -fy1;

                if (deltay < 0) deltay=-deltay;
                if ((deltax > 0) && (deltax <= fixed_half) &&
                    (deltax+deltay <= fixed_half))
                {
                    int c = gx_fill_rectangle_device_rop(fixed2int_var(fx1),
                                                         fixed2int_var(fy1),
                                                         1,1,pdevc,dev,lop);
                    if (c < 0) return c;
                }
                deltax = int2fixed(fixed2int_var(fx0)) + fixed_half -fx0;
                deltay = int2fixed(fixed2int_var(fy0)) + fixed_half -fy0;

                if (deltay < 0) deltay=-deltay;
                if ((deltax < 0) && (deltax >= -fixed_half) &&
                    (-deltax+deltay <= fixed_half))
                {
                    int c = gx_fill_rectangle_device_rop(fixed2int_var(fx0),
                                                         fixed2int_var(fy0),
                                                         1,1,pdevc,dev,lop);
                    if (c < 0) return c;
                }
            }
            /* Can we treat this as a horizontal rectangle? */
            iy   = fixed2int_var(fy0 - epsilon);
            itoy = fixed2int_var(fy1 - epsilon);
            if (itoy == iy) {
                /* Figure out the start/width, allowing for our "covers
                * centre of pixel" rule. */
                ix   = fixed2int_var(fx0+fixed_half-fixed_epsilon);
                itox = fixed2int_var(fx1+fixed_half-fixed_epsilon);
                itox = itox - ix;
                if (itox <= 0) {
                    /* Zero width; drawing this as a trapezoid wouldn't
                     * fill any pixels, so just exit. */
                    return 0;
                }
                return gx_fill_rectangle_device_rop(ix, iy, itox, 1,
                                                    pdevc, dev, lop);
            }
            left.start.x = fy0 - fixed_half + fixed_epsilon - epsilon;
            right.start.x = left.start.x + fixed_1;
            left.end.x = fy1 - fixed_half + fixed_epsilon - epsilon;
            right.end.x = left.end.x + fixed_1;
            left.start.y = right.start.y = fx0;
            left.end.y = right.end.y = fx1;
            swap_axes = true;
        }
        return (*dev_proc(dev, fill_trapezoid)) (dev, &left, &right,
                                                 left.start.y, left.end.y,
                                                 swap_axes, pdevc, lop);
    }
}
Exemplo n.º 21
0
int
mem_gray8_rgb24_strip_copy_rop(gx_device * dev,
             const byte * sdata, int sourcex, uint sraster, gx_bitmap_id id,
                               const gx_color_index * scolors,
           const gx_strip_bitmap * textures, const gx_color_index * tcolors,
                               int x, int y, int width, int height,
                       int phase_x, int phase_y, gs_logical_operation_t lop)
{
    gx_device_memory *mdev = (gx_device_memory *) dev;
    gs_rop3_t rop = lop_rop(lop);
    gx_color_index const_source = gx_no_color_index;
    gx_color_index const_texture = gx_no_color_index;
    uint draster = mdev->raster;
    int line_count;
    byte *drow, *base;
    int depth = dev->color_info.depth;
    int bpp = depth >> 3;       /* bytes per pixel, 1 or 3 */
    gx_color_index all_ones = ((gx_color_index) 1 << depth) - 1;
    gx_color_index strans =
        (lop & lop_S_transparent ? all_ones : gx_no_color_index);
    gx_color_index ttrans =
        (lop & lop_T_transparent ? all_ones : gx_no_color_index);
#ifdef USE_RUN_ROP
    rop_run_op ropper;
#ifdef COMPARE_AND_CONTRAST
    static byte testbuffer[4096];
    static byte *start;
    static int bytelen;
#endif
#endif

    /* Check for constant source. */
    if (!rop3_uses_S(rop))
        const_source = 0;       /* arbitrary */
    else if (scolors != 0 && scolors[0] == scolors[1]) {
        /* Constant source */
        const_source = scolors[0];
        if (const_source == gx_device_black(dev))
            rop = rop3_know_S_0(rop);
        else if (const_source == gx_device_white(dev))
            rop = rop3_know_S_1(rop);
    }

    /* Check for constant texture. */
    if (!rop3_uses_T(rop))
        const_texture = 0;      /* arbitrary */
    else if (tcolors != 0 && tcolors[0] == tcolors[1]) {
        /* Constant texture */
        const_texture = tcolors[0];
        if (const_texture == gx_device_black(dev))
            rop = rop3_know_T_0(rop);
        else if (const_texture == gx_device_white(dev))
            rop = rop3_know_T_1(rop);
    }

    if (bpp == 1 &&
        (gx_device_has_color(dev) ||
         (gx_device_black(dev) != 0 || gx_device_white(dev) != all_ones))
        ) {
        /*
         * This is an 8-bit device but not gray-scale.  Except in a few
         * simple cases, we have to use the slow algorithm that converts
         * values to and from RGB.
         */
        gx_color_index bw_pixel;

        switch (rop) {
        case rop3_0:
            bw_pixel = gx_device_black(dev);
            goto bw;
        case rop3_1:
            bw_pixel = gx_device_white(dev);
bw:         if (bw_pixel == 0x00)
                rop = rop3_0;
            else if (bw_pixel == 0xff)
                rop = rop3_1;
            else
                goto df;
            break;
        case rop3_D:
            break;
        case rop3_S:
            if (lop & lop_S_transparent)
                goto df;
            break;
        case rop3_T:
            if (lop & lop_T_transparent)
                goto df;
            break;
        default:
df:         return mem_default_strip_copy_rop(dev,
                                              sdata, sourcex, sraster, id,
                                              scolors, textures, tcolors,
                                              x, y, width, height,
                                              phase_x, phase_y, lop);
        }
    }

    /* Adjust coordinates to be in bounds. */
    if (const_source == gx_no_color_index) {
        fit_copy(dev, sdata, sourcex, sraster, id,
                 x, y, width, height);
    } else {
        fit_fill(dev, x, y, width, height);
    }

    /* Set up transfer parameters. */
    line_count = height;
    base = scan_line_base(mdev, y);
    drow = base + x * bpp;

    /*
     * There are 18 cases depending on whether each of the source and
     * texture is constant, 1-bit, or multi-bit, and on whether the
     * depth is 8 or 24 bits.  We divide first according to constant
     * vs. non-constant, and then according to 1- vs. multi-bit, and
     * finally according to pixel depth.  This minimizes source code,
     * but not necessarily time, since we do some of the divisions
     * within 1 or 2 levels of loop.
     */

#ifdef USE_RUN_ROP
#define dbit(base, i) ((base)[(i) >> 3] & (0x80 >> ((i) & 7)))
/* 8-bit */
#define cbit8(base, i, colors)\
  (dbit(base, i) ? (byte)colors[1] : (byte)colors[0])
#define rop_body_8(s_pixel, t_pixel)\
  if ( (s_pixel) == strans ||   /* So = 0, s_tr = 1 */\
       (t_pixel) == ttrans      /* Po = 0, p_tr = 1 */\
     )\
    continue;\
  *dptr = (*rop_proc_table[rop])(*dptr, s_pixel, t_pixel)
/* 24-bit */
#define get24(ptr)\
  (((gx_color_index)(ptr)[0] << 16) | ((gx_color_index)(ptr)[1] << 8) | (ptr)[2])
#define put24(ptr, pixel)\
  (ptr)[0] = (byte)((pixel) >> 16),\
  (ptr)[1] = (byte)((uint)(pixel) >> 8),\
  (ptr)[2] = (byte)(pixel)
#define cbit24(base, i, colors)\
  (dbit(base, i) ? colors[1] : colors[0])
#define rop_body_24(s_pixel, t_pixel)\
  if ( (s_pixel) == strans ||   /* So = 0, s_tr = 1 */\
       (t_pixel) == ttrans      /* Po = 0, p_tr = 1 */\
     )\
    continue;\
  { gx_color_index d_pixel = get24(dptr);\
    d_pixel = (*rop_proc_table[rop])(d_pixel, s_pixel, t_pixel);\
    put24(dptr, d_pixel);\
  }
    if (const_texture != gx_no_color_index) {
/**** Constant texture ****/
        if (const_source != gx_no_color_index) {
/**** Constant source & texture ****/
            rop_get_run_op(&ropper, lop, depth, rop_s_constant | rop_t_constant);
            rop_set_s_constant(&ropper, const_source);
            rop_set_t_constant(&ropper, const_texture);
            for (; line_count-- > 0; drow += draster) {
#ifdef COMPARE_AND_CONTRAST
                byte *dptr = drow;
                int left = width;

                bytelen = left*bpp; start = dptr;
                memcpy(testbuffer, dptr, bytelen);
                rop_run(&ropper, testbuffer, left);

                if (bpp == 1)
/**** 8-bit destination ****/
                    for (; left > 0; ++dptr, --left) {
                        vd_pixel(int2fixed((dptr - base) % draster),
                                 int2fixed((dptr - base) / draster + y), const_texture);
                        rop_body_8((byte)const_source, (byte)const_texture);
                    }
                else
/**** 24-bit destination ****/
                    for (; left > 0; dptr += 3, --left) {
                        vd_pixel(int2fixed((dptr - base) % draster / 3),
                                 int2fixed((dptr - base) / draster + y), const_texture);
                        rop_body_24(const_source, const_texture);
                    }
                if (memcmp(testbuffer, start, bytelen) != 0) {
                    eprintf("Failed!\n");
                }
#else
                rop_run(&ropper, drow, width);
#endif
            }
            rop_release_run_op(&ropper);
        } else {
/**** Data source, const texture ****/
            if (scolors) {
                const byte *srow = sdata;

                rop_get_run_op(&ropper, lop, depth, rop_t_constant | rop_s_1bit);
                rop_set_t_constant(&ropper, const_texture);
                rop_set_s_colors(&ropper, scolors);

                for (; line_count-- > 0; drow += draster, srow += sraster) {
#ifdef COMPARE_AND_CONTRAST
                    byte *dptr = drow;
                    int left = width;
/**** 1-bit source ****/
                    int sx = sourcex;

                    rop_set_s_bitmap_subbyte(&ropper, srow, sourcex);
                    bytelen = left*bpp; start = dptr;
                    memcpy(testbuffer, dptr, bytelen);
                    rop_run(&ropper, testbuffer, width);
                    if (bpp == 1)
/**** 8-bit destination ****/
                        for (; left > 0; ++dptr, ++sx, --left) {
                            byte s_pixel = cbit8(srow, sx, scolors);

                            vd_pixel(int2fixed((dptr - base) % draster),
                                 int2fixed((dptr - base) / draster + y), const_texture);
                            rop_body_8(s_pixel, (byte)const_texture);
                        }
                    else
/**** 24-bit destination ****/
                        for (; left > 0; dptr += 3, ++sx, --left) {
                            bits32 s_pixel = cbit24(srow, sx, scolors);

                            vd_pixel(int2fixed((dptr - base) % draster / 3),
                                 int2fixed((dptr - base) / draster + y), const_texture);
                            rop_body_24(s_pixel, const_texture);
                        }
                    if (memcmp(testbuffer, start, bytelen) != 0) {
                        eprintf("Failed!\n");
                    }
#else
/**** 1-bit source ****/
/**** 8-bit destination ****/
/**** 24-bit destination ****/
                    rop_set_s_bitmap_subbyte(&ropper, srow, sourcex);
                    rop_run(&ropper, drow, width);
#endif
                }
                rop_release_run_op(&ropper);
            } else {
                const byte *srow = sdata;
                rop_get_run_op(&ropper, lop, depth, rop_t_constant);
                rop_set_t_constant(&ropper, const_texture);
                for (; line_count-- > 0; drow += draster, srow += sraster) {
#ifdef COMPARE_AND_CONTRAST
                    byte *dptr = drow;
                    int left = width;

                    bytelen = left*bpp; start = dptr;
                    memcpy(testbuffer, dptr, bytelen);

                    rop_set_s_bitmap(&ropper, srow + sourcex * bpp);
                    rop_run(&ropper, testbuffer, left);
/**** 8-bit source & dest ****/
                    if (bpp == 1) {
                        const byte *sptr = srow + sourcex;

                        for (; left > 0; ++dptr, ++sptr, --left) {
                            byte s_pixel = *sptr;

                            vd_pixel(int2fixed((dptr - base) % draster),
                                     int2fixed((dptr - base) / draster + y), const_texture);
                            rop_body_8(s_pixel, (byte)const_texture);
                        }
                    } else {
/**** 24-bit source & dest ****/
                        const byte *sptr = srow + sourcex * 3;

                        bytelen = left*bpp; start = dptr;
                        memcpy(testbuffer, dptr, bytelen);

                        for (; left > 0; dptr += 3, sptr += 3, --left) {
                            bits32 s_pixel = get24(sptr);

                            vd_pixel(int2fixed((dptr - base) % draster / 3),
                                     int2fixed((dptr - base) / draster + y), const_texture);
                            rop_body_24(s_pixel, const_texture);
                        }
                    }
                    if (memcmp(testbuffer, start, bytelen) != 0) {
                        eprintf("Failed!\n");
                    }
#else
/**** 8-bit source & dest ****/
/**** 24-bit source & dest ****/
                    rop_set_s_bitmap(&ropper, srow + sourcex * bpp);
                    rop_run(&ropper, drow, width);
#endif
                }
                rop_release_run_op(&ropper);
            }
        }
    } else if (const_source != gx_no_color_index) {
/**** Const source, data texture ****/
        if (tcolors) {
            uint traster = textures->raster;
            int ty = y + phase_y;

            rop_get_run_op(&ropper, lop, depth, rop_s_constant | rop_t_1bit);
            rop_set_s_constant(&ropper, const_source);
            for (; line_count-- > 0; drow += draster, ++ty) {   /* Loop over copies of the tile. */
                int dx = x, w = width, nw;
                byte *dptr = drow;
                const byte *trow =
                textures->data + (ty % textures->size.y) * traster;
                int xoff = x_offset(phase_x, ty, textures);

                for (; w > 0; dx += nw, w -= nw) {
                    int tx = (dx + xoff) % textures->rep_width;
                    int left = nw = min(w, textures->size.x - tx);
                    const byte *tptr = trow;

                    rop_set_t_bitmap_subbyte(&ropper, trow, tx);
#ifdef COMPARE_AND_CONTRAST
                    bytelen = left*bpp; start = dptr;
                    memcpy(testbuffer, dptr, bytelen);
                    rop_run(&ropper, testbuffer, left);
/**** 1-bit texture ****/
                    if (bpp == 1)
/**** 8-bit dest ****/
                        for (; left > 0; ++dptr, ++tx, --left) {
                            byte t_pixel = cbit8(tptr, tx, tcolors);

                            vd_pixel(int2fixed((dptr - base) % draster),
                                 int2fixed((dptr - base) / draster + y), t_pixel);
                            rop_body_8((byte)const_source, t_pixel);
                        }
                    else
/**** 24-bit dest ****/
                        for (; left > 0; dptr += 3, ++tx, --left) {
                            bits32 t_pixel = cbit24(tptr, tx, tcolors);

                            vd_pixel(int2fixed((dptr - base) % draster / 3),
                                 int2fixed((dptr - base) / draster + y), t_pixel);
                            rop_body_24(const_source, t_pixel);
                        }
                    if (memcmp(testbuffer, start, bytelen) != 0) {
                        eprintf("Failed!\n");
                    }
#else
                    rop_run(&ropper, dptr, left);
                    dptr += left;
#endif
                }
            }
        } else {
            uint traster = textures->raster;
            int ty = y + phase_y;

            rop_get_run_op(&ropper, lop, depth, rop_s_constant);
            rop_set_s_constant(&ropper, const_source);

            for (; line_count-- > 0; drow += draster, ++ty) {   /* Loop over copies of the tile. */
                int dx = x, w = width, nw;
                byte *dptr = drow;
                const byte *trow =
                textures->data + (ty % textures->size.y) * traster;
                int xoff = x_offset(phase_x, ty, textures);

                for (; w > 0; dx += nw, w -= nw) {
                    int tx = (dx + xoff) % textures->rep_width;
                    int left = nw = min(w, textures->size.x - tx);
                    const byte *tptr = trow + tx*bpp;
                    rop_set_t_bitmap(&ropper, tptr);
#ifdef COMPARE_AND_CONTRAST
                    bytelen = left*bpp; start = dptr;
                    memcpy(testbuffer, dptr, bytelen);
                    rop_run(&ropper, testbuffer, left);
/**** 8-bit T & D ****/
                    if (bpp == 1) {
                        for (; left > 0; ++dptr, ++tptr, --left) {
                            byte t_pixel = *tptr;

                            vd_pixel(int2fixed((dptr - base) % draster),
                                    int2fixed((dptr - base) / draster + y), t_pixel);
                            rop_body_8((byte)const_source, t_pixel);
                        }
                    } else {
/**** 24-bit T & D ****/
                        for (; left > 0; dptr += 3, tptr += 3, --left) {
                            bits32 t_pixel = get24(tptr);

                            vd_pixel(int2fixed((dptr - base) % draster / 3),
                                     int2fixed((dptr - base) / draster + y), t_pixel);
                            rop_body_24(const_source, t_pixel);
                        }
                    }
                    if (memcmp(testbuffer, start, bytelen) != 0) {
                        eprintf("Failed!\n");
                    }
#else
/**** 8-bit T & D ****/
/**** 24-bit T & D ****/
                    rop_run(&ropper, dptr, left);
                    dptr += left * bpp;
#endif
                }
            }
            rop_release_run_op(&ropper);
        }
    } else {
/**** Data source & texture ****/
        if (scolors != NULL | tcolors != NULL) {
            uint traster = textures->raster;
            int ty = y + phase_y;
            const byte *srow = sdata;

            rop_get_run_op(&ropper, lop, depth,
                           ((scolors == NULL ? 0 : rop_s_1bit) |
                            (tcolors == NULL ? 0 : rop_t_1bit)));

            /* Loop over scan lines. */
            for (; line_count-- > 0; drow += draster, srow += sraster, ++ty) {  /* Loop over copies of the tile. */
                int sx = sourcex;
                int dx = x;
                int w = width;
                int nw;
                byte *dptr = drow;
                const byte *trow =
                textures->data + (ty % textures->size.y) * traster;
                int xoff = x_offset(phase_x, ty, textures);

                for (; w > 0; dx += nw, w -= nw) {      /* Loop over individual pixels. */
                    int tx = (dx + xoff) % textures->rep_width;
                    int left = nw = min(w, textures->size.x - tx);
                    const byte *sptr = srow + sx*bpp;
                    const byte *tptr = trow + tx*bpp;

                    /*
                     * For maximum speed, we should split this loop
                     * into 7 cases depending on source & texture
                     * depth: (1,1), (1,8), (1,24), (8,1), (8,8),
                     * (24,1), (24,24).  But since we expect these
                     * cases to be relatively uncommon, we just
                     * divide on the destination depth.
                     */
                    if (scolors)
                        rop_set_s_bitmap_subbyte(&ropper, srow, sx);
                    else
                        rop_set_s_bitmap(&ropper, sptr);
                    if (tcolors)
                        rop_set_t_bitmap_subbyte(&ropper, trow, tx);
                    else
                        rop_set_t_bitmap(&ropper, tptr);

#ifdef COMPARE_AND_CONTRAST
                    bytelen = left*bpp; start = dptr;
                    memcpy(testbuffer, dptr, bytelen);
                    rop_run(&ropper, testbuffer, left);
                    if (bpp == 1) {
/**** 8-bit destination ****/
                        for (; left > 0; ++dptr, ++sptr, ++tptr, ++sx, ++tx, --left) {
                            byte s_pixel =
                                (scolors ? cbit8(srow, sx, scolors) : *sptr);
                            byte t_pixel =
                                (tcolors ? cbit8(trow, tx, tcolors) : *tptr);

                            vd_pixel(int2fixed((dptr - base) % draster),
                                     int2fixed((dptr - base) / draster + y), t_pixel);
                            rop_body_8(s_pixel, t_pixel);
                        }
                    } else {
/**** 24-bit destination ****/
                        for (; left > 0; dptr += 3, sptr += 3, tptr += 3, ++sx, ++tx, --left) {
                            bits32 s_pixel =
                                (scolors ? cbit24(srow, sx, scolors) :
                                 get24(sptr));
                            bits32 t_pixel =
                                (tcolors ? cbit24(tptr, tx, tcolors) :
                                 get24(tptr));

                            vd_pixel(int2fixed((dptr - base) % draster / 3),
                                     int2fixed((dptr - base) / draster + y), t_pixel);
                            rop_body_24(s_pixel, t_pixel);
                        }
                    }
                    if (memcmp(testbuffer, start, bytelen) != 0) {
                        eprintf("Failed!\n");
                    }
#else
                    rop_run(&ropper, dptr, left);
#endif
                }
            }
        } else {
            uint traster = textures->raster;
            int ty = y + phase_y;
            const byte *srow = sdata;

            /* Loop over scan lines. */
            rop_get_run_op(&ropper, rop, depth, 0);
            for (; line_count-- > 0; drow += draster, srow += sraster, ++ty) {  /* Loop over copies of the tile. */
                int sx = sourcex;
                int dx = x;
                int w = width;
                int nw;
                byte *dptr = drow;
                const byte *trow =
                textures->data + (ty % textures->size.y) * traster;
                int xoff = x_offset(phase_x, ty, textures);

                for (; w > 0; dx += nw, w -= nw) {      /* Loop over individual pixels. */
                    int tx = (dx + xoff) % textures->rep_width;
                    int left = nw = min(w, textures->size.x - tx);
                    const byte *tptr = trow + tx * bpp;
                    const byte *sptr = srow + sx * bpp;

                    rop_set_s_bitmap(&ropper, sptr);
                    rop_set_t_bitmap(&ropper, tptr);
#ifdef COMPARE_AND_CONTRAST
                    if (bpp == 1) {
                        rop_run(&ropper, testbuffer, left);
/**** 8-bit destination ****/

                        for (; left > 0; ++dptr, ++sptr, ++tptr, ++sx, ++tx, --left) {
                            rop_body_8(*sptr, *tptr);
                        }
                    } else {
/**** 24-bit destination ****/
                        for (; left > 0; dptr += 3, sptr += 3, tptr += 3, ++sx, ++tx, --left) {
                            bits32 s_pixel = get24(sptr);
                            bits32 t_pixel = get24(tptr);

                            rop_body_24(s_pixel, t_pixel);
                        }
                    }
                    if (memcmp(testbuffer, start, bytelen) != 0) {
                        eprintf("Failed!\n");
                    }
#else
/**** 8-bit destination ****/
/**** 24-bit destination ****/
                    rop_run(&ropper, dptr, left);
#endif
                }
            }
            rop_release_run_op(&ropper);
        }
    }
#undef rop_body_8
#undef rop_body_24
#undef dbit
#undef cbit8
#undef cbit24
#else

#define dbit(base, i) ((base)[(i) >> 3] & (0x80 >> ((i) & 7)))
/* 8-bit */
#define cbit8(base, i, colors)\
  (dbit(base, i) ? (byte)colors[1] : (byte)colors[0])
#define rop_body_8(s_pixel, t_pixel)\
  if ( (s_pixel) == strans ||   /* So = 0, s_tr = 1 */\
       (t_pixel) == ttrans      /* Po = 0, p_tr = 1 */\
     )\
    continue;\
  *dptr = (*rop_proc_table[rop])(*dptr, s_pixel, t_pixel)
/* 24-bit */
#define get24(ptr)\
  (((gx_color_index)(ptr)[0] << 16) | ((gx_color_index)(ptr)[1] << 8) | (ptr)[2])
#define put24(ptr, pixel)\
  (ptr)[0] = (byte)((pixel) >> 16),\
  (ptr)[1] = (byte)((uint)(pixel) >> 8),\
  (ptr)[2] = (byte)(pixel)
#define cbit24(base, i, colors)\
  (dbit(base, i) ? colors[1] : colors[0])
#define rop_body_24(s_pixel, t_pixel)\
  if ( (s_pixel) == strans ||   /* So = 0, s_tr = 1 */\
       (t_pixel) == ttrans      /* Po = 0, p_tr = 1 */\
     )\
    continue;\
  { gx_color_index d_pixel = get24(dptr);\
    d_pixel = (*rop_proc_table[rop])(d_pixel, s_pixel, t_pixel);\
    put24(dptr, d_pixel);\
  }

    if (const_texture != gx_no_color_index) {
/**** Constant texture ****/
        if (const_source != gx_no_color_index) {
/**** Constant source & texture ****/
            for (; line_count-- > 0; drow += draster) {
                byte *dptr = drow;
                int left = width;

                if (bpp == 1)
/**** 8-bit destination ****/
                    for (; left > 0; ++dptr, --left) {
                        vd_pixel(int2fixed((dptr - base) % draster),
                                 int2fixed((dptr - base) / draster + y), const_texture);
                        rop_body_8((byte)const_source, (byte)const_texture);
                    }
                else
/**** 24-bit destination ****/
                    for (; left > 0; dptr += 3, --left) {
                        vd_pixel(int2fixed((dptr - base) % draster / 3),
                                 int2fixed((dptr - base) / draster + y), const_texture);
                        rop_body_24(const_source, const_texture);
                    }
            }
        } else {
/**** Data source, const texture ****/
            const byte *srow = sdata;

            for (; line_count-- > 0; drow += draster, srow += sraster) {
                byte *dptr = drow;
                int left = width;

                if (scolors) {
/**** 1-bit source ****/
                    int sx = sourcex;

                    if (bpp == 1)
/**** 8-bit destination ****/
                        for (; left > 0; ++dptr, ++sx, --left) {
                            byte s_pixel = cbit8(srow, sx, scolors);

                            vd_pixel(int2fixed((dptr - base) % draster),
                                 int2fixed((dptr - base) / draster + y), const_texture);
                            rop_body_8(s_pixel, (byte)const_texture);
                        }
                    else
/**** 24-bit destination ****/
                        for (; left > 0; dptr += 3, ++sx, --left) {
                            bits32 s_pixel = cbit24(srow, sx, scolors);

                            vd_pixel(int2fixed((dptr - base) % draster / 3),
                                 int2fixed((dptr - base) / draster + y), const_texture);
                            rop_body_24(s_pixel, const_texture);
                        }
                } else if (bpp == 1) {
/**** 8-bit source & dest ****/
                    const byte *sptr = srow + sourcex;

                    for (; left > 0; ++dptr, ++sptr, --left) {
                        byte s_pixel = *sptr;

                        vd_pixel(int2fixed((dptr - base) % draster),
                                 int2fixed((dptr - base) / draster + y), const_texture);
                        rop_body_8(s_pixel, (byte)const_texture);
                    }
                } else {
/**** 24-bit source & dest ****/
                    const byte *sptr = srow + sourcex * 3;

                    for (; left > 0; dptr += 3, sptr += 3, --left) {
                        bits32 s_pixel = get24(sptr);

                        vd_pixel(int2fixed((dptr - base) % draster / 3),
                                 int2fixed((dptr - base) / draster + y), const_texture);
                        rop_body_24(s_pixel, const_texture);
                    }
                }
            }
        }
    } else if (const_source != gx_no_color_index) {
/**** Const source, data texture ****/
        uint traster = textures->raster;
        int ty = y + phase_y;

        for (; line_count-- > 0; drow += draster, ++ty) {       /* Loop over copies of the tile. */
            int dx = x, w = width, nw;
            byte *dptr = drow;
            const byte *trow =
            textures->data + (ty % textures->size.y) * traster;
            int xoff = x_offset(phase_x, ty, textures);

            for (; w > 0; dx += nw, w -= nw) {
                int tx = (dx + xoff) % textures->rep_width;
                int left = nw = min(w, textures->size.x - tx);
                const byte *tptr = trow;

                if (tcolors) {
/**** 1-bit texture ****/
                    if (bpp == 1)
/**** 8-bit dest ****/
                        for (; left > 0; ++dptr, ++tx, --left) {
                            byte t_pixel = cbit8(tptr, tx, tcolors);

                            vd_pixel(int2fixed((dptr - base) % draster),
                                 int2fixed((dptr - base) / draster + y), t_pixel);
                            rop_body_8((byte)const_source, t_pixel);
                        }
                    else
/**** 24-bit dest ****/
                        for (; left > 0; dptr += 3, ++tx, --left) {
                            bits32 t_pixel = cbit24(tptr, tx, tcolors);

                            vd_pixel(int2fixed((dptr - base) % draster / 3),
                                 int2fixed((dptr - base) / draster + y), t_pixel);
                            rop_body_24(const_source, t_pixel);
                        }
                } else if (bpp == 1) {
/**** 8-bit T & D ****/
                    tptr += tx;
                    for (; left > 0; ++dptr, ++tptr, --left) {
                        byte t_pixel = *tptr;

                        vd_pixel(int2fixed((dptr - base) % draster),
                                 int2fixed((dptr - base) / draster + y), t_pixel);
                        rop_body_8((byte)const_source, t_pixel);
                    }
                } else {
/**** 24-bit T & D ****/
                    tptr += tx * 3;
                    for (; left > 0; dptr += 3, tptr += 3, --left) {
                        bits32 t_pixel = get24(tptr);

                        vd_pixel(int2fixed((dptr - base) % draster / 3),
                                 int2fixed((dptr - base) / draster + y), t_pixel);
                        rop_body_24(const_source, t_pixel);
                    }
                }
            }
        }
    } else {
/**** Data source & texture ****/
        uint traster = textures->raster;
        int ty = y + phase_y;
        const byte *srow = sdata;

        /* Loop over scan lines. */
        for (; line_count-- > 0; drow += draster, srow += sraster, ++ty) {      /* Loop over copies of the tile. */
            int sx = sourcex;
            int dx = x;
            int w = width;
            int nw;
            byte *dptr = drow;
            const byte *trow =
            textures->data + (ty % textures->size.y) * traster;
            int xoff = x_offset(phase_x, ty, textures);

            for (; w > 0; dx += nw, w -= nw) {  /* Loop over individual pixels. */
                int tx = (dx + xoff) % textures->rep_width;
                int left = nw = min(w, textures->size.x - tx);
                const byte *tptr = trow;

                /*
                 * For maximum speed, we should split this loop
                 * into 7 cases depending on source & texture
                 * depth: (1,1), (1,8), (1,24), (8,1), (8,8),
                 * (24,1), (24,24).  But since we expect these
                 * cases to be relatively uncommon, we just
                 * divide on the destination depth.
                 */
                if (bpp == 1) {
/**** 8-bit destination ****/
                    const byte *sptr = srow + sx;

                    tptr += tx;
                    for (; left > 0; ++dptr, ++sptr, ++tptr, ++sx, ++tx, --left) {
                        byte s_pixel =
                            (scolors ? cbit8(srow, sx, scolors) : *sptr);
                        byte t_pixel =
                            (tcolors ? cbit8(tptr, tx, tcolors) : *tptr);

                        vd_pixel(int2fixed((dptr - base) % draster),
                                 int2fixed((dptr - base) / draster + y), t_pixel);
                        rop_body_8(s_pixel, t_pixel);
                    }
                } else {
/**** 24-bit destination ****/
                    const byte *sptr = srow + sx * 3;

                    tptr += tx * 3;
                    for (; left > 0; dptr += 3, sptr += 3, tptr += 3, ++sx, ++tx, --left) {
                        bits32 s_pixel =
                            (scolors ? cbit24(srow, sx, scolors) :
                             get24(sptr));
                        bits32 t_pixel =
                            (tcolors ? cbit24(tptr, tx, tcolors) :
                             get24(tptr));

                        vd_pixel(int2fixed((dptr - base) % draster / 3),
                                 int2fixed((dptr - base) / draster + y), t_pixel);
                        rop_body_24(s_pixel, t_pixel);
                    }
                }
            }
        }
    }
#undef rop_body_8
#undef rop_body_24
#undef dbit
#undef cbit8
#undef cbit24
#endif
    return 0;
}
Exemplo n.º 22
0
/*
 * Continue interpreting a Type 2 charstring.  If str != 0, it is taken as
 * the byte string to interpret.  Return 0 on successful completion, <0 on
 * error, or >0 when client intervention is required (or allowed).  The int*
 * argument is only for compatibility with the Type 1 charstring interpreter.
 */
int
gs_type2_interpret(gs_type1_state * pcis, const gs_glyph_data_t *pgd,
                   int *ignore_pindex)
{
    gs_font_type1 *pfont = pcis->pfont;
    gs_type1_data *pdata = &pfont->data;
    t1_hinter *h = &pcis->h;
    bool encrypted = pdata->lenIV >= 0;
    fixed cstack[ostack_size];
    cs_ptr csp;
#define clear CLEAR_CSTACK(cstack, csp)
    ip_state_t *ipsp = &pcis->ipstack[pcis->ips_count - 1];
    register const byte *cip;
    register crypt_state state;
    register int c;
    cs_ptr ap;
    bool vertical;
    int code = 0;

/****** FAKE THE REGISTRY ******/
    struct {
        float *values;
        uint size;
    } Registry[1];

    Registry[0].values = pcis->pfont->data.WeightVector.values;

    switch (pcis->init_done) {
        case -1:
            t1_hinter__init(h, pcis->path);
            break;
        case 0:
            gs_type1_finish_init(pcis);	/* sets origin */
            code = t1_hinter__set_mapping(h, &pcis->pis->ctm,
                            &pfont->FontMatrix, &pfont->base->FontMatrix,
                            pcis->scale.x.log2_unit, pcis->scale.x.log2_unit,
                            pcis->scale.x.log2_unit - pcis->log2_subpixels.x,
                            pcis->scale.y.log2_unit - pcis->log2_subpixels.y,
                            pcis->origin.x, pcis->origin.y,
                            gs_currentaligntopixels(pfont->dir));
            if (code < 0)
                return code;
            code = t1_hinter__set_font_data(h, 2, pdata, pcis->no_grid_fitting,
                            pcis->pfont->is_resource);
            if (code < 0)
                return code;
            break;
        default /*case 1 */ :
            break;
    }
    INIT_CSTACK(cstack, csp, pcis);

    if (pgd == 0)
        goto cont;
    ipsp->cs_data = *pgd;
    cip = pgd->bits.data;
    if (cip == 0)
        return (gs_note_error(gs_error_invalidfont));
  call:state = crypt_charstring_seed;
    if (encrypted) {
        int skip = pdata->lenIV;

        /* Skip initial random bytes */
        for (; skip > 0; ++cip, --skip)
            decrypt_skip_next(*cip, state);
    }
    goto top;
  cont:if (ipsp < pcis->ipstack || ipsp->ip == 0)
        return (gs_note_error(gs_error_invalidfont));
    cip = ipsp->ip;
    state = ipsp->dstate;
  top:for (;;) {
        uint c0 = *cip++;

        charstring_next(c0, state, c, encrypted);
        if (c >= c_num1) {
            /* This is a number, decode it and push it on the stack. */

            if (c < c_pos2_0) {	/* 1-byte number */
                decode_push_num1(csp, cstack, c);
            } else if (c < cx_num4) {	/* 2-byte number */
                decode_push_num2(csp, cstack, c, cip, state, encrypted);
            } else if (c == cx_num4) {	/* 4-byte number */
                long lw;

                decode_num4(lw, cip, state, encrypted);
                /* 32-bit numbers are 16:16. */
                CS_CHECK_PUSH(csp, cstack);
                *++csp = arith_rshift(lw, 16 - _fixed_shift);
            } else		/* not possible */
                return_error(gs_error_invalidfont);
          pushed:if_debug3('1', "[1]%d: (%d) %f\n",
                      (int)(csp - cstack), c, fixed2float(*csp));
            continue;
        }
#ifdef DEBUG
        if (gs_debug['1']) {
            static const char *const c2names[] =
            {char2_command_names};

            if (c2names[c] == 0)
                dlprintf2("[1]0x%lx: %02x??\n", (ulong) (cip - 1), c);
            else
                dlprintf3("[1]0x%lx: %02x %s\n", (ulong) (cip - 1), c,
                          c2names[c]);
        }
#endif
        switch ((char_command) c) {
#define cnext clear; goto top

                /* Commands with identical functions in Type 1 and Type 2, */
                /* except for 'escape'. */

            case c_undef0:
            case c_undef2:
            case c_undef17:
                return_error(gs_error_invalidfont);
            case c_callsubr:
                c = fixed2int_var(*csp) + pdata->subroutineNumberBias;
                code = pdata->procs.subr_data
                    (pfont, c, false, &ipsp[1].cs_data);
              subr:if (code < 0) {
                    /* Calling a Subr with an out-of-range index is clearly a error:
                     * the Adobe documentation says the results of doing this are
                     * undefined. However, we have seen a PDF file produced by Adobe
                     * PDF Library 4.16 that included a Type 2 font that called an
                     * out-of-range Subr, and Acrobat Reader did not signal an error.
                     * Therefore, we ignore such calls.
                     */
                    cip++;
                    goto top;
                }
                --csp;
                ipsp->ip = cip, ipsp->dstate = state;
                ++ipsp;
                cip = ipsp->cs_data.bits.data;
                goto call;
            case c_return:
                gs_glyph_data_free(&ipsp->cs_data, "gs_type2_interpret");
                --ipsp;
                goto cont;
            case c_undoc15:
                /* See gstype1.h for information on this opcode. */
                cnext;

                /* Commands with similar but not identical functions */
                /* in Type 1 and Type 2 charstrings. */

            case cx_hstem:
                goto hstem;
            case cx_vstem:
                goto vstem;
            case cx_vmoveto:
                check_first_operator(csp > cstack);
                code = t1_hinter__rmoveto(h, 0, *csp);
              move:
              cc:
                if (code < 0)
                    return code;
                goto pp;
            case cx_rlineto:
                for (ap = cstack; ap + 1 <= csp; ap += 2) {
                    code = t1_hinter__rlineto(h, ap[0], ap[1]);
                    if (code < 0)
                        return code;
                }
              pp:
                cnext;
            case cx_hlineto:
                vertical = false;
                goto hvl;
            case cx_vlineto:
                vertical = true;
              hvl:for (ap = cstack; ap <= csp; vertical = !vertical, ++ap) {
                    if (vertical) {
                        code = t1_hinter__rlineto(h, 0, ap[0]);
                    } else {
                        code = t1_hinter__rlineto(h, ap[0], 0);
                    }
                    if (code < 0)
                        return code;
                }
                goto pp;
            case cx_rrcurveto:
                for (ap = cstack; ap + 5 <= csp; ap += 6) {
                    code = t1_hinter__rcurveto(h, ap[0], ap[1], ap[2],
                                            ap[3], ap[4], ap[5]);
                    if (code < 0)
                        return code;
                }
                goto pp;
            case cx_endchar:
                /*
                 * It is a feature of Type 2 CharStrings that if endchar is
                 * invoked with 4 or 5 operands, it is equivalent to the
                 * Type 1 seac operator. In this case, the asb operand of
                 * seac is missing: we assume it is the same as the
                 * l.s.b. of the accented character.  This feature was
                 * undocumented until the 16 March 2000 version of the Type
                 * 2 Charstring Format specification, but, thankfully, is
                 * described in that revision.
                 */
                if (csp >= cstack + 3) {
                    check_first_operator(csp > cstack + 3);
                    code = gs_type1_seac(pcis, cstack, 0, ipsp);
                    if (code < 0)
                        return code;
                    clear;
                    cip = ipsp->cs_data.bits.data;
                    goto call;
                }
                /*
                 * This might be the only operator in the charstring.
                 * In this case, there might be a width on the stack.
                 */
                check_first_operator(csp >= cstack);
                if (pcis->seac_accent < 0) {
                    code = t1_hinter__endglyph(h);
                    if (code < 0)
                        return code;
                    code = gx_setcurrentpoint_from_path(pcis->pis, pcis->path);
                    if (code < 0)
                        return code;
                } else {
                    t1_hinter__setcurrentpoint(h, pcis->save_adxy.x + pcis->origin_offset.x,
                                                  pcis->save_adxy.y + pcis->origin_offset.y);
                    code = t1_hinter__end_subglyph(h);
                    if (code < 0)
                        return code;
                }
                code = gs_type1_endchar(pcis);
                if (code == 1) {
                    /*
                     * Reset the total hint count so that hintmask will
                     * parse its following data correctly.
                     * (gs_type1_endchar already reset the actual hint
                     * tables.)
                     */
                    pcis->num_hints = 0;
                    /* do accent of seac */
                    ipsp = &pcis->ipstack[pcis->ips_count - 1];
                    cip = ipsp->cs_data.bits.data;
                    goto call;
                }
                return code;
            case cx_rmoveto:
                /* See vmoveto above re closing the subpath. */
                check_first_operator(!((csp - cstack) & 1));
                if (csp > cstack + 1) {
                  /* Some Type 2 charstrings omit the vstemhm operator before rmoveto,
                     even though this is only allowed before hintmask and cntrmask.
                     Thanks to Felix Pahl.
                   */
                  type2_vstem(pcis, csp - 2, cstack);
                  cstack [0] = csp [-1];
                  cstack [1] = csp [ 0];
                  csp = cstack + 1;
                }
                code = t1_hinter__rmoveto(h, csp[-1], *csp);
                goto move;
            case cx_hmoveto:
                /* See vmoveto above re closing the subpath. */
                check_first_operator(csp > cstack);
                code = t1_hinter__rmoveto(h, *csp, 0);
                goto move;
            case cx_vhcurveto:
                vertical = true;
                goto hvc;
            case cx_hvcurveto:
                vertical = false;
              hvc:for (ap = cstack; ap + 3 <= csp; vertical = !vertical, ap += 4) {
                    gs_fixed_point pt[2] = {{0, 0}, {0, 0}};
                    if (vertical) {
                        pt[0].y = ap[0];
                        pt[1].x = ap[3];
                        if (ap + 4 == csp)
                            pt[1].y = ap[4];
                    } else {
                        pt[0].x = ap[0];
                        if (ap + 4 == csp)
                            pt[1].x = ap[4];
                        pt[1].y = ap[3];
                    }
                    code = t1_hinter__rcurveto(h, pt[0].x, pt[0].y, ap[1], ap[2], pt[1].x, pt[1].y);
                    if (code < 0)
                        return code;
                }
                goto pp;

                        /***********************
                         * New Type 2 commands *
                         ***********************/

            case c2_blend:
                {
                    int n = fixed2int_var(*csp);
                    int num_values = csp - cstack;
                    gs_font_type1 *pfont = pcis->pfont;
                    int k = pfont->data.WeightVector.count;
                    int i, j;
                    cs_ptr base, deltas;

                    base = csp - 1 - num_values;
                    deltas = base + n - 1;
                    for (j = 0; j < n; j++, base++, deltas += k - 1)
                        for (i = 1; i < k; i++)
                            *base += (fixed)(deltas[i] *
                                pfont->data.WeightVector.values[i]);
                }
                cnext;
            case c2_hstemhm:
              hstem:check_first_operator(!((csp - cstack) & 1));
                {
                    fixed x = 0;

                    for (ap = cstack; ap + 1 <= csp; x += ap[1], ap += 2) {
                            code = t1_hinter__hstem(h, x += ap[0], ap[1]);
                            if (code < 0)
                                return code;
                    }
                }
                pcis->num_hints += (csp + 1 - cstack) >> 1;
                cnext;
            case c2_hintmask:
                /*
                 * A hintmask at the beginning of the CharString is
                 * equivalent to vstemhm + hintmask.  For simplicity, we use
                 * this interpretation everywhere.
                 */
            case c2_cntrmask:
                check_first_operator(!((csp - cstack) & 1));
                type2_vstem(pcis, csp, cstack);
                /*
                 * We should clear the stack here only if this is the
                 * initial mask operator that includes the implicit
                 * vstemhm, but currently this is too much trouble to
                 * detect.
                 */
                clear;
                {
                    byte mask[max_total_stem_hints / 8];
                    int i;

                    for (i = 0; i < pcis->num_hints; ++cip, i += 8) {
                        charstring_next(*cip, state, mask[i >> 3], encrypted);
                        if_debug1('1', " 0x%02x", mask[i >> 3]);
                    }
                    if_debug0('1', "\n");
                    ipsp->ip = cip;
                    ipsp->dstate = state;
                    if (c == c2_cntrmask) {
                        /****** NYI ******/
                    } else {	/* hintmask or equivalent */
                        if_debug0('1', "[1]hstem hints:\n");
                        if_debug0('1', "[1]vstem hints:\n");
                        code = t1_hinter__hint_mask(h, mask);
                        if (code < 0)
                            return code;
                    }
                }
                break;
            case c2_vstemhm:
              vstem:check_first_operator(!((csp - cstack) & 1));
                type2_vstem(pcis, csp, cstack);
                cnext;
            case c2_rcurveline:
                for (ap = cstack; ap + 5 <= csp; ap += 6) {
                    code = t1_hinter__rcurveto(h, ap[0], ap[1], ap[2], ap[3],
                                            ap[4], ap[5]);
                    if (code < 0)
                        return code;
                }
                code = t1_hinter__rlineto(h, ap[0], ap[1]);
                goto cc;
            case c2_rlinecurve:
                for (ap = cstack; ap + 7 <= csp; ap += 2) {
                    code = t1_hinter__rlineto(h, ap[0], ap[1]);
                    if (code < 0)
                        return code;
                }
                code = t1_hinter__rcurveto(h, ap[0], ap[1], ap[2], ap[3],
                                        ap[4], ap[5]);
                goto cc;
            case c2_vvcurveto:
                ap = cstack;
                {
                    int n = csp + 1 - cstack;
                    fixed dxa = (n & 1 ? *ap++ : 0);

                    for (; ap + 3 <= csp; ap += 4) {
                        code = t1_hinter__rcurveto(h, dxa, ap[0], ap[1], ap[2],
                                                fixed_0, ap[3]);
                        if (code < 0)
                            return code;
                        dxa = 0;
                    }
                }
                goto pp;
            case c2_hhcurveto:
                ap = cstack;
                {
                    int n = csp + 1 - cstack;
                    fixed dya = (n & 1 ? *ap++ : 0);

                    for (; ap + 3 <= csp; ap += 4) {
                        code = t1_hinter__rcurveto(h, ap[0], dya, ap[1], ap[2],
                                                ap[3], fixed_0);
                        if (code < 0)
                            return code;
                        dya = 0;
                    }
                }
                goto pp;
            case c2_shortint:
                {
                    int c1, c2;

                    charstring_next(*cip, state, c1, encrypted);
                    ++cip;
                    charstring_next(*cip, state, c2, encrypted);
                    ++cip;
                    CS_CHECK_PUSH(csp, cstack);
                    *++csp = int2fixed((((c1 ^ 0x80) - 0x80) << 8) + c2);
                }
                goto pushed;
            case c2_callgsubr:
                c = fixed2int_var(*csp) + pdata->gsubrNumberBias;
                code = pdata->procs.subr_data
                    (pfont, c, true, &ipsp[1].cs_data);
                goto subr;
            case cx_escape:
                charstring_next(*cip, state, c, encrypted);
                ++cip;
#ifdef DEBUG
                if (gs_debug['1'] && c < char2_extended_command_count) {
                    static const char *const ce2names[] =
                    {char2_extended_command_names};

                    if (ce2names[c] == 0)
                        dlprintf2("[1]0x%lx: %02x??\n", (ulong) (cip - 1), c);
                    else
                        dlprintf3("[1]0x%lx: %02x %s\n", (ulong) (cip - 1), c,
                                  ce2names[c]);
                }
#endif
                switch ((char2_extended_command) c) {
                    case ce2_and:
                        csp[-1] = ((csp[-1] != 0) & (*csp != 0) ? fixed_1 : 0);
                        --csp;
                        break;
                    case ce2_or:
                        csp[-1] = (csp[-1] | *csp ? fixed_1 : 0);
                        --csp;
                        break;
                    case ce2_not:
                        *csp = (*csp ? 0 : fixed_1);
                        break;
                    case ce2_store:
                        {
                            int i, n = fixed2int_var(*csp);
                            float *to = Registry[fixed2int_var(csp[-3])].values +
                            fixed2int_var(csp[-2]);
                            const fixed *from =
                            pcis->transient_array + fixed2int_var(csp[-1]);

                            for (i = 0; i < n; ++i)
                                to[i] = fixed2float(from[i]);
                        }
                        csp -= 4;
                        break;
                    case ce2_abs:
                        if (*csp < 0)
                            *csp = -*csp;
                        break;
                    case ce2_add:
                        csp[-1] += *csp;
                        --csp;
                        break;
                    case ce2_sub:
                        csp[-1] -= *csp;
                        --csp;
                        break;
                    case ce2_div:
                        csp[-1] = float2fixed((double)csp[-1] / *csp);
                        --csp;
                        break;
                    case ce2_load:
                        /* The specification says there is no j (starting index */
                        /* in registry array) argument.... */
                        {
                            int i, n = fixed2int_var(*csp);
                            const float *from = Registry[fixed2int_var(csp[-2])].values;
                            fixed *to =
                            pcis->transient_array + fixed2int_var(csp[-1]);

                            for (i = 0; i < n; ++i)
                                to[i] = float2fixed(from[i]);
                        }
                        csp -= 3;
                        break;
                    case ce2_neg:
                        *csp = -*csp;
                        break;
                    case ce2_eq:
                        csp[-1] = (csp[-1] == *csp ? fixed_1 : 0);
                        --csp;
                        break;
                    case ce2_drop:
                        --csp;
                        break;
                    case ce2_put:
                        pcis->transient_array[fixed2int_var(*csp)] = csp[-1];
                        csp -= 2;
                        break;
                    case ce2_get:
                        *csp = pcis->transient_array[fixed2int_var(*csp)];
                        break;
                    case ce2_ifelse:
                        if (csp[-1] > *csp)
                            csp[-3] = csp[-2];
                        csp -= 3;
                        break;
                    case ce2_random:
                        CS_CHECK_PUSH(csp, cstack);
                        ++csp;
                        /****** NYI ******/
                        break;
                    case ce2_mul:
                        {
                            double prod = fixed2float(csp[-1]) * *csp;

                            csp[-1] =
                                (prod > max_fixed ? max_fixed :
                                 prod < min_fixed ? min_fixed : (fixed)prod);
                        }
                        --csp;
                        break;
                    case ce2_sqrt:
                        if (*csp >= 0)
                            *csp = float2fixed(sqrt(fixed2float(*csp)));
                        break;
                    case ce2_dup:
                        CS_CHECK_PUSH(csp, cstack);
                        csp[1] = *csp;
                        ++csp;
                        break;
                    case ce2_exch:
                        {
                            fixed top = *csp;

                            *csp = csp[-1], csp[-1] = top;
                        }
                        break;
                    case ce2_index:
                        *csp =
                            (*csp < 0 ? csp[-1] : csp[-1 - fixed2int_var(csp[-1])]);
                        break;
                    case ce2_roll:
                        {
                            int distance = fixed2int_var(*csp);
                            int count = fixed2int_var(csp[-1]);
                            cs_ptr bot;

                            csp -= 2;
                            if (count < 0 || count > csp + 1 - cstack)
                                return_error(gs_error_invalidfont);
                            if (count == 0)
                                break;
                            if (distance < 0)
                                distance = count - (-distance % count);
                            bot = csp + 1 - count;
                            while (--distance >= 0) {
                                fixed top = *csp;

                                memmove(bot + 1, bot,
                                        (count - 1) * sizeof(fixed));
                                *bot = top;
                            }
                        }
                        break;
                    case ce2_hflex:
                        csp[6] = fixed_half;	/* fd/100 */
                        csp[4] = *csp, csp[5] = 0;	/* dx6, dy6 */
                        csp[2] = csp[-1], csp[3] = -csp[-4];	/* dx5, dy5 */
                        *csp = csp[-2], csp[1] = 0;	/* dx4, dy4 */
                        csp[-2] = csp[-3], csp[-1] = 0;		/* dx3, dy3 */
                        csp[-3] = csp[-4], csp[-4] = csp[-5];	/* dx2, dy2 */
                        csp[-5] = 0;	/* dy1 */
                        csp += 6;
                        goto flex;
                    case ce2_flex:
                        *csp /= 100;	/* fd/100 */
flex:			{
                            fixed x_join = csp[-12] + csp[-10] + csp[-8];
                            fixed y_join = csp[-11] + csp[-9] + csp[-7];
                            fixed x_end = x_join + csp[-6] + csp[-4] + csp[-2];
                            fixed y_end = y_join + csp[-5] + csp[-3] + csp[-1];
                            gs_point join, end;
                            double flex_depth;

                            if ((code =
                                 gs_distance_transform(fixed2float(x_join),
                                                       fixed2float(y_join),
                                                       &ctm_only(pcis->pis),
                                                       &join)) < 0 ||
                                (code =
                                 gs_distance_transform(fixed2float(x_end),
                                                       fixed2float(y_end),
                                                       &ctm_only(pcis->pis),
                                                       &end)) < 0
                                )
                                return code;
                            /*
                             * Use the X or Y distance depending on whether
                             * the curve is more horizontal or more
                             * vertical.
                             */
                            if (any_abs(end.y) > any_abs(end.x))
                                flex_depth = join.x;
                            else
                                flex_depth = join.y;
                            if (fabs(flex_depth) < fixed2float(*csp)) {
                                /* Do flex as line. */
                                code = t1_hinter__rlineto(h, x_end, y_end);
                            } else {
                                /*
                                 * Do flex as curve.  We can't jump to rrc,
                                 * because the flex operators don't clear
                                 * the stack (!).
                                 */
                                code = t1_hinter__rcurveto(h,
                                        csp[-12], csp[-11], csp[-10],
                                        csp[-9], csp[-8], csp[-7]);
                                if (code < 0)
                                    return code;
                                code = t1_hinter__rcurveto(h,
                                        csp[-6], csp[-5], csp[-4],
                                        csp[-3], csp[-2], csp[-1]);
                            }
                            if (code < 0)
                                return code;
                            csp -= 13;
                        }
                        cnext;
                    case ce2_hflex1:
                        csp[4] = fixed_half;	/* fd/100 */
                        csp[2] = *csp;          /* dx6 */
                        csp[3] = -(csp[-7] + csp[-5] + csp[-1]);	/* dy6 */
                        *csp = csp[-2], csp[1] = csp[-1];	/* dx5, dy5 */
                        csp[-2] = csp[-3], csp[-1] = 0;		/* dx4, dy4 */
                        csp[-3] = 0;	/* dy3 */
                        csp += 4;
                        goto flex;
                    case ce2_flex1:
                        {
                            fixed dx = csp[-10] + csp[-8] + csp[-6] + csp[-4] + csp[-2];
                            fixed dy = csp[-9] + csp[-7] + csp[-5] + csp[-3] + csp[-1];

                            if (any_abs(dx) > any_abs(dy))
                                csp[1] = -dy;	/* d6 is dx6 */
                            else
                                csp[1] = *csp, *csp = -dx;	/* d6 is dy6 */
                        }
                        csp[2] = fixed_half;	/* fd/100 */
                        csp += 2;
                        goto flex;
                }
                break;

                /* Fill up the dispatch up to 32. */

              case_c2_undefs:
            default:		/* pacify compiler */
                return_error(gs_error_invalidfont);
        }
    }
}