Beispiel #1
0
static int
alpha_buffer_init(gs_state * pgs, fixed extra_x, fixed extra_y, int alpha_bits, 
                  bool devn)
{
    gx_device *dev = gs_currentdevice_inline(pgs);
    int log2_alpha_bits = ilog2(alpha_bits);
    gs_fixed_rect bbox;
    gs_int_rect ibox;
    uint width, raster, band_space;
    uint height;
    gs_log2_scale_point log2_scale;
    gs_memory_t *mem;
    gx_device_memory *mdev;

    log2_scale.x = log2_scale.y = log2_alpha_bits;
    gx_path_bbox(pgs->path, &bbox);
    ibox.p.x = fixed2int(bbox.p.x - extra_x) - 1;
    ibox.p.y = fixed2int(bbox.p.y - extra_y) - 1;
    ibox.q.x = fixed2int_ceiling(bbox.q.x + extra_x) + 1;
    ibox.q.y = fixed2int_ceiling(bbox.q.y + extra_y) + 1;
    width = (ibox.q.x - ibox.p.x) << log2_scale.x;
    raster = bitmap_raster(width);
    band_space = raster << log2_scale.y;
    height = (abuf_nominal / band_space) << log2_scale.y;
    if (height == 0)
        height = 1 << log2_scale.y;
    mem = pgs->memory;
    mdev = gs_alloc_struct(mem, gx_device_memory, &st_device_memory,
                           "alpha_buffer_init");
    if (mdev == 0)
        return 0;		/* if no room, don't buffer */
    /* We may have to update the marking parameters if we have a pdf14 device
       as our target.  Need to do while dev is still active in pgs */
    if (dev_proc(dev, dev_spec_op)(dev, gxdso_is_pdf14_device, NULL, 0) > 0) {
        gs_update_trans_marking_params(pgs);
    }
    gs_make_mem_abuf_device(mdev, mem, dev, &log2_scale,
                            alpha_bits, ibox.p.x << log2_scale.x, devn);
    mdev->width = width;
    mdev->height = height;
    mdev->bitmap_memory = mem;
    if ((*dev_proc(mdev, open_device)) ((gx_device *) mdev) < 0) {
        /* No room for bits, punt. */
        gs_free_object(mem, mdev, "alpha_buffer_init");
        return 0;
    }
    gx_set_device_only(pgs, (gx_device *) mdev);
    scale_paths(pgs, log2_scale.x, log2_scale.y, true);
    return 1;
}
Beispiel #2
0
/*
 * Handle the case of a large value or a value with a fraction part.
 * See gxmatrix.h for more details.
 */
fixed
fixed_coeff_mult(fixed value, long coeff, const fixed_coeff *pfc, int maxb)
{
    int shift = pfc->shift;

    /*
     * Test if the value is too large for simple long math.
     */
    if ((value + (fixed_1 << (maxb - 1))) & (-fixed_1 << maxb)) {
        /* The second argument of fixed_mult_quo must be non-negative. */
        return
            (coeff < 0 ?
             -fixed_mult_quo(value, -coeff, fixed_1 << shift) :
             fixed_mult_quo(value, coeff, fixed_1 << shift));
    } else {
        /*
         * The construction above guarantees that the multiplications
         * won't overflow the capacity of an int.
         */
        return (fixed)
            arith_rshift(fixed2int_var(value) * coeff
                         + fixed2int(fixed_fraction(value) * coeff)
                         + pfc->round, shift);
    }
}
Beispiel #3
0
/* Draw a one-pixel-wide line. */
int
gz_draw_line_fixed(fixed ixf, fixed iyf, fixed itoxf, fixed itoyf,
  gx_device_color *pdevc, gs_state *pgs)
{	int ix = fixed2int(ixf);
	int iy = fixed2int(iyf);
	int itox = fixed2int(itoxf);
	int itoy = fixed2int(itoyf);
	if ( itoy == iy )		/* horizontal line */
	   {	if ( ix <= itox )
			gz_fill_rectangle(ix, iy, fixed2int_ceiling(itoxf) -
						ix, 1, pdevc, pgs);
		else
			gz_fill_rectangle(itox, iy, fixed2int_ceiling(ixf) -
						itox, 1, pdevc, pgs);
	   }
	else
	   {	gx_device *dev = pgs->device->info;
		fixed h, w, tf;
#define fswap(a, b) tf = a, a = b, b = tf
		if ( color_is_pure(pdevc) &&
		    (*dev->procs->draw_line)(dev, ix, iy, itox, itoy,
					     pdevc->color1) >= 0 )
		  return 0;
		h = itoyf - iyf;
		w = itoxf - ixf;
#define fixed_eps (fixed)1
		if ( (w < 0 ? -w : w) <= (h < 0 ? -h : h) )
		   {	if ( h < 0 )
				fswap(ixf, itoxf), fswap(iyf, itoyf),
				h = -h;
			gz_fill_trapezoid_fixed(ixf, fixed_eps, iyf,
						itoxf, fixed_eps, h,
						0, pdevc, pgs);
		   }
		else
		   {	if ( w < 0 )
				fswap(ixf, itoxf), fswap(iyf, itoyf),
				w = -w;
			gz_fill_trapezoid_fixed(iyf, fixed_eps, ixf,
						itoyf, fixed_eps, w,
						1, pdevc, pgs);
		   }
#undef fixed_eps
#undef fswap
	   }
	return 0;
}
Beispiel #4
0
static int
alpha_buffer_init(gs_state * pgs, fixed extra_x, fixed extra_y, int alpha_bits)
{
    gx_device *dev = gs_currentdevice_inline(pgs);
    int log2_alpha_bits = ilog2(alpha_bits);
    gs_fixed_rect bbox;
    gs_int_rect ibox;
    uint width, raster, band_space;
    uint height;
    gs_log2_scale_point log2_scale;
    gs_memory_t *mem;
    gx_device_memory *mdev;

    log2_scale.x = log2_scale.y = log2_alpha_bits;
    gx_path_bbox(pgs->path, &bbox);
    ibox.p.x = fixed2int(bbox.p.x - extra_x) - 1;
    ibox.p.y = fixed2int(bbox.p.y - extra_y) - 1;
    ibox.q.x = fixed2int_ceiling(bbox.q.x + extra_x) + 1;
    ibox.q.y = fixed2int_ceiling(bbox.q.y + extra_y) + 1;
    width = (ibox.q.x - ibox.p.x) << log2_scale.x;
    raster = bitmap_raster(width);
    band_space = raster << log2_scale.y;
    height = (abuf_nominal / band_space) << log2_scale.y;
    if (height == 0)
	height = 1 << log2_scale.y;
    mem = pgs->memory;
    mdev = gs_alloc_struct(mem, gx_device_memory, &st_device_memory,
			   "alpha_buffer_init");
    if (mdev == 0)
	return 0;		/* if no room, don't buffer */
    gs_make_mem_abuf_device(mdev, mem, dev, &log2_scale,
			    alpha_bits, ibox.p.x << log2_scale.x);
    mdev->width = width;
    mdev->height = height;
    mdev->bitmap_memory = mem;
    if ((*dev_proc(mdev, open_device)) ((gx_device *) mdev) < 0) {
	/* No room for bits, punt. */
	gs_free_object(mem, mdev, "alpha_buffer_init");
	return 0;
    }
    gx_set_device_only(pgs, (gx_device *) mdev);
    scale_paths(pgs, log2_scale.x, log2_scale.y, true);
    return 1;
}
Beispiel #5
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, di, 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, di = 1; i < i1; i += di) {
	if (di == 1) {
	    /* Advance colors by 1 pixel. */
	    ci1 = 0;
	    for (k = 0; k < n; k++) {
		int shift = cinfo->comp_shift[k];
		int bits = cinfo->comp_bits[k];

		if (cg_num[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;
	    }
	} else {
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;
}
Beispiel #7
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);
}
Beispiel #8
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;
}
Beispiel #9
0
/* Note that the arguments are fixeds, not ints! */
int
gz_fill_trapezoid_fixed(fixed fx0, fixed fw0, fixed fy0,
  fixed fx1, fixed fw1, fixed fh, int swap_axes,
  gx_device_color *pdevc, gs_state *pgs)
{	/* For the moment, we just convert everything to ints. */
	/* Later we will do the right thing with fractional pixels. */
	int x0 = fixed2int(fx0);
	fixed fx0r = fx0 + fw0;
	int w0 = fixed2int_ceiling(fx0r) - x0;
	int y0 = fixed2int(fy0);
	int x1 = fixed2int(fx1);
	fixed fx1r = fx1 + fw1;
	int w1 = fixed2int_ceiling(fx1r) - x1;
	fixed fy1 = fy0 + fh;
	int y1 = fixed2int_ceiling(fy1);
	int h = y1 - y0;
	if ( w0 == 0 && w1 == 0 || h <= 0 ) return 0;
	if ( !swap_axes && color_is_pure(pdevc) )
	   {	gx_device *dev = pgs->device->info;
		if ( (*dev->procs->fill_trapezoid)(dev,
			x0, y0, w0, x1, y1, w1,
			pdevc->color1) >= 0
		   )
			return 0;
	   }
	   {	int xl, fxl;
		int dxl, dxl1, dxlf = x1 - x0;
		int xr, fxr;
		int dxr, dxr1, dxrf = x1 + w1 - (x0 + w0);
		int y = y0;
		int rxl, rxr, ry;
		/* Compute integer and fractional deltas */
#define reduce_delta(df, d, d1, pos)\
	if ( df >= 0 )\
	   {	if ( df >= h )\
		  d1 = (d = df / h) + 1, df -= d * h;\
		else	/* save the divides */\
		   {	pos();\
			d = 0, d1 = 1;\
		   }\
	   }\
	else			/* df < 0 */\
	   {	if ( df <= -h )\
		  d1 = (d = df / h) - 1, df = d * h - df;\
		else	/* save the divides */\
		  d = 0, d1 = -1, df = -df;\
	   }
#define fill_trap_rect(x,y,w,h)\
  if ( swap_axes ) gz_fill_rectangle(y, x, h, w, pdevc, pgs);\
  else gz_fill_rectangle(x, y, w, h, pdevc, pgs)
#define pos_for_xl()			/* nothing */
		reduce_delta(dxlf, dxl, dxl1, pos_for_xl);
#define pos_for_xr()\
	if ( dxl == 0 && dxlf == 0 && dxrf == 0 )  /* detect rectangle */\
	   {	fill_trap_rect(x0, y0, w0, h);\
		return 0;\
	   }
		reduce_delta(dxrf, dxr, dxr1, pos_for_xr);
		xl = x0, fxl = arith_rshift(dxlf, 1);
		xr = x0 + w0, fxr = arith_rshift(dxrf, 1);
		rxl = xl, rxr = xr, ry = y;
		/* Do the fill */
		do
		   {	if ( xl != rxl || xr != rxr )	/* detect rectangles */
			   {	fill_trap_rect(rxl, ry, rxr - rxl, y - ry);
				rxl = xl, rxr = xr, ry = y;
			   }
			if ( (fxl += dxlf) >= h ) fxl -= h, xl += dxl1;
			else xl += dxl;
			if ( (fxr += dxrf) >= h ) fxr -= h, xr += dxr1;
			else xr += dxr;
		   }
		while ( ++y < y1 );
		if ( y != ry )
		   {	fill_trap_rect(rxl, ry, rxr - rxl, y - ry);
		   }
#undef fill_trap_rect
	   }
	return 0;
}
Beispiel #10
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;
	}
Beispiel #11
0
static int margin_boundary(line_list * ll, margin_set * set, active_line * alp,
                            fixed xx0, fixed xx1, fixed yy0, fixed yy1, int dir, fixed y0, fixed y1)
{   section *sect = set->sect;
    fixed x0, x1, xmin, xmax;
    int xp0, xp;
    int i0, i;
#   if !CHECK_SPOT_CONTIGUITY
    int i1;
#   endif

    if (yy0 > yy1)
        return 0;
    /* enumerate integral x's in [yy0,yy1] : */

    if (alp == 0)
        x0 = xx0, x1 = xx1;
    else {
        x0 = (yy0 == y0 ? alp->x_current : AL_X_AT_Y(alp, yy0));
        x1 = (yy1 == y1 ? alp->x_next : AL_X_AT_Y(alp, yy1));
    }
    xmin = min(x0, x1);
    xmax = max(x0, x1);
#   if !CHECK_SPOT_CONTIGUITY
        xp0 = fixed_floor(xmin) + fixed_half;
        i0 = fixed2int(xp0) - ll->bbox_left;
        if (xp0 < xmin) {
            xp0 += fixed_1;
            i0++;
        }
        if (i0 < 0)
            return_error(gs_error_unregistered); /* Must not happen. */
        for (i = i0, xp = xp0; xp < xmax && i < ll->bbox_width; xp += fixed_1, i++) {
            fixed y = (alp == 0 ? yy0 : Y_AT_X(alp, xp));
            fixed dy = y - set->y;
            bool ud;
            short *b, h;
            section *s = &sect[i];

            if (dy < 0)
                dy = 0; /* fix rounding errors in Y_AT_X */
            if (dy >= fixed_1)
                dy = fixed_1; /* safety */
            vd_circle(xp, y, 2, 0);
            ud = (alp == 0 ? (dir > 0) : ((alp->start.x - alp->end.x) * dir > 0));
            b = (ud ? &s->y0 : &s->y1);
            h = (short)dy;
            if (*b == -1 || (*b != -2 && ( ud ? *b > h : *b < h)))
                *b = h;
        }
#   else
        xp0 = fixed_floor(xmin) + fixed_half;
        i0 = fixed2int(xp0) - ll->bbox_left;
        if (xp0 < xmin) {
            i0++;
            xp0 += fixed_1;
        }
        for (i = i0, xp = xp0; xp < xmax; xp += fixed_1, i++) {
            section *s = &sect[i];
            fixed y = (alp==0 ? yy0 : Y_AT_X(alp, xp));
            fixed dy = y - set->y;
            bool ud;
            short *b, h;

            if (dy < 0)
                dy = 0; /* fix rounding errors in Y_AT_X */
            if (dy >= fixed_1)
                dy = fixed_1; /* safety */
            vd_circle(xp, y, 2, 0);
            ud = (alp == 0 ? (dir > 0) : ((alp->start.x - alp->end.x) * dir > 0));
            b = (ud ? &s->y0 : &s->y1);
            h = (short)dy;
            if (*b == -1 || (*b != -2 && ( ud ? *b > h : *b < h)))
                *b = h;
        }
        if (i0 < 0 || i > ll->bbox_width)
            return_error(gs_error_unregistered); /* Must not happen. */
#	endif
    if (i > i0)
        return store_margin(ll, set, i0, i);
    return 0;
}
Beispiel #12
0
int
gslt_render_font_glyph(gs_state *pgs, gslt_font_t *xf, gs_matrix *tm, int gid, gslt_glyph_bitmap_t *slot)
{
    gs_fixed_point subpixel = {0, 0}; /* we don't use subpixel accurate device metrics */
    gs_log2_scale_point oversampling = {0, 0}; /* we don't use oversampling */
    gs_text_params_t params;
    gs_text_enum_t *textenum;
    gs_matrix matrix;
    cached_fm_pair *ppair;
    cached_char *cc;
    int code;

    /* get the real font matrix (this is a little dance) */
    gs_setfont(pgs, xf->font); /* set pgs->font and invalidate existing charmatrix */
    gs_setcharmatrix(pgs, tm); /* set the charmatrix to ctm * tm */
    gs_currentcharmatrix(pgs, &matrix, true); /* extract charmatrix (and multiply by FontMatrix) */

    // dprintf4("tm = [%g %g %g %g]\n", matrix.xx, matrix.xy, matrix.yx, matrix.yy);

    /* find the font/matrix pair (or add it) */
    code = gx_lookup_fm_pair(xf->font, &matrix, &oversampling, false, &ppair);
    if (code != 0)
        return gs_throw(-1, "cannot gx_lookup_fm_pair()");

    cc = gx_lookup_cached_char(xf->font, ppair, gid, 0, 1, &subpixel);
    if (!cc)
    {
        /* No luck ... now we need to get it into the cache somehow.
         *
         * We do this by rendering one glyph (that's why we need a device and pgs).
         * The renderer always renders the bitmap into the cache, and draws
         * from out of the cache when blitting to the device.
         *
         * Things don't get evicted from the cache until there is a collision,
         * so we have a safe window to snarf it back out of the cache
         * after it's been drawn to the device.
         */

        // dprintf1("cache miss for glyph %d\n", gid);

        params.operation = TEXT_FROM_SINGLE_GLYPH | TEXT_DO_DRAW | TEXT_RETURN_WIDTH;
        params.data.d_glyph = gid;
        params.size = 1;

	gs_moveto(pgs, 100.0, 100.0); // why?

        code = gs_text_begin(pgs, &params, xf->font->memory, &textenum);
	if (code != 0)
            return gs_throw1(-1, "cannot gs_text_begin() (%d)", code);

        code = gs_text_process(textenum);
	if (code != 0)
            return gs_throw1(-1, "cannot gs_text_process() (%d)", code);

        gs_text_release(textenum, "gslt font render");

        cc = gx_lookup_cached_char(xf->font, ppair, gid, 0, 1, &subpixel);
        if (!cc)
        {
            /* merde! it rendered but was not placed in the cache. */
            return gs_throw(-2, "cannot render from cache");
        }
    }

    /* copy values from the cache into the client struct */
    slot->w = cc->width;
    slot->h = cc->height;
    slot->stride = cc_raster(cc);
    slot->lsb = fixed2int(cc->offset.x);
    slot->top = fixed2int(cc->offset.y);

    slot->cc = cc;
    slot->data = cc_bits(cc);
    gx_retain_cached_char(cc);

#define XXX
#ifndef XXX
    static int xxx = 0; /* declaration out in the wild not allowed in ansi c */
    dprintf1("glyph %d\n", xxx);
    debug_dump_bitmap(cc_bits(cc), cc_raster(cc), cc->height, "");
    {
        char fn[32];
        sprintf(fn, "glyph%d.pbm", xxx);
        FILE *fo = fopen(fn, "wb");
        if (!fo)
            return -1;
        fprintf(fo, "P4\n%d %d\n", cc->width, cc->height);
        int y;
        int s = (cc->width + 7) / 8;
        for (y = 0; y < cc->height; y++)
            fwrite(cc_bits(cc) + y * cc_raster(cc), 1, s, fo);
        fclose(fo);
    }
    xxx ++;
#endif

    return 0;
}
Beispiel #13
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;
}
Beispiel #14
0
/* We take the trouble to do this efficiently in the simple cases. */
int
gs_rectfill(gs_state * pgs, const gs_rect * pr, uint count)
{
    const gs_rect *rlist = pr;
    gx_clip_path *pcpath;
    uint rcount = count;
    int code;
    gx_device * pdev = pgs->device;
    gx_device_color *pdc = gs_currentdevicecolor_inline(pgs);
    const gs_imager_state *pis = (const gs_imager_state *)pgs;
    bool hl_color_available = gx_hld_is_hl_color_available(pis, pdc);
    bool hl_color = (hl_color_available &&
                dev_proc(pdev, dev_spec_op)(pdev, gxdso_supports_hlcolor, 
                                  NULL, 0));
    bool center_of_pixel = (pgs->fill_adjust.x == 0 && pgs->fill_adjust.y == 0);

    /* Processing a fill object operation */
    dev_proc(pgs->device, set_graphics_type_tag)(pgs->device, GS_PATH_TAG);

    code = gx_set_dev_color(pgs);
    if (code != 0)
        return code;
    if ((is_fzero2(pgs->ctm.xy, pgs->ctm.yx) ||
         is_fzero2(pgs->ctm.xx, pgs->ctm.yy)) &&
        gx_effective_clip_path(pgs, &pcpath) >= 0 &&
        clip_list_is_rectangle(gx_cpath_list(pcpath)) &&
        (hl_color ||
         pdc->type == gx_dc_type_pure ||
         pdc->type == gx_dc_type_ht_binary ||
         pdc->type == gx_dc_type_ht_colored) &&
        gs_state_color_load(pgs) >= 0 &&
        (*dev_proc(pdev, get_alpha_bits)) (pdev, go_graphics)
        <= 1 &&
        (!pgs->overprint || !pgs->effective_overprint_mode)
        ) {
        uint i;
        gs_fixed_rect clip_rect;

        gx_cpath_inner_box(pcpath, &clip_rect);
        /* We should never plot anything for an empty clip rectangle */
        if ((clip_rect.p.x >= clip_rect.q.x) &&
            (clip_rect.p.y >= clip_rect.q.y))
            return 0;
        for (i = 0; i < count; ++i) {
            gs_fixed_point p, q;
            gs_fixed_rect draw_rect;

            if (gs_point_transform2fixed(&pgs->ctm, pr[i].p.x, pr[i].p.y, &p) < 0 ||
                gs_point_transform2fixed(&pgs->ctm, pr[i].q.x, pr[i].q.y, &q) < 0
                ) {		/* Switch to the slow algorithm. */
                goto slow;
            }
            draw_rect.p.x = min(p.x, q.x);
            draw_rect.p.y = min(p.y, q.y);
            draw_rect.q.x = max(p.x, q.x);
            draw_rect.q.y = max(p.y, q.y);
            if (hl_color) {
                rect_intersect(draw_rect, clip_rect);
                /* We do pass on 0 extant rectangles to high level
                   devices.  It isn't clear how a client and an output
                   device should interact if one uses a center of
                   pixel algorithm and the other uses any part of
                   pixel.  For now we punt and just pass the high
                   level rectangle on without adjustment. */
                if (draw_rect.p.x <= draw_rect.q.x &&
                    draw_rect.p.y <= draw_rect.q.y) {
                    code = dev_proc(pdev, fill_rectangle_hl_color)(pdev,
                             &draw_rect, pis, pdc, pcpath);
                    if (code < 0)
                        return code;
                }
            } else {
                int x, y, w, h;

                rect_intersect(draw_rect, clip_rect);
                if (center_of_pixel) {
                    draw_rect.p.x = fixed_rounded(draw_rect.p.x);
                    draw_rect.p.y = fixed_rounded(draw_rect.p.y);
                    draw_rect.q.x = fixed_rounded(draw_rect.q.x);
                    draw_rect.q.y = fixed_rounded(draw_rect.q.y);
                } else { /* any part of pixel rule - touched */
                    draw_rect.p.x = fixed_floor(draw_rect.p.x);
                    draw_rect.p.y = fixed_floor(draw_rect.p.y);
                    draw_rect.q.x = fixed_ceiling(draw_rect.q.x);
                    draw_rect.q.y = fixed_ceiling(draw_rect.q.y);
                }
                x = fixed2int(draw_rect.p.x);
                y = fixed2int(draw_rect.p.y);
                w = fixed2int(draw_rect.q.x) - x;
                h = fixed2int(draw_rect.q.y) - y;
                /* clients that use the "any part of pixel" rule also
                   fill 0 areas.  This is true of current graphics
                   library clients but not a general rule.  */
                if (!center_of_pixel) {
                    if (w == 0)
                        w = 1;
                    /* yes Adobe Acrobat 8, seems to back up the y
                       coordinate when the width is 0, sigh. */
                    if (h == 0) {
                        y--;
                        h = 1;
                    }
                }
                if (gx_fill_rectangle(x, y, w, h, pdc, pgs) < 0)
                    goto slow;
            }
        }
        return 0;
      slow:rlist = pr + i;
        rcount = count - i;
    } {
        bool do_save = !gx_path_is_null(pgs->path);

        if (do_save) {
            if ((code = gs_gsave(pgs)) < 0)
                return code;
            gs_newpath(pgs);
        }
        if ((code = gs_rectappend(pgs, rlist, rcount)) < 0 ||
            (code = gs_fill(pgs)) < 0
            )
            DO_NOTHING;
        if (do_save)
            gs_grestore(pgs);
        else if (code < 0)
            gs_newpath(pgs);
    }
    return code;
}
Beispiel #15
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;
}
Beispiel #16
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;
}