Exemplo n.º 1
0
/* Initialize a Type 1 interpreter. */
static int
type1_exec_init(gs_type1_state *pcis, gs_text_enum_t *penum,
                gs_state *pgs, gs_font_type1 *pfont1)
{
    /*
     * We have to disregard penum->pis and penum->path, and render to
     * the current gstate and path.  This is a design bug that we will
     * have to address someday!
     */

    int alpha_bits = 1;
    gs_log2_scale_point log2_subpixels;

    if (color_is_pure(gs_currentdevicecolor_inline(pgs))) /* Keep consistency with alpha_buffer_bits() */
        alpha_bits = (*dev_proc(pgs->device, get_alpha_bits)) (pgs->device, go_text);
    if (alpha_bits <= 1) {
        /* We render to cache device or the target device has no alpha bits. */
        log2_subpixels = penum->log2_scale;
    } else {
        /* We'll render to target device through alpha buffer. */
        /* Keep consistency with alpha_buffer_init() */
        log2_subpixels.x = log2_subpixels.y = ilog2(alpha_bits);
    }
    return gs_type1_interp_init(pcis, (gs_imager_state *)pgs, pgs->path,
                                &penum->log2_scale, &log2_subpixels,
                                (penum->text.operation & TEXT_DO_ANY_CHARPATH) != 0 ||
                                penum->device_disabled_grid_fitting,
                                pfont1->PaintType, pfont1);
}
Exemplo n.º 2
0
/* Fill a rectangle. */
int
gz_fill_rectangle(int x, int y, int w, int h, gx_device_color *pdevc,
  gs_state *pgs)
{	gx_color_index darker = pdevc->color1;
	gx_color_index lighter;
	gx_device *dev = pgs->device->info;
	gx_bitmap *tile;
	int code;
#ifdef DEBUG
if ( gs_debug['q'] )
	printf("[q]x=%d y=%d w=%d h=%d  c1=%ld c2=%ld htl=%d\n",
		x, y, w, h, darker, (long)pdevc->color2,
		(long)pdevc->halftone_level);
#endif
	if ( color_is_pure(pdevc) )	/* no halftoning */
	   {	return (*dev->procs->fill_rectangle)(dev, x, y, w, h, darker);
	   }
	lighter = pdevc->color2;
	tile = pdevc->tile;
	/* See if the entire transfer falls within a single tile. */
	/* This is worth a quick check, because tiling is slow. */
	if ( w <= tile->width && h <= tile->height )
	   {	int xmod = x % tile->width, ymod;
		if ( xmod + w <= tile->width &&
		     (ymod = y % tile->height) + h <= tile->height
		   )
		   {	/* Just do a copy. */
			int raster = tile->raster;
			byte *tdata = tile->data + ymod * raster;
			return (color_is_color_halftone(pdevc) ?
				(*dev->procs->copy_color)(dev, tdata,
					xmod, raster, x, y, w, h) :
				(*dev->procs->copy_mono)(dev, tdata,
					xmod, raster, x, y, w, h,
					darker, lighter));
		   }
	   }
	/* Try to tile the rectangle primitively; */
	/* if this fails, use the default implementation. */
	if ( color_is_color_halftone(pdevc) )
		darker = lighter = gx_no_color_index;
	code = (*dev->procs->tile_rectangle)(dev, tile,
		x, y, w, h, darker, lighter);
	if ( code < 0 )
	   {	/* Use the default implementation */
		code = gx_default_tile_rectangle(dev, tile,
			x, y, w, h, darker, lighter);
	   }
	return code;
}
Exemplo n.º 3
0
/* Draw a one-pixel-wide line. */
int
gz_draw_line_fixed(fixed ixf, fixed iyf, fixed itoxf, fixed itoyf,
  const gx_device_color *pdevc, gs_state *pgs)
{	int ix = fixed2int_var(ixf);
	int iy = fixed2int_var(iyf);
	int itox = fixed2int_var(itoxf);
	int itoy = fixed2int_var(itoyf);
	gx_device *dev;
	gp_check_interrupts();
	if ( itoy == iy )		/* horizontal line */
	  { return (ix <= itox ?
		    gz_fill_rectangle(ix, iy, itox - ix + 1, 1, pdevc, pgs) :
		    gz_fill_rectangle(itox, iy, ix - itox + 1, 1, pdevc, pgs)
		    );
	  }
	if ( itox == ix )		/* vertical line */
	  { return (iy <= itoy ?
		    gz_fill_rectangle(ix, iy, 1, itoy - iy + 1, pdevc, pgs) :
		    gz_fill_rectangle(ix, itoy, 1, iy - itoy + 1, pdevc, pgs)
		    );
	  }
	if ( color_is_pure(pdevc) &&
	    (dev = pgs->device->info,
	     (*dev->procs->draw_line)(dev, ix, iy, itox, itoy,
				      pdevc->color1)) >= 0 )
	  return 0;
	{ fixed h = itoyf - iyf;
	  fixed w = itoxf - ixf;
	  fixed tf;
#define fswap(a, b) tf = a, a = b, b = tf
	  if ( (w < 0 ? -w : w) <= (h < 0 ? -h : h) )
	    { if ( h < 0 )
		fswap(ixf, itoxf), fswap(iyf, itoyf),
		h = -h;
	      return gz_fill_trapezoid_fixed(ixf - fixed_half, fixed_1, iyf,
					     itoxf - fixed_half, fixed_1, h,
					     0, pdevc, pgs);
	    }
	  else
	    { if ( w < 0 )
		fswap(ixf, itoxf), fswap(iyf, itoyf),
		w = -w;
	      return gz_fill_trapezoid_fixed(iyf - fixed_half, fixed_1, ixf,
					     itoyf - fixed_half, fixed_1, w,
					     1, pdevc, pgs);
	    }
#undef fswap
	}
}
Exemplo n.º 4
0
/*
 * Determine the number of bits of alpha buffer for a stroke or fill.
 * We should do alpha buffering iff this value is >1.
 */
static int
alpha_buffer_bits(gs_state * pgs)
{
    gx_device *dev;

    if (!color_is_pure(pgs->dev_color))
	return 0;
    dev = gs_currentdevice_inline(pgs);
    if (gs_device_is_abuf(dev)) {
	/* We're already writing into an alpha buffer. */
	return 0;
    }
    return (*dev_proc(dev, get_alpha_bits))
	(dev, (pgs->in_cachedevice ? go_text : go_graphics));
}
Exemplo n.º 5
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;
}
Exemplo n.º 6
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;
}
Exemplo n.º 7
0
int
gz_fill_trapezoid_fixed(fixed fx0, fixed fw0, fixed fy0,
  fixed fx1, fixed fw1, fixed fh, int swap_axes,
  const gx_device_color *pdevc, gs_state *pgs)
{	const fixed ymin = fixed_rounded(fy0) + fixed_half;
	const fixed ymax = fixed_rounded(fy0 + fh);
	int iy = fixed2int_var(ymin);
	const int iy1 = fixed2int_var(ymax);
	if ( iy >= iy1 ) return 0;	/* no scan lines to sample */
   {	trap_line l, r;
	int rxl, rxr, ry;
	const fixed dxl = fx1 - fx0;
	const fixed dxr = dxl + fw1 - fw0;
	const fixed yline = ymin - fy0;	/* partial pixel offset to */
					/* first line to sample */
	int fill_direct = color_is_pure(pdevc);
	gx_color_index cindex;
	gx_device *dev;
	dev_proc_fill_rectangle((*fill_rect));
	int code;
	
	if_debug2('z', "[z]y=[%d,%d]\n", iy, iy1);

	if ( fill_direct )
	  cindex = pdevc->color1,
	  dev = pgs->device->info,
	  fill_rect = dev->procs->fill_rectangle;
	gp_check_interrupts();
	r.x = (l.x = fx0 + fixed_half) + fw0;
	ry = iy;

	/* If the rounded X values are the same on both sides, */
	/* we can save ourselves a *lot* of work. */
	if ( fixed_truncated(l.x) == fixed_rounded(fx1) &&
	     fixed_truncated(r.x) == fixed_rounded(fx1 + fw1)
	   )
	{	rxl = fixed2int_var(l.x);
		rxr = fixed2int_var(r.x);
		iy = iy1;
		if_debug2('z', "[z]rectangle, x=[%d,%d]\n", rxl, rxr);
		goto last;
	}

#define fill_trap_rect(x,y,w,h)\
  (fill_direct ?\
    (swap_axes ? (*fill_rect)(dev, y, x, h, w, cindex) :\
     (*fill_rect)(dev, x, y, w, h, cindex)) :\
   swap_axes ? gz_fill_rectangle(y, x, h, w, pdevc, pgs) :\
   gz_fill_rectangle(x, y, w, h, pdevc, pgs))

	/* Compute the dx/dy ratios. */
	/* dx# = dx#i + (dx#f / fh). */
#define compute_dx(tl, d)\
  if ( d >= 0 )\
   { if ( d < fh ) tl.di = 0, tl.df = d;\
     else tl.di = (int)(d / fh), tl.df = d - tl.di * fh, tl.x += yline * tl.di;\
   }\
  else\
   { if ( (tl.df = d + fh) >= 0 /* d >= -fh */ ) tl.di = -1, tl.x -= yline;\
     else tl.di = (int)-((fh - 1 - d) / fh), tl.df = d - tl.di * fh, tl.x += yline * tl.di;\
   }

	/* Compute the x offsets at the first scan line to sample. */
	/* We need to be careful in computing yline * dx#f {/,%} fh */
	/* because the multiplication may overflow.  We know that */
	/* all the quantities involved are non-negative, and that */
	/* yline is less than 1 (as a fixed, of course); this gives us */
	/* a cheap conservative check for overflow in the multiplication. */
#define ymult_limit (max_fixed / fixed_1)
#define ymult_quo(yl, dxxf)\
  (dxxf < ymult_limit ? yl * dxxf / fh : fixed_mult_quo(yl, dxxf, fh))
#define ymult_rem(yl, dxxf)\
  (dxxf < ymult_limit ? yl * dxxf % fh : fixed_mult_rem(yl, dxxf, fh))

	/* It's worth checking for dxl == dxr, since this is the case */
	/* for parallelograms (including stroked lines). */
	compute_dx(l, dxl);
	if ( dxr == dxl )
	   {	fixed fx = ymult_quo(yline, l.df);
		l.x += fx;
		if ( l.di == 0 )
			r.di = 0, r.df = l.df;
		else			/* too hard to do adjustments right */
			compute_dx(r, dxr);
		r.x += fx;
	   }
	else
	   {	l.x += ymult_quo(yline, l.df);
		compute_dx(r, dxr);
		r.x += ymult_quo(yline, r.df);
	   }
	rxl = fixed2int_var(l.x);
	rxr = fixed2int_var(r.x);

	/* Compute one line's worth of dx/dy. */
	/* dx# * fixed_1 = ld#i + (ld#f / fh). */
	/* We don't have to bother with this if */
	/* we're only sampling a single scan line. */
	if ( iy1 - iy == 1 )
	   {	iy++;
		goto last;
	   }
#define compute_ldx(tl)\
  if ( tl.df < ymult_limit )\
    tl.ldi = int2fixed(tl.di) + int2fixed(tl.df) / fh,\
    tl.ldf = int2fixed(tl.df) % fh,\
    tl.xf = yline * tl.df % fh - fh;\
  else\
    tl.ldi = int2fixed(tl.di) + fixed_mult_quo(fixed_1, tl.df, fh),\
    tl.ldf = fixed_mult_rem(fixed_1, tl.df, fh),\
    tl.xf = fixed_mult_rem(yline, tl.df, fh) - fh
	compute_ldx(l);
	if ( dxr == dxl )
		r.ldi = l.ldi, r.ldf = l.ldf, r.xf = l.xf;
	else
	   {	compute_ldx(r);
	   }
#undef compute_ldx

	while ( ++iy != iy1 )
	   {	int ixl, ixr;
#define step_line(tl)\
  tl.x += tl.ldi;\
  if ( (tl.xf += tl.ldf) >= 0 ) tl.xf -= fh, tl.x++;
		step_line(l);
		step_line(r);
#undef step_line
		ixl = fixed2int_var(l.x);
		ixr = fixed2int_var(r.x);
		if ( ixl != rxl || ixr != rxr )
		   {	code = fill_trap_rect(rxl, ry, rxr - rxl, iy - ry);
			if ( code < 0 ) goto xit;
			rxl = ixl, rxr = ixr, ry = iy;
		   }	
	   }
last:	code = fill_trap_rect(rxl, ry, rxr - rxl, iy - ry);
xit:	gp_check_interrupts();
	if ( code < 0 && fill_direct ) return_error(code);
	return code;
   }
}
Exemplo n.º 8
0
static int
do_stroke(gs_state * pgs)
{
    int code, abits, acode, rcode = 0;
    bool devn;

    /* Here we need to distinguish text from vectors to compute the object tag.
       Actually we need to know whether this function is called to rasterize a character,
       or to rasterize a vector graphics to the output device.
       Currently we assume it works for the bitrgbtags device only,
       which is a low level device with a 4-component color model.
       We use the fact that with printers a character is usually being rendered
       to a 1bpp cache device rather than to the output device.
       Therefore we hackly look whether the target device
       "has a color" : either it's a multicomponent color model,
       or it is not gray (such as a yellow separation).

       This check has several limitations :
       1. It doesn't work with -dNOCACHE.
       2. It doesn't work with large characters,
          which cannot fit into a cache cell and thus they
          render directly to the output device.
       3. It doesn't work for TextAlphaBits=2 or 4.
          We don't care of this case because
          text antialiasing usually usn't applied to printers.
       4. It doesn't work for things like with "(xyz) true charpath stroke".
          That's unfortunate, we'd like to improve someday.
       5. It doesn't work for high level devices when a Type 3 character is being constructed.
          This case is not important for low level devices
          (which a printer is), because low level device doesn't accept
          Type 3 charproc streams immediately.
     */
    if (gx_device_has_color(gs_currentdevice(pgs))) {
        dev_proc(pgs->device, set_graphics_type_tag)(pgs->device, GS_PATH_TAG);
    }
    else {
        dev_proc(pgs->device, set_graphics_type_tag)(pgs->device, GS_TEXT_TAG);
    }
    code = gx_set_dev_color(pgs);
    if (code != 0)
        return code;
    code = gs_state_color_load(pgs);
    if (code < 0)
        return code;
    abits = 0;
    {
        gx_device_color *col = gs_currentdevicecolor_inline(pgs);
        devn = color_is_devn(col);
        if (color_is_pure(col) || devn)
            abits = alpha_buffer_bits(pgs);
    }
    if (abits > 1) {
        /*
         * Expand the bounding box by the line width.
         * This is expensive to compute, so we only do it
         * if we know we're going to buffer.
         */
        float xxyy = fabs(pgs->ctm.xx) + fabs(pgs->ctm.yy);
        float xyyx = fabs(pgs->ctm.xy) + fabs(pgs->ctm.yx);
        float scale = (float)(1 << (abits / 2));
        float orig_width = gs_currentlinewidth(pgs);
        float new_width = orig_width * scale;
        fixed extra_adjust =
                float2fixed(max(xxyy, xyyx) * new_width / 2);
        float orig_flatness = gs_currentflat(pgs);
        gx_path spath;

        /* Scale up the line width, dash pattern, and flatness. */
        if (extra_adjust < fixed_1)
            extra_adjust = fixed_1;
        acode = alpha_buffer_init(pgs,
                                  pgs->fill_adjust.x + extra_adjust,
                                  pgs->fill_adjust.y + extra_adjust,
                                  abits, devn);
        if (acode < 0)
            return acode;
        gs_setlinewidth(pgs, new_width);
        scale_dash_pattern(pgs, scale);
        gs_setflat(pgs, orig_flatness * scale);
        /*
         * The alpha-buffer device requires that we fill the
         * entire path as a single unit.
         */
        gx_path_init_local(&spath, pgs->memory);
        code = gx_stroke_add(pgs->path, &spath, pgs, false);
        gs_setlinewidth(pgs, orig_width);
        scale_dash_pattern(pgs, 1.0 / scale);
        if (code >= 0)
            code = gx_fill_path(&spath, gs_currentdevicecolor_inline(pgs), pgs,
                                gx_rule_winding_number,
                                pgs->fill_adjust.x,
                                pgs->fill_adjust.y);
        gs_setflat(pgs, orig_flatness);
        gx_path_free(&spath, "gs_stroke");
        if (acode > 0)
            rcode = alpha_buffer_release(pgs, code >= 0);
    } else
        code = gx_stroke_fill(pgs->path, pgs);
    if (code >= 0 && rcode < 0)
        code = rcode;
    return code;
}
Exemplo n.º 9
0
static int do_fill(gs_state *pgs, int rule)
{
    int code, abits, acode, rcode = 0;
    bool devn;

    /* Here we need to distinguish text from vectors to compute the object tag.
       Actually we need to know whether this function is called to rasterize a character,
       or to rasterize a vector graphics to the output device.
       Currently we assume it works for the bitrgbtags device only,
       which is a low level device with a 4-component color model.
       We use the fact that with printers a character is usually being rendered
       to a 1bpp cache device rather than to the output device.
       Therefore we hackly look whether the target device
       "has a color" : either it's a multicomponent color model,
       or it is not gray (such as a yellow separation).

       This check has several limitations :
       1. It doesn't work with -dNOCACHE.
       2. It doesn't work with large characters,
          which cannot fit into a cache cell and thus they
          render directly to the output device.
       3. It doesn't work for TextAlphaBits=2 or 4.
          We don't care of this case because
          text antialiasing usually usn't applied to printers.
       4. It doesn't work for things like with "(xyz) true charpath stroke".
          That's unfortunate, we'd like to improve someday.
       5. It doesn't work for high level devices when a Type 3 character is being constructed.
          This case is not important for low level devices
          (which a printer is), because low level device doesn't accept
          Type 3 charproc streams immediately.
       6. It doesn't work properly while an insiding testing,
          which sets gs_hit_device, which is uncolored.
     */
    if (gx_device_has_color(gs_currentdevice(pgs))) {
        dev_proc(pgs->device, set_graphics_type_tag)(pgs->device, GS_PATH_TAG);
    }
    else {
        dev_proc(pgs->device, set_graphics_type_tag)(pgs->device, GS_TEXT_TAG);
    }
    code = gx_set_dev_color(pgs);
    if (code != 0)
        return code;
    code = gs_state_color_load(pgs);
    if (code < 0)
        return code;
    abits = 0;
    {
        gx_device_color *col = gs_currentdevicecolor_inline(pgs);
        devn = color_is_devn(col);
        if (color_is_pure(col) || devn)
            abits = alpha_buffer_bits(pgs);
    }
    if (abits > 1) {
        acode = alpha_buffer_init(pgs, pgs->fill_adjust.x,
                                  pgs->fill_adjust.y, abits, devn);
        if (acode < 0)
            return acode;
    } else
        acode = 0;
    code = gx_fill_path(pgs->path, gs_currentdevicecolor_inline(pgs), pgs, rule,
                        pgs->fill_adjust.x, pgs->fill_adjust.y);
    if (acode > 0)
        rcode = alpha_buffer_release(pgs, code >= 0);
    if (code >= 0 && rcode < 0)
        code = rcode;

    return code;
}