Пример #1
0
/* Append a list of rectangles to a path. */
static int
gs_rectappend_compat(gs_state * pgs, const gs_rect * pr, uint count, bool clip)
{
    bool CPSI_mode = gs_currentcpsimode(pgs->memory);

    for (; count != 0; count--, pr++) {
        double px = pr->p.x, py = pr->p.y, qx = pr->q.x, qy = pr->q.y;
        int code;

        if (CPSI_mode) {
            /* We believe that the result must be independent
               on the device initial matrix.
               Particularly for the correct dashing
               the starting point and the contour direction
               must be same with any device initial matrix.
               Only way to provide it is to choose the starting point
               and the direction in the user space. */
            if (clip) {
                /* CPSI starts a clippath with the upper right corner. */
                /* Debugged with CET 11-11.PS page 6 item much13.*/
                if ((code = gs_moveto(pgs, qx, qy)) < 0 ||
                    (code = gs_lineto(pgs, qx, py)) < 0 ||
                    (code = gs_lineto(pgs, px, py)) < 0 ||
                    (code = gs_lineto(pgs, px, qy)) < 0 ||
                    (code = gs_closepath(pgs)) < 0
                    )
                    return code;
            } else {
                /* Debugged with CET 12-12.PS page 10 item more20.*/
                if (px > qx) {
                    px = qx; qx = pr->p.x;
                }
                if (py > qy) {
                    py = qy; qy = pr->p.y;
                }
                if ((code = gs_moveto(pgs, px, py)) < 0 ||
                    (code = gs_lineto(pgs, qx, py)) < 0 ||
                    (code = gs_lineto(pgs, qx, qy)) < 0 ||
                    (code = gs_lineto(pgs, px, qy)) < 0 ||
                    (code = gs_closepath(pgs)) < 0
                    )
                    return code;
            }
        } else {
            /* Ensure counter-clockwise drawing. */
            if ((qx >= px) != (qy >= py))
                qx = px, px = pr->q.x;	/* swap x values */
            if ((code = gs_moveto(pgs, px, py)) < 0 ||
                (code = gs_lineto(pgs, qx, py)) < 0 ||
                (code = gs_lineto(pgs, qx, qy)) < 0 ||
                (code = gs_lineto(pgs, px, qy)) < 0 ||
                (code = gs_closepath(pgs)) < 0
                )
                return code;
        }
    }
    return 0;
}
Пример #2
0
static int
test2(gs_state * pgs, gs_memory_t * mem)
{
    gs_client_color cc;
    gx_tile_bitmap tile;
    /*const */ byte tpdata[] =
    {
    /* Define a pattern that looks like this:
       ..xxxx
       .....x
       .....x
       ..xxxx
       .x....
       x.....
     */
        0x3c, 0, 0, 0, 0x04, 0, 0, 0, 0x04, 0, 0, 0, 0x3c, 0, 0, 0,
        0x40, 0, 0, 0, 0x80, 0, 0, 0
    };

    gs_newpath(pgs);
    gs_moveto(pgs, 100.0, 300.0);
    gs_lineto(pgs, 500.0, 500.0);
    gs_lineto(pgs, 200.0, 100.0);
    gs_lineto(pgs, 300.0, 500.0);
    gs_lineto(pgs, 500.0, 200.0);
    gs_closepath(pgs);
    gs_setrgbcolor(pgs, 0.0, 0.0, 0.0);
    gs_gsave(pgs);
    gs_fill(pgs);
    gs_grestore(pgs);
    tile.data = tpdata;
    tile.raster = 4;
    tile.size.x = tile.rep_width = 6;
    tile.size.y = tile.rep_height = 6;
    tile.id = gx_no_bitmap_id;
    gs_makebitmappattern(&cc, &tile, true, pgs, NULL);
    /* Note: color space is DeviceRGB */
    cc.paint.values[0] = 0.0;
    cc.paint.values[1] = 1.0;
    cc.paint.values[2] = 1.0;
    gs_setpattern(pgs, &cc);
    gs_eofill(pgs);
    gs_makebitmappattern(&cc, &tile, false, pgs, NULL);
    gs_setcolor(pgs, &cc);
    gs_moveto(pgs, 50.0, 50.0);
    gs_lineto(pgs, 300.0, 50.0);
    gs_lineto(pgs, 50.0, 300.0);
    gs_closepath(pgs);
    gs_setrgbcolor(pgs, 1.0, 0.0, 0.0);
    gs_gsave(pgs);
    gs_fill(pgs);
    gs_grestore(pgs);
    gs_setpattern(pgs, &cc);
    gs_eofill(pgs);
    return 0;
}
Пример #3
0
static int
xps_true_callback_build_char(gs_show_enum *penum, gs_state *pgs, gs_font *pfont,
        gs_char chr, gs_glyph glyph)
{
    gs_font_type42 *p42 = (gs_font_type42*)pfont;
    const gs_rect *pbbox;
    float sbw[4], w2[6];
    gs_fixed_point saved_adjust;
    int code;

    // dprintf1("build char ttf %d\n", glyph);

    code = gs_type42_get_metrics(p42, glyph, sbw);
    if (code < 0)
        return code;

    w2[0] = sbw[2];
    w2[1] = sbw[3];

    pbbox =  &p42->FontBBox;
    w2[2] = pbbox->p.x;
    w2[3] = pbbox->p.y;
    w2[4] = pbbox->q.x;
    w2[5] = pbbox->q.y;

    /* Expand the bbox when stroking */
    if ( pfont->PaintType )
    {
        float expand = max(1.415, gs_currentmiterlimit(pgs)) * gs_currentlinewidth(pgs) / 2;
        w2[2] -= expand, w2[3] -= expand;
        w2[4] += expand, w2[5] += expand;
    }

    if ( (code = gs_moveto(pgs, 0.0, 0.0)) < 0 )
        return code;

    if ( (code = gs_setcachedevice(penum, pgs, w2)) < 0 )
        return code;

    code = gs_type42_append(glyph, pgs,
            gx_current_path(pgs),
            (gs_text_enum_t*)penum, (gs_font*)p42,
            gs_show_in_charpath(penum) != cpm_show);
    if (code < 0)
        return code;

    /* Indicate that dropout prevention should be enabled by setting
        fill_adjust to the special value -1. */
    saved_adjust = pgs->fill_adjust;
    pgs->fill_adjust.x = -1;
    pgs->fill_adjust.y = -1;

    code = (pfont->PaintType ? gs_stroke(pgs) : gs_fill(pgs));
    if (code < 0)
        return code;

    pgs->fill_adjust = saved_adjust;

    return 0;
}
Пример #4
0
static int
test1(gs_state * pgs, gs_memory_t * mem)
{
    int n;

    gs_scale(pgs, 72.0, 72.0);
    gs_translate(pgs, 4.25, 5.5);
    gs_scale(pgs, 4.0, 4.0);
    gs_newpath(pgs);
    for (n = 200; --n >= 0;) {
        int j;

#define rf() (rand() / (1.0 * 0x10000 * 0x8000))
        double r = rf(), g = rf(), b = rf();
        double x0 = rf(), y0 = rf(), x1 = rf(), y1 = rf(), x2 = rf(), y2 = rf();

        gs_setrgbcolor(pgs, r, g, b);
        for (j = 0; j < 6; j++) {
            gs_gsave(pgs);
            gs_rotate(pgs, 60.0 * j);
            gs_moveto(pgs, x0, y0);
            gs_lineto(pgs, x1, y1);
            gs_lineto(pgs, x2, y2);
            gs_fill(pgs);
            gs_grestore(pgs);
        }
    }
#undef mem
    return 0;
}
Пример #5
0
int
xps_begin_opacity(xps_context_t *ctx, char *base_uri, xps_resource_t *dict,
        char *opacity_att, xps_item_t *opacity_mask_tag)
{
    gs_transparency_group_params_t tgp;
    gs_transparency_mask_params_t tmp;
    gs_rect bbox;
    float opacity;
    int save;
    int code;

    if (!opacity_att && !opacity_mask_tag)
        return 0;

    opacity = 1.0;
    if (opacity_att)
        opacity = atof(opacity_att);
    gs_setopacityalpha(ctx->pgs, opacity);

    xps_bounds_in_user_space(ctx, &bbox);

    if (opacity_mask_tag)
    {
        gs_trans_mask_params_init(&tmp, TRANSPARENCY_MASK_Luminosity);
        gs_begin_transparency_mask(ctx->pgs, &tmp, &bbox, 0);

        gs_gsave(ctx->pgs);

        /* Need a path to fill/clip for the brush */
        gs_moveto(ctx->pgs, bbox.p.x, bbox.p.y);
        gs_lineto(ctx->pgs, bbox.p.x, bbox.q.y);
        gs_lineto(ctx->pgs, bbox.q.x, bbox.q.y);
        gs_lineto(ctx->pgs, bbox.q.x, bbox.p.y);
        gs_closepath(ctx->pgs);

        /* opacity-only mode: use alpha value as gray color to create luminosity mask */
        save = ctx->opacity_only;
        ctx->opacity_only = 1;

        code = xps_parse_brush(ctx, base_uri, dict, opacity_mask_tag);
        if (code)
        {
            gs_grestore(ctx->pgs);
            gs_end_transparency_mask(ctx->pgs, TRANSPARENCY_CHANNEL_Opacity);
            ctx->opacity_only = save;
            return gs_rethrow(code, "cannot parse opacity mask brush");
        }

        gs_grestore(ctx->pgs);
        gs_end_transparency_mask(ctx->pgs, TRANSPARENCY_CHANNEL_Opacity);
        ctx->opacity_only = save;
    }

    gs_trans_group_params_init(&tgp);
    gs_begin_transparency_group(ctx->pgs, &tgp, &bbox);

    return 0;
}
Пример #6
0
static int
test4(gs_state * pgs, gs_memory_t * mem)
{
    gs_c_param_list list;
    float resv[2];
    gs_param_float_array ares;
    int code;
    gx_device *dev = gs_currentdevice(pgs);

    gs_c_param_list_write(&list, mem);
    resv[0] = resv[1] = 100;
    ares.data = resv;
    ares.size = 2;
    ares.persistent = true;
    code = param_write_float_array((gs_param_list *) & list,
                                   "HWResolution", &ares);
    if (code < 0) {
        lprintf1("Writing HWResolution failed: %d\n", code);
        gs_abort(mem);
    }
    gs_c_param_list_read(&list);
    code = gs_putdeviceparams(dev, (gs_param_list *) & list);
    gs_c_param_list_release(&list);
    if (code < 0) {
        lprintf1("Setting HWResolution failed: %d\n", code);
        gs_abort(mem);
    }
    gs_initmatrix(pgs);
    gs_initclip(pgs);
    if (code == 1) {
        code = (*dev_proc(dev, open_device)) (dev);
        if (code < 0) {
            lprintf1("Reopening device failed: %d\n", code);
            gs_abort(mem);
        }
    }
    gs_moveto(pgs, 0.0, 72.0);
    gs_rlineto(pgs, 72.0, 0.0);
    gs_rlineto(pgs, 0.0, 72.0);
    gs_closepath(pgs);
    gs_stroke(pgs);
    return 0;
}
Пример #7
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;
}
Пример #8
0
/* Append a list of rectangles to a path. */
int
gs_rectappend(gs_state * pgs, const gs_rect * pr, uint count)
{
    for (; count != 0; count--, pr++) {
	floatp px = pr->p.x, py = pr->p.y, qx = pr->q.x, qy = pr->q.y;
	int code;

	/* Ensure counter-clockwise drawing. */
	if ((qx >= px) != (qy >= py))
	    qx = px, px = pr->q.x;	/* swap x values */
	if ((code = gs_moveto(pgs, px, py)) < 0 ||
	    (code = gs_lineto(pgs, qx, py)) < 0 ||
	    (code = gs_lineto(pgs, qx, qy)) < 0 ||
	    (code = gs_lineto(pgs, px, qy)) < 0 ||
	    (code = gs_closepath(pgs)) < 0
	    )
	    return code;
    }
    return 0;
}
Пример #9
0
/* Add a symbol to the path. */
static int
hpgl_stick_arc_build_char(gs_show_enum *penum, gs_state *pgs, gs_font *pfont,
  gs_glyph uni_code, hpgl_font_type_t font_type)
{	
    int width;
    gs_matrix save_ctm;
    int code;

    /* we assert the font is present at this point */
    width = hpgl_stick_arc_width(uni_code, font_type);

    /* *** incorrect comment The TRM says the stick font is based on a
       32x32 unit cell, */
    /* but the font we're using here is only 15x15. */
    /* Also, per TRM 23-18, the character cell is only 2/3 the */
    /* point size. */
    gs_setcharwidth(penum, pgs, width / 1024.0 * 0.667, 0.0);
    gs_currentmatrix(pgs, &save_ctm);
    gs_scale(pgs, 1.0 / 1024.0 * .667, 1.0 / 1024.0 * .667);
    gs_moveto(pgs, 0.0, 0.0);
    code = hpgl_stick_arc_segments(pfont->memory, (void *)pgs, uni_code, font_type);
    if ( code < 0 )
	return code;
    gs_setdefaultmatrix(pgs, NULL);
    gs_initmatrix(pgs);
    /* Set predictable join and cap styles. */
    gs_setlinejoin(pgs, gs_join_round);
    gs_setmiterlimit(pgs, 2.61); /* start beveling at 45 degrees */
    gs_setlinecap(pgs, gs_cap_round);
    { 
        float pattern[1];
        gs_setdash(pgs, pattern, 0, 0);
    }
    gs_stroke(pgs);
    gs_setmatrix(pgs, &save_ctm);
    return 0;
}
Пример #10
0
/* <mark> <x0> <y0> ... <xn> <yn> .pdfinkpath - */
static int
zpdfinkpath(i_ctx_t *i_ctx_p)
{
    os_ptr optr, op = osp;
    uint count = ref_stack_counttomark(&o_stack);

    uint i, ocount;
    int code;
    double x0, y0, x1, y1, x2, y2, x3, y3, xc1, yc1, xc2, yc2, xc3, yc3;
    double len1, len2, len3, k1, k2, xm1, ym1, xm2, ym2;
    double ctrl1_x, ctrl1_y, ctrl2_x, ctrl2_y;
    const double smooth_value = 1; /* from 0..1 range */

    if (count == 0)
        return_error(e_unmatchedmark);
    if ((count & 1) == 0 || count < 3)
        return_error(e_rangecheck);

    ocount = count - 1;
    optr = op - ocount + 1;

    if ((code = real_param(optr, &x1)) < 0)
        return code;
    if ((code = real_param(optr + 1, &y1)) < 0)
        return code;
    if ((code = gs_moveto(igs, x1, y1)) < 0)
        return code;
    if (ocount == 2)
          goto pop;

    if ((code = real_param(optr + 2, &x2)) < 0)
        return code;
    if ((code = real_param(optr + 3, &y2)) < 0)
        return code;
    if (ocount == 4) {
        if((code = gs_lineto(igs, x2, y2)) < 0)
            return code;
        goto pop;
    }
    x0 = 2*x1 - x2;
    y0 = 2*y1 - y2;

    for (i = 4; i <= ocount; i += 2) {
        if (i < ocount) {
            if ((code = real_param(optr + i, &x3)) < 0)
                return code;
            if ((code = real_param(optr + i + 1, &y3)) < 0)
                return code;
        } else {
            x3 = 2*x2 - x1;
            y3 = 2*y2 - y1;
        }

        xc1 = (x0 + x1) / 2.0;
        yc1 = (y0 + y1) / 2.0;
        xc2 = (x1 + x2) / 2.0;
        yc2 = (y1 + y2) / 2.0;
        xc3 = (x2 + x3) / 2.0;
        yc3 = (y2 + y3) / 2.0;

        len1 = hypot(x1 - x0, y1 - y0);
        len2 = hypot(x2 - x1, y2 - y1);
        len3 = hypot(x3 - x2, y3 - y2);

        k1 = len1 / (len1 + len2);
        k2 = len2 / (len2 + len3);

        xm1 = xc1 + (xc2 - xc1) * k1;
        ym1 = yc1 + (yc2 - yc1) * k1;

        xm2 = xc2 + (xc3 - xc2) * k2;
        ym2 = yc2 + (yc3 - yc2) * k2;

        ctrl1_x = xm1 + (xc2 - xm1) * smooth_value + x1 - xm1;
        ctrl1_y = ym1 + (yc2 - ym1) * smooth_value + y1 - ym1;

        ctrl2_x = xm2 + (xc2 - xm2) * smooth_value + x2 - xm2;
        ctrl2_y = ym2 + (yc2 - ym2) * smooth_value + y2 - ym2;

        code = gs_curveto(igs, ctrl1_x, ctrl1_y, ctrl2_x, ctrl2_y, x2, y2);
        if (code < 0)
            return code;
        x0 = x1, x1 = x2, x2 = x3;
        y0 = y1, y1 = y2, y2 = y3;
    }
  pop:
    ref_stack_pop(&o_stack, count);
    return 0;
}
Пример #11
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;
}
Пример #12
0
int
gslt_outline_font_glyph(gs_state *pgs, gslt_font_t *xf, int gid, gslt_outline_walker_t *walk)
{
    gs_text_params_t params;
    gs_text_enum_t *textenum;
    gs_matrix matrix;
    segment *seg;
    curve_segment *cseg;

    gs_gsave(pgs);
    gs_make_identity(&matrix);
    gs_setmatrix(pgs, &matrix);
    gs_scale(pgs, 1000.0, 1000.0); /* otherwise we hit serious precision problems with fixpoint math */

    /* set gstate params */
    gs_setfont(pgs, xf->font); /* set pgs->font and invalidate existing charmatrix */
    gs_make_identity(&matrix);
    gs_setcharmatrix(pgs, &matrix); /* set the charmatrix to identity */

    /* reset the path */
    gs_newpath(pgs);
    gs_moveto(pgs, 0.0, 0.0);

    /* draw the glyph, in charpath mode */
    params.operation = TEXT_FROM_SINGLE_GLYPH | TEXT_DO_FALSE_CHARPATH | TEXT_RETURN_WIDTH;
    params.data.d_glyph = gid;
    params.size = 1;

    if (gs_text_begin(pgs, &params, xf->font->memory, &textenum) != 0)
        return gs_throw(-1, "cannot gs_text_begin()");
    if (gs_text_process(textenum) != 0)
        return gs_throw(-1, "cannot gs_text_process()");
    gs_text_release(textenum, "gslt font outline");

    /* walk the resulting path */
    seg = (segment*)pgs->path->first_subpath;
    while (seg)
    {
        switch (seg->type)
        {
        case s_start:
            walk->moveto(walk->user,
                    fixed2float(seg->pt.x) * 0.001,
                    fixed2float(seg->pt.y) * 0.001);
            break;
        case s_line:
            walk->lineto(walk->user,
                    fixed2float(seg->pt.x) * 0.001,
                    fixed2float(seg->pt.y) * 0.001);
            break;
        case s_line_close:
            walk->closepath(walk->user);
            break;
        case s_curve:
            cseg = (curve_segment*)seg;
            walk->curveto(walk->user,
                    fixed2float(cseg->p1.x) * 0.001,
                    fixed2float(cseg->p1.y) * 0.001,
                    fixed2float(cseg->p2.x) * 0.001,
                    fixed2float(cseg->p2.y) * 0.001,
                    fixed2float(seg->pt.x) * 0.001,
                    fixed2float(seg->pt.y) * 0.001);
            break;
        }
        seg = seg->next;
    }

    /* and toss it away... */
    gs_newpath(pgs);

    gs_grestore(pgs);
    return 0;
}
Пример #13
0
static int
charstring_execchar_aux(i_ctx_t *i_ctx_p, gs_text_enum_t *penum, gs_font *pfont)
{
    os_ptr op = osp;
    gs_font_base *const pbfont = (gs_font_base *) pfont;
    gs_font_type1 *const pfont1 = (gs_font_type1 *) pfont;
    const gs_type1_data *pdata;
    gs_type1exec_state cxs;
    gs_type1_state *const pcis = &cxs.cis;
    gs_rect FontBBox = pfont1->FontBBox;
    int code;

    if (penum->current_font->FontType == ft_CID_encrypted) {
        if (FontBBox.q.x <= FontBBox.p.x && FontBBox.q.y <= FontBBox.p.y) {
            gs_font_cid0 *pfcid0 = (gs_font_cid0 *)penum->current_font;

            FontBBox = pfcid0->FontBBox;
        }
    }

    pdata = &pfont1->data;
    /*
     * Any reasonable implementation would execute something like
     *    1 setmiterlimit 0 setlinejoin 0 setlinecap
     * here, but the Adobe implementations don't.
     *
     * If this is a stroked font, set the stroke width.
     */
    if (pfont->PaintType)
        gs_setlinewidth(igs, pfont->StrokeWidth);
    check_estack(3);		/* for continuations */
    /*
     * Execute the definition of the character.
     */
    if (r_is_proc(op))
        return zchar_exec_char_proc(i_ctx_p);
    /*
     * The definition must be a Type 1 CharString.
     * Note that we do not require read access: this is deliberate.
     */
    check_type(*op, t_string);
    if (r_size(op) <= max(pdata->lenIV, 0))
        return_error(e_invalidfont);
    /*
     * In order to make character oversampling work, we must
     * set up the cache before calling .type1addpath.
     * To do this, we must get the bounding box from the FontBBox,
     * and the width from the CharString or the Metrics.
     * If the FontBBox isn't valid, we can't do any of this.
     */

    if ((penum->FontBBox_as_Metrics2.x == 0 &&
         penum->FontBBox_as_Metrics2.y == 0) ||
        gs_rootfont(igs)->WMode == 0 ) {
        code = zchar_get_metrics(pbfont, op - 1, cxs.sbw);
        if (code < 0)
            return code;
        cxs.present = code;
        cxs.use_FontBBox_as_Metrics2 = false;
    }  else {  /* pass here if FontType==9,11 && WMode==1*/
        cxs.sbw[0] = penum->FontBBox_as_Metrics2.x / 2;
        cxs.sbw[1] = penum->FontBBox_as_Metrics2.y;
        cxs.sbw[2] = 0;
        cxs.sbw[3] = -penum->FontBBox_as_Metrics2.x; /* Sic! */
        cxs.use_FontBBox_as_Metrics2 = true;
        cxs.present = metricsNone;
    }
    /* Establish a current point. */
    code = gs_moveto(igs, 0.0, 0.0);
    if (code < 0)
        return code;
    code = type1_exec_init(pcis, penum, igs, pfont1);
    if (code < 0)
        return code;
    gs_type1_set_callback_data(pcis, &cxs);
    if (FontBBox.q.x > FontBBox.p.x &&
        FontBBox.q.y > FontBBox.p.y
        ) {
        /* The FontBBox appears to be valid. */
        op_proc_t exec_cont = 0;

        cxs.char_bbox = pfont1->FontBBox;
        code = type1exec_bbox(i_ctx_p, penum, &cxs, pfont, &exec_cont);
        if (code >= 0 && exec_cont != 0)
            code = (*exec_cont)(i_ctx_p);
        return code;
    } else {
        /* The FontBBox is not valid */
        const ref *opstr = op;
        ref other_subr;
        const gs_matrix * pctm = &ctm_only(igs);

        /* First, check for singular CTM */
        if (pctm->xx * pctm->yy == pctm->xy * pctm->yx) {
           /* The code below won't be able to find the FontBBox but we
            * don't need it anyway. Set an empty box and consider it valid.
            */
            op_proc_t exec_cont = 0;

            cxs.char_bbox.p.x = 0;
            cxs.char_bbox.p.y = 0;
            cxs.char_bbox.q.x = 0;
            cxs.char_bbox.q.y = 0;
            code = type1exec_bbox(i_ctx_p, penum, &cxs, pfont, &exec_cont);
            if (code >= 0 && exec_cont != 0)
                code = (*exec_cont)(i_ctx_p);
            return code;
        }
        /* Now we create the path first, then do the setcachedevice.
         * If we are oversampling (in this case, only for anti-
         * aliasing, not just to improve quality), we have to
         * create the path twice, since we can't know the
         * oversampling factor until after setcachedevice.
         */
        switch (cxs.present) {
            case metricsSideBearingAndWidth: {
                gs_point pt;

                pt.x = cxs.sbw[0], pt.y = cxs.sbw[1];
                gs_type1_set_lsb(pcis, &pt);
            }
            /* fall through */
            case metricsWidthOnly: {
                gs_point pt;

                pt.x = cxs.sbw[2], pt.y = cxs.sbw[3];
                gs_type1_set_width(pcis, &pt);
            }
        }

        /* Continue interpreting. */
      icont:
        code = type1_continue_dispatch(i_ctx_p, &cxs, opstr, &other_subr, 4);
        op = osp;		/* OtherSubrs might change it */
        switch (code) {
            case 0:		/* all done */
                return nobbox_finish(i_ctx_p, &cxs);
            default:		/* code < 0, error */
                return code;
            case type1_result_callothersubr:	/* unknown OtherSubr */
                return type1_call_OtherSubr(i_ctx_p, &cxs, nobbox_continue,
                                            &other_subr);
            case type1_result_sbw:	/* [h]sbw, just continue */
                switch (cxs.present) {
                    case metricsNone:
                        cxs.sbw[0] = fixed2float(pcis->lsb.x);
                        cxs.sbw[1] = fixed2float(pcis->lsb.y);
                    /* fall through */
                    case metricsWidthOnly:
                        cxs.sbw[2] = fixed2float(pcis->width.x);
                        cxs.sbw[3] = fixed2float(pcis->width.y);
                }
                opstr = 0;
                goto icont;
        }
    }
}
Пример #14
0
/* in x-then-y scan order; if detect is false, actually draw the outline. */
static int
trace_from(register status * out, int x0, int y0, int detect)
{
    int x = x0, y = y0;
    int dx = -1, dy = 0;	/* initially going west */
    int part = 0;		/* how far along edge we are; */

    /* initialized only to pacify gcc */
    int code;

    if (!detect) {
	part = (get_pixel(out, x + 1, y - 1) ?
		outline_scale - step : step);
	code = gs_moveto(out->pgs,
			 x + 1 - part / (float)outline_scale,
			 (float)y);
	if (code < 0)
	    return code;
    }
    while (1) {			/* Relative to the current direction, */
	/* -dy,dx is at +90 degrees (counter-clockwise); */
	/* tx,ty is at +45 degrees; */
	/* ty,-tx is at -45 degrees (clockwise); */
	/* dy,-dx is at -90 degrees. */
	int tx = dx - dy, ty = dy + dx;

	if (get_pixel(out, x + tx, y + ty)) {	/* Cell at 45 degrees is full, */
	    /* go counter-clockwise. */
	    if (!detect) {	/* If this is a 90 degree corner set at a */
		/* 45 degree angle, avoid backtracking. */
		if (out->dx == ty && out->dy == -tx) {
#define half_scale (outline_scale / 2 - step)
		    out->count -= half_scale;
		    add_deltas(out, tx, ty, outline_scale / 2);
#undef half_scale
		} else {
		    add_deltas(out, dx, dy, step - part);
		    add_deltas(out, tx, ty, outline_scale - step);
		}
		part = outline_scale - step;
	    }
	    x += tx, y += ty;
	    dx = -dy, dy += tx;
	} else if (!get_pixel(out, x + dx, y + dy)) {	/* Cell straight ahead is empty, go clockwise. */
	    if (!detect) {
		add_deltas(out, dx, dy, outline_scale - step - part);
		add_deltas(out, ty, -tx, step);
		part = step;
	    }
	    dx = dy, dy -= ty;
	} else {		/* Neither of the above, go in same direction. */
	    if (!detect) {
		add_deltas(out, dx, dy, outline_scale);
	    }
	    x += dx, y += dy;
	}
	if (dx == -step && dy == 0 && !(tx == -step && ty == -step)) {	/* We just turned a corner and are going west, */
	    /* so the previous pixel is a starting point pixel. */
	    if (x == x0 && y == y0)
		return 0;
	    if (detect && (y > y0 || (y == y0 && x > x0)))
		return 1;
	}
    }
}
Пример #15
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;
}
Пример #16
0
int
pxSetCursor(px_args_t *par, px_state_t *pxs)
{	return gs_moveto(pxs->pgs, real_value(par->pv[0], 0),
			 real_value(par->pv[0], 1));
}