예제 #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
int
gs_clippath(gs_state * pgs)
{
    gx_path cpath;
    int code;

    gx_path_init_local(&cpath, pgs->path->memory);
    code = gx_cpath_to_path(pgs->clip_path, &cpath);
    if (code >= 0) {
	code = gx_path_assign_free(pgs->path, &cpath);
	pgs->current_point.x = fixed2float(pgs->path->position.x);
	pgs->current_point.y = fixed2float(pgs->path->position.y);
	pgs->current_point_valid = true;
    }
    if (code < 0)
	gx_path_free(&cpath, "gs_clippath");
    return code;
}
예제 #3
0
int
gs_viewclippath(gs_state * pgs)
{
    gx_path cpath;
    gx_clip_path *pcpath = pgs->view_clip;
    int code;

    gx_path_init_local(&cpath, pgs->memory);
    if (pcpath == 0 || pcpath->rule == 0) {
	/* No view clip path is active: fabricate one. */
	gs_fixed_rect box;

	code = gx_default_clip_box(pgs, &box);
	if (code < 0)
	    return code;
	code = gx_path_add_rectangle(&cpath, box.p.x, box.p.y,
				     box.q.x, box.q.y);
    } else {
	code = gx_cpath_to_path(pcpath, &cpath);
    }
    if (code < 0)
	return code;
    return gx_path_assign_free(pgs->path, &cpath);
}
예제 #4
0
/*
 * Return the effective clipping path of a graphics state.  Sometimes this
 * is the intersection of the clip path and the view clip path; sometimes it
 * is just the clip path.  We aren't sure what the correct algorithm is for
 * this: for now, we use view clipping unless the current device is a memory
 * device.  This takes care of the most important case, where the current
 * device is a cache device.
 */
int
gx_effective_clip_path(gs_state * pgs, gx_clip_path ** ppcpath)
{
    gs_id view_clip_id =
	(pgs->view_clip == 0 || pgs->view_clip->rule == 0 ? gs_no_id :
	 pgs->view_clip->id);

    if (gs_device_is_memory(pgs->device)) {
	*ppcpath = pgs->clip_path;
	return 0;
    }
    if (pgs->effective_clip_id == pgs->clip_path->id &&
	pgs->effective_view_clip_id == view_clip_id
	) {
	*ppcpath = pgs->effective_clip_path;
	return 0;
    }
    /* Update the cache. */
    if (view_clip_id == gs_no_id) {
	if (!pgs->effective_clip_shared)
	    gx_cpath_free(pgs->effective_clip_path, "gx_effective_clip_path");
	pgs->effective_clip_path = pgs->clip_path;
	pgs->effective_clip_shared = true;
    } else {
	gs_fixed_rect cbox, vcbox;

	gx_cpath_inner_box(pgs->clip_path, &cbox);
	gx_cpath_outer_box(pgs->view_clip, &vcbox);
	if (rect_within(vcbox, cbox)) {
	    if (!pgs->effective_clip_shared)
		gx_cpath_free(pgs->effective_clip_path,
			      "gx_effective_clip_path");
	    pgs->effective_clip_path = pgs->view_clip;
	    pgs->effective_clip_shared = true;
	} else {
	    /* Construct the intersection of the two clip paths. */
	    int code;
	    gx_clip_path ipath;
	    gx_path vpath;
	    gx_clip_path *npath = pgs->effective_clip_path;

	    if (pgs->effective_clip_shared) {
		npath = gx_cpath_alloc(pgs->memory, "gx_effective_clip_path");
		if (npath == 0)
		    return_error(gs_error_VMerror);
	    }
	    gx_cpath_init_local(&ipath, pgs->memory);
	    code = gx_cpath_assign_preserve(&ipath, pgs->clip_path);
	    if (code < 0)
		return code;
	    gx_path_init_local(&vpath, pgs->memory);
	    code = gx_cpath_to_path(pgs->view_clip, &vpath);
	    if (code < 0 ||
		(code = gx_cpath_clip(pgs, &ipath, &vpath,
				      gx_rule_winding_number)) < 0 ||
		(code = gx_cpath_assign_free(npath, &ipath)) < 0
		)
		DO_NOTHING;
	    gx_path_free(&vpath, "gx_effective_clip_path");
	    gx_cpath_free(&ipath, "gx_effective_clip_path");
	    if (code < 0)
		return code;
	    pgs->effective_clip_path = npath;
	    pgs->effective_clip_shared = false;
	}
    }
    pgs->effective_clip_id = pgs->effective_clip_path->id;
    pgs->effective_view_clip_id = view_clip_id;
    *ppcpath = pgs->effective_clip_path;
    return 0;
}
예제 #5
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;
}