Пример #1
0
int
pxSetClipIntersect(px_args_t *par, px_state_t *pxs)
{	gs_state *pgs = pxs->pgs;
	pxeClipRegion_t clip_region  = par->pv[0]->value.i;
	int code;

	check_clip_region(par, pxs);
	/*
	 * The discussion of ClipMode and ClipRegion in the published
	 * specification is confused and incorrect.  Based on testing with
	 * the LaserJet 6MP, we believe that ClipMode works just like
	 * PostScript clip and eoclip, and that ClipRegion applies only to
	 * the *current* path (i.e., support for "outside clipping" in the
	 * library is unnecessary).  If we had only known....
	 */
#if 0
	gs_setclipoutside(pgs, false);
#endif
	if ( clip_region == eExterior )
	  { /*
	     * We know clip_mode is eEvenOdd, so we can complement the
	     * region defined by the current path by just adding a
	     * rectangle that encloses the entire page.
	     */
	    gs_rect bbox;

	    code = gs_gsave(pgs);
	    if ( code < 0 )
	      return code;
	    px_initclip(pxs);
	    if ( (code = gs_clippath(pgs)) < 0 ||
		 (code = gs_pathbbox(pgs, &bbox)) < 0
	       )
	      DO_NOTHING;
	    gs_grestore(pgs);
	    if ( code < 0 ||
		 (code = gs_rectappend(pgs, &bbox, 1)) < 0
	       )
	      return code;
#ifdef CLIP_INTERSECT_EXTERIOR_REPLACES
	    px_initclip(pxs);
#endif
	  }
	code =
	  (pxs->pxgs->clip_mode == eEvenOdd ? gs_eoclip(pgs) : gs_clip(pgs));
	if ( code < 0 )
	  return code;
#if 0
	gs_setclipoutside(pgs, clip_region == eExterior);
#endif
	return gs_newpath(pgs);
}
Пример #2
0
/* This is very inefficient right now. */
int
gx_clip_to_path(gs_state * pgs)
{
    gs_fixed_rect bbox;
    int code;

    if ((code = gx_path_bbox(pgs->path, &bbox)) < 0 ||
	(code = gx_clip_to_rectangle(pgs, &bbox)) < 0 ||
	(code = gs_clip(pgs)) < 0
	)
	return code;
    note_set_clip_path(pgs);
    return 0;
}
Пример #3
0
/* Clip to a list of rectangles. */
int
gs_rectclip(gs_state * pgs, const gs_rect * pr, uint count)
{
    int code;
    gx_path save;

    gx_path_init_local(&save, pgs->memory);
    gx_path_assign_preserve(&save, pgs->path);
    gs_newpath(pgs);
    if ((code = gs_rectappend_compat(pgs, pr, count, true)) < 0 ||
        (code = gs_clip(pgs)) < 0
        ) {
        gx_path_assign_free(pgs->path, &save);
        return code;
    }
    gx_path_free(&save, "gs_rectclip");
    gs_newpath(pgs);
    return 0;
}
Пример #4
0
static int
xps_paint_tiling_brush_clipped(struct tile_closure_s *c)
{
    xps_context_t *ctx = c->ctx;
    int code;

    gs_moveto(ctx->pgs, c->viewbox.p.x, c->viewbox.p.y);
    gs_lineto(ctx->pgs, c->viewbox.p.x, c->viewbox.q.y);
    gs_lineto(ctx->pgs, c->viewbox.q.x, c->viewbox.q.y);
    gs_lineto(ctx->pgs, c->viewbox.q.x, c->viewbox.p.y);
    gs_closepath(ctx->pgs);
    gs_clip(ctx->pgs);
    gs_newpath(ctx->pgs);

    code = c->func(c->ctx, c->base_uri, c->dict, c->tag, c->user);
    if (code < 0)
        return gs_rethrow(code, "cannot draw clipped tile");

    return 0;
}
Пример #5
0
/* - clip - */
static int
zclip(i_ctx_t *i_ctx_p)
{
    return gs_clip(igs);
}
Пример #6
0
int
xps_parse_tiling_brush(xps_context_t *ctx, char *base_uri, xps_resource_t *dict, xps_item_t *root,
    int (*func)(xps_context_t*, char*, xps_resource_t*, xps_item_t*, void*), void *user)
{
    xps_item_t *node;
    int code;

    char *opacity_att;
    char *transform_att;
    char *viewbox_att;
    char *viewport_att;
    char *tile_mode_att;
    /*char *viewbox_units_att;*/
    /*char *viewport_units_att;*/

    xps_item_t *transform_tag = NULL;

    gs_matrix transform;
    gs_rect viewbox;
    gs_rect viewport;
    float scalex, scaley;
    int tile_mode;

    opacity_att = xps_att(root, "Opacity");
    transform_att = xps_att(root, "Transform");
    viewbox_att = xps_att(root, "Viewbox");
    viewport_att = xps_att(root, "Viewport");
    tile_mode_att = xps_att(root, "TileMode");
    /*viewbox_units_att = xps_att(root, "ViewboxUnits");*/
    /*viewport_units_att = xps_att(root, "ViewportUnits");*/

    for (node = xps_down(root); node; node = xps_next(node))
    {
        if (!strcmp(xps_tag(node), "ImageBrush.Transform"))
            transform_tag = xps_down(node);
        if (!strcmp(xps_tag(node), "VisualBrush.Transform"))
            transform_tag = xps_down(node);
    }

    xps_resolve_resource_reference(ctx, dict, &transform_att, &transform_tag, NULL);

    gs_make_identity(&transform);
    if (transform_att)
        xps_parse_render_transform(ctx, transform_att, &transform);
    if (transform_tag)
        xps_parse_matrix_transform(ctx, transform_tag, &transform);

    viewbox.p.x = 0.0; viewbox.p.y = 0.0;
    viewbox.q.x = 1.0; viewbox.q.y = 1.0;
    if (viewbox_att)
        xps_parse_rectangle(ctx, viewbox_att, &viewbox);

    viewport.p.x = 0.0; viewport.p.y = 0.0;
    viewport.q.x = 1.0; viewport.q.y = 1.0;
    if (viewport_att)
        xps_parse_rectangle(ctx, viewport_att, &viewport);

    /* some sanity checks on the viewport/viewbox size */
    if (fabs(viewport.q.x - viewport.p.x) < 0.01) { gs_warn("skipping tile with zero width view port"); return 0; }
    if (fabs(viewport.q.y - viewport.p.y) < 0.01) { gs_warn("skipping tile with zero height view port"); return 0; }
    if (fabs(viewbox.q.x - viewbox.p.x) < 0.01) { gs_warn("skipping tile with zero width view box"); return 0; }
    if (fabs(viewbox.q.y - viewbox.p.y) < 0.01) { gs_warn("skipping tile with zero height view box"); return 0; }

    scalex = (viewport.q.x - viewport.p.x) / (viewbox.q.x - viewbox.p.x);
    scaley = (viewport.q.y - viewport.p.y) / (viewbox.q.y - viewbox.p.y);

    tile_mode = TILE_NONE;
    if (tile_mode_att)
    {
        if (!strcmp(tile_mode_att, "None"))
            tile_mode = TILE_NONE;
        if (!strcmp(tile_mode_att, "Tile"))
            tile_mode = TILE_TILE;
        if (!strcmp(tile_mode_att, "FlipX"))
            tile_mode = TILE_FLIP_X;
        if (!strcmp(tile_mode_att, "FlipY"))
            tile_mode = TILE_FLIP_Y;
        if (!strcmp(tile_mode_att, "FlipXY"))
            tile_mode = TILE_FLIP_X_Y;
    }

    gs_gsave(ctx->pgs);

    code = xps_begin_opacity(ctx, base_uri, dict, opacity_att, NULL, false, false);
    if (code)
    {
        gs_grestore(ctx->pgs);
        return gs_rethrow(code, "cannot create transparency group");
    }

    /* TODO(tor): check viewport and tiling to see if we can set it to TILE_NONE */

    if (tile_mode != TILE_NONE)
    {
        struct tile_closure_s closure;

        gs_client_pattern gspat;
        gs_client_color gscolor;
        gs_color_space *cs;
        bool sa;

        closure.ctx = ctx;
        closure.base_uri = base_uri;
        closure.dict = dict;
        closure.tag = root;
        closure.tile_mode = tile_mode;
        closure.user = user;
        closure.func = func;

        closure.viewbox.p.x = viewbox.p.x;
        closure.viewbox.p.y = viewbox.p.y;
        closure.viewbox.q.x = viewbox.q.x;
        closure.viewbox.q.y = viewbox.q.y;

        gs_pattern1_init(&gspat);
        uid_set_UniqueID(&gspat.uid, gs_next_ids(ctx->memory, 1));
        gspat.PaintType = 1;
        gspat.TilingType = 2;
        gspat.PaintProc = xps_remap_pattern;
        gspat.client_data = &closure;

        /* We need to know if this tiling brush includes transparency.
           We could do a proper scan, but for now we'll be lazy and just look
           at the flag from scanning the page. */
        gspat.uses_transparency = ctx->has_transparency;

        gspat.XStep = viewbox.q.x - viewbox.p.x;
        gspat.YStep = viewbox.q.y - viewbox.p.y;
        gspat.BBox.p.x = viewbox.p.x;
        gspat.BBox.p.y = viewbox.p.y;
        gspat.BBox.q.x = viewbox.q.x;
        gspat.BBox.q.y = viewbox.q.y;

        if (tile_mode == TILE_FLIP_X || tile_mode == TILE_FLIP_X_Y)
        {
            gspat.BBox.q.x += gspat.XStep;
            gspat.XStep *= 2;
        }

        if (tile_mode == TILE_FLIP_Y || tile_mode == TILE_FLIP_X_Y)
        {
            gspat.BBox.q.y += gspat.YStep;
            gspat.YStep *= 2;
        }

        gs_matrix_translate(&transform, viewport.p.x, viewport.p.y, &transform);
        gs_matrix_scale(&transform, scalex, scaley, &transform);
        gs_matrix_translate(&transform, -viewbox.p.x, -viewbox.p.y, &transform);

        cs = ctx->srgb;
        gs_setcolorspace(ctx->pgs, cs);
        gsicc_profile_reference(cs->cmm_icc_profile_data, 1);

        sa = gs_currentstrokeadjust(ctx->pgs);
        gs_setstrokeadjust(ctx->pgs, false);
        gs_makepattern(&gscolor, &gspat, &transform, ctx->pgs, NULL);
        gs_setpattern(ctx->pgs, &gscolor);
        xps_fill(ctx);
        gs_setstrokeadjust(ctx->pgs, sa);
        gsicc_profile_reference(cs->cmm_icc_profile_data, -1);

        /* gs_makepattern increments the pattern count stored in the color
         * structure. We will discard the color struct (its on the stack)
         * so we need to decrement the reference before we throw away
         * the structure.
         */
        gs_pattern_reference(&gscolor, -1);
    }
    else
    {
        xps_clip(ctx);

        gs_concat(ctx->pgs, &transform);

        gs_translate(ctx->pgs, viewport.p.x, viewport.p.y);
        gs_scale(ctx->pgs, scalex, scaley);
        gs_translate(ctx->pgs, -viewbox.p.x, -viewbox.p.y);

        gs_moveto(ctx->pgs, viewbox.p.x, viewbox.p.y);
        gs_lineto(ctx->pgs, viewbox.p.x, viewbox.q.y);
        gs_lineto(ctx->pgs, viewbox.q.x, viewbox.q.y);
        gs_lineto(ctx->pgs, viewbox.q.x, viewbox.p.y);
        gs_closepath(ctx->pgs);
        gs_clip(ctx->pgs);
        gs_newpath(ctx->pgs);

        code = func(ctx, base_uri, dict, root, user);
        if (code < 0)
        {
            xps_end_opacity(ctx, base_uri, dict, opacity_att, NULL);
            gs_grestore(ctx->pgs);
            return gs_rethrow(code, "cannot draw tile");
        }
    }

    xps_end_opacity(ctx, base_uri, dict, opacity_att, NULL);

    gs_grestore(ctx->pgs);

    return 0;
}