示例#1
0
文件: gscolor3.c 项目: 99years/plan9
/* shfill */
int
gs_shfill(gs_state * pgs, const gs_shading_t * psh)
{
    /*
     * shfill is equivalent to filling the current clipping path (or, if
     * clipping, its bounding box) with the shading, disregarding the
     * Background if any.  In order to produce reasonable high-level output,
     * we must actually implement this by calling gs_fill rather than
     * gs_shading_fill_path.  However, filling with a shading pattern does
     * paint the Background, so if necessary, we construct a copy of the
     * shading with Background removed.
     */
    gs_pattern2_template_t pat;
    gx_path cpath;
    gs_matrix imat;
    gs_client_color cc;
    gs_color_space cs;
    gx_device_color devc;
    int code;

    gs_pattern2_init(&pat);
    pat.Shading = psh;
    gs_make_identity(&imat);
    code = gs_make_pattern(&cc, (gs_pattern_template_t *)&pat, &imat, pgs,
			   pgs->memory);
    if (code < 0)
	return code;
    code = gs_pattern2_set_shfill(&cc);
    if (code < 0)
	return code;
    gs_cspace_init(&cs, &gs_color_space_type_Pattern, pgs->memory, false);
    cs.params.pattern.has_base_space = false;
    code = cs.type->remap_color(&cc, &cs, &devc, (gs_imager_state *)pgs,
				pgs->device, gs_color_select_texture);
    if (code >= 0) {
	gx_path_init_local(&cpath, pgs->memory);
	code = gx_cpath_to_path(pgs->clip_path, &cpath);
	if (code >= 0)
	    code = gx_fill_path(&cpath, &devc, pgs, gx_rule_winding_number,
				fixed_0, fixed_0);
	gx_path_free(&cpath, "gs_shfill");
    }
    gs_pattern_reference(&cc, -1);
    return code;
}
示例#2
0
/* Fill the current path using a specified rule. */
static int
fill_with_rule(gs_state * pgs, int rule)
{
    int code;

    /* If we're inside a charpath, just merge the current path */
    /* into the parent's path. */
    if (pgs->in_charpath)
	code = gx_path_add_char_path(pgs->show_gstate->path, pgs->path,
				     pgs->in_charpath);
    else if (gs_is_null_device(pgs->device)) {
	/* Handle separately to prevent gs_state_color_load - bug 688308. */
	gs_newpath(pgs);
	code = 0;
    } else {
	int abits, acode, rcode = 0;

	/* 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))) {
            gs_set_object_tag(pgs, GS_PATH_TAG);
	}
	else {
            gs_set_object_tag(pgs, GS_TEXT_TAG);
	}
	gx_set_dev_color(pgs);
	code = gs_state_color_load(pgs);
	if (code < 0)
	    return code;
	abits = alpha_buffer_bits(pgs);
	if (abits > 1) {
	    acode = alpha_buffer_init(pgs, pgs->fill_adjust.x,
				      pgs->fill_adjust.y, abits);
	    if (acode < 0)
		return acode;
	} else
	    acode = 0;
	code = gx_fill_path(pgs->path, pgs->dev_color, pgs, rule,
			    pgs->fill_adjust.x, pgs->fill_adjust.y);
	if (acode > 0)
	    rcode = alpha_buffer_release(pgs, code >= 0);
	if (code >= 0)
	    gs_newpath(pgs);
	if (code >= 0 && rcode < 0)
	    code = rcode;

    }
    return code;
}
示例#3
0
/* Stroke the current path */
int
gs_stroke(gs_state * pgs)
{
    int code;

    /*
     * If we're inside a charpath, just merge the current path
     * into the parent's path.
     */
    if (pgs->in_charpath) {
	if (pgs->in_charpath == cpm_true_charpath) {
	    /*
	     * A stroke inside a true charpath should do the
	     * equivalent of strokepath.
	     */
	    code = gs_strokepath(pgs);
	    if (code < 0)
		return code;
	}
	code = gx_path_add_char_path(pgs->show_gstate->path, pgs->path,
				     pgs->in_charpath);
    }
    if (gs_is_null_device(pgs->device)) {
	/* Handle separately to prevent gs_state_color_load. */
	gs_newpath(pgs);
	code = 0;
    } else {
	int abits, acode, rcode = 0;

        /* to distinguish text from vectors we hackly look at the
           target device 1 bit per component is a cache and this is
           text else it is a path */
        if (gx_device_has_color(gs_currentdevice(pgs)))
            gs_set_object_tag(pgs, GS_PATH_TAG);
        else
            gs_set_object_tag(pgs, GS_TEXT_TAG);

	/* 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))) {
            gs_set_object_tag(pgs, GS_PATH_TAG);
	}
	else {
            gs_set_object_tag(pgs, GS_TEXT_TAG);
	}
	gx_set_dev_color(pgs);
	code = gs_state_color_load(pgs);
	if (code < 0)
	    return code;
	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);
	    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);
	    gs_setlinewidth(pgs, orig_width);
	    scale_dash_pattern(pgs, 1.0 / scale);
	    if (code >= 0)
		code = gx_fill_path(&spath, pgs->dev_color, 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)
	    gs_newpath(pgs);
	if (code >= 0 && rcode < 0)
	    code = rcode;
    }
    return code;
}
示例#4
0
/* shfill */
int
gs_shfill(gs_gstate * pgs, const gs_shading_t * psh)
{
    /*
     * shfill is equivalent to filling the current clipping path (or, if
     * clipping, its bounding box) with the shading, disregarding the
     * Background if any.  In order to produce reasonable high-level output,
     * we must implement this by calling gs_fill_path.
     */
    gs_pattern2_template_t pat;
    gs_matrix imat;
    gs_client_color cc;
    gs_color_space *pcs;
    gx_device_color devc;
    int code;

    /* Must install the shading color space
       to allow check_DeviceN_component_names initialize
       the color component map.
     */
    /* Don't bother with saving the old color space, color,
       and cie_joint_caches,
       because .shfill is always called within gsave-grestore -
       see gs/lib . */
    code = gs_setcolorspace(pgs, psh->params.ColorSpace);
    if (code < 0)
        return 0;
    if (psh->params.cie_joint_caches != NULL) {
        pgs->cie_joint_caches = psh->params.cie_joint_caches;
        rc_increment(pgs->cie_joint_caches);
    }
    gs_pattern2_init(&pat);
    pat.Shading = psh;
    gs_make_identity(&imat);
    code = gs_make_pattern(&cc, (gs_pattern_template_t *)&pat, &imat, pgs,
                           pgs->memory);
    if (code < 0)
        return code;
    code = gs_pattern2_set_shfill(&cc);
    if (code < 0)
        return code;
    pcs = gs_cspace_alloc(pgs->memory, &gs_color_space_type_Pattern);
    if (pcs == NULL)
        return_error(gs_error_VMerror);

    pcs->params.pattern.has_base_space = false;
    code = pcs->type->remap_color(&cc, pcs, &devc, pgs,
                                  pgs->device, gs_color_select_texture);
    if (code >= 0) {
        gx_device *dev = pgs->device;
        bool need_path = !dev_proc(dev, dev_spec_op)(dev,
                             gxdso_pattern_shfill_doesnt_need_path, NULL, 0);

        if (need_path) {
            gx_path cpath;

            gx_path_init_local(&cpath, pgs->memory);
            code = gx_cpath_to_path(pgs->clip_path, &cpath);
            if (code >= 0)
                code = gx_fill_path(&cpath, &devc, pgs, gx_rule_winding_number,
                                    pgs->fill_adjust.x, pgs->fill_adjust.y);
            gx_path_free(&cpath, "gs_shfill");
        } else
            code = gx_fill_path(NULL, &devc, pgs, gx_rule_winding_number,
                                pgs->fill_adjust.x, pgs->fill_adjust.y);
    }
    rc_decrement_cs(pcs, "gs_shfill");
    gs_pattern_reference(&cc, -1);
    return code;
}