Exemple #1
0
/* <userpath> <matrix> ustrokepath - */
static int
zustrokepath(i_ctx_t *i_ctx_p)
{
    gx_path save;
    gs_matrix saved_matrix;
    int npop, code = gs_currentmatrix(igs, &saved_matrix);

    if (code < 0)
        return code;
    /* Save and reset the path. */
    gx_path_init_local(&save, imemory);
    gx_path_assign_preserve(&save, igs->path);
    if ((code = npop = upath_stroke(i_ctx_p, NULL, false)) < 0 ||
        (code = gs_strokepath(igs)) < 0
        ) {
        gx_path_assign_free(igs->path, &save);
        return code;
    }
    /*
     * If a matrix was specified then restore the previous matrix.
     */
    if (npop > 1) {
        if ((code = gs_setmatrix(igs, &saved_matrix)) < 0) {
            gx_path_assign_free(igs->path, &save);
            return code;
        }
    }
    gx_path_free(&save, "ustrokepath");
    pop(npop);
    return 0;
}
Exemple #2
0
/* <xx> <xy> <yx> <yy> <tx> <ty> .setmatrix - */
static int
zsetmatrix(i_ctx_t *i_ctx_p)
{
    os_ptr op = osp;
    gs_matrix mat;
    int code = float_params(op, 6, &mat.xx);

    if (code < 0)
        return code;
    if ((code = gs_setmatrix(igs, &mat)) < 0)
        return code;
    pop(6);
    return 0;
}
/* Common code for composite and dissolve. */
static int
composite_image(i_ctx_t *i_ctx_p, const gs_composite_alpha_params_t * params)
{
    os_ptr op = osp;
    alpha_composite_state_t cstate;
    gs_image2_t image;
    double src_rect[4];
    double dest_pt[2];
    gs_matrix save_ctm;
    int code = xywh_param(op - 4, src_rect);

    cstate.params = *params;
    gs_image2_t_init(&image);
    if (code < 0 ||
        (code = num_params(op - 1, 2, dest_pt)) < 0
        )
        return code;
    if (r_has_type(op - 3, t_null))
        image.DataSource = igs;
    else {
        check_stype(op[-3], st_igstate_obj);
        check_read(op[-3]);
        image.DataSource = igstate_ptr(op - 3);
    }
    image.XOrigin = src_rect[0];
    image.YOrigin = src_rect[1];
    image.Width = src_rect[2];
    image.Height = src_rect[3];
    image.PixelCopy = true;
    /* Compute appropriate transformations. */
    gs_currentmatrix(igs, &save_ctm);
    gs_translate(igs, dest_pt[0], dest_pt[1]);
    gs_make_identity(&image.ImageMatrix);
    if (image.DataSource == igs) {
        image.XOrigin -= dest_pt[0];
        image.YOrigin -= dest_pt[1];
    }
    code = begin_composite(i_ctx_p, &cstate);
    if (code >= 0) {
        code = process_non_source_image(i_ctx_p,
                                        (const gs_image_common_t *)&image,
                                        "composite_image");
        end_composite(i_ctx_p, &cstate);
        if (code >= 0)
            pop(8);
    }
    gs_setmatrix(igs, &save_ctm);
    return code;
}
Exemple #4
0
static int
pl_fapi_build_char(gs_show_enum * penum, gs_state * pgs, gs_font * pfont,
                   gs_char chr, gs_glyph glyph)
{
    int code;
    gs_matrix save_ctm;
    gs_font_base *pbfont = (gs_font_base *) pfont;
    pl_font_t *plfont = (pl_font_t *) pfont->client_data;
    gs_fapi_server *I = pbfont->FAPI;

    I->ff.embolden = plfont->bold_fraction;
    I->ff.is_mtx_skipped = plfont->is_xl_format;

    code =
        gs_fapi_do_char(pfont, pgs, (gs_text_enum_t *) penum, NULL, false,
                        NULL, NULL, chr, glyph, 0);

    if (code == gs_error_unknownerror) {
        gs_fapi_font tmp_ff;

        tmp_ff.fapi_set_cache = I->ff.fapi_set_cache;

        /* save the ctm */
        gs_currentmatrix(pgs, &save_ctm);

        /* magic numbers - we don't completelely understand
           the translation magic used by HP.  This provides a
           good approximation */
        gs_translate(pgs, 1.0 / 1.15, -(1.0 - 1.0 / 1.15));
        gs_rotate(pgs, 90);

        I->ff.fapi_set_cache = pl_fapi_set_cache_rotate;

        code =
            gs_fapi_do_char(pfont, pgs, (gs_text_enum_t *) penum, NULL, false,
                            NULL, NULL, chr, glyph, 0);

        I->ff.fapi_set_cache = tmp_ff.fapi_set_cache;

        gs_setmatrix(pgs, &save_ctm);
    }

    I->ff.embolden = 0;

    return (code);
}
Exemple #5
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;
}
Exemple #6
0
static int
test5(gs_state * pgs, gs_memory_t * mem)
{
    gx_device *dev = gs_currentdevice(pgs);
    gx_image_enum_common_t *info;
    gx_image_plane_t planes[5];
    gx_drawing_color dcolor;
    int code;
    static const byte data3[] =
    {
        0x00, 0x44, 0x88, 0xcc,
        0x44, 0x88, 0xcc, 0x00,
        0x88, 0xcc, 0x00, 0x44,
        0xcc, 0x00, 0x44, 0x88
    };
    gs_color_space *gray_cs = gs_cspace_new_DeviceGray(mem);

    /*
     * Neither ImageType 3 nor 4 needs a current color,
     * but some intermediate code assumes it's valid.
     */
    set_nonclient_dev_color(&dcolor, 0);

    /* Scale everything up, and fill the background. */
    {
        gs_matrix mat;

        gs_currentmatrix(pgs, &mat);
        mat.xx = gs_copysign(98.6, mat.xx);
        mat.yy = gs_copysign(98.6, mat.yy);
        mat.tx = floor(mat.tx) + 0.499;
        mat.ty = floor(mat.ty) + 0.499;
        gs_setmatrix(pgs, &mat);
    }
    gs_setrgbcolor(pgs, 1.0, 0.9, 0.9);
    fill_rect1(pgs, 0.25, 0.25, 4.0, 6.0);
    gs_setrgbcolor(pgs, 0.5, 1.0, 0.5);

#if 0
    /* Make things a little more interesting.... */
    gs_translate(pgs, 1.0, 1.0);
    gs_rotate(pgs, 10.0);
    gs_scale(pgs, 1.3, 0.9);
#endif

#define do_image(image, idata)\
  BEGIN\
  code = gx_device_begin_typed_image(dev, (gs_imager_state *)pgs, NULL,\
     (gs_image_common_t *)&image, NULL, &dcolor, NULL, mem, &info);\
  /****** TEST code >= 0 ******/\
  planes[0].data = idata;\
  planes[0].data_x = 0;\
  planes[0].raster = (image.Height * image.BitsPerComponent + 7) >> 3;\
  code = gx_image_plane_data(info, planes, image.Height);\
  /****** TEST code == 1 ******/\
  code = gx_image_end(info, true);\
  /****** TEST code >= 0 ******/\
  END

#define W 4
#define H 4

    /* Test an unmasked image. */
    gs_gsave(pgs);
    {
        gs_image1_t image1;
        void *info1;
        gs_color_space *cs;

        cs = gs_cspace_new_DeviceGray(mem);
        gs_image_t_init(&image1, cs);
        /* image */
        image1.ImageMatrix.xx = W;
        image1.ImageMatrix.yy = -H;
        image1.ImageMatrix.ty = H;
        /* data_image */
        image1.Width = W;
        image1.Height = H;
        image1.BitsPerComponent = 8;

        gs_translate(pgs, 0.5, 4.0);
        code = gx_device_begin_image(dev, (gs_imager_state *) pgs,
                                     &image1, gs_image_format_chunky,
                                     NULL, &dcolor, NULL, mem, &info1);
/****** TEST code >= 0 ******/
        planes[0].data = data3;
        planes[0].data_x = 0;
        planes[0].raster =
            (image1.Height * image1.BitsPerComponent + 7) >> 3;
        /* Use the old image_data API. */
        code = gx_image_data(info1, &planes[0].data, 0,
                             planes[0].raster, image1.Height);
/****** TEST code == 1 ******/
        code = gx_image_end(info1, true);
/****** TEST code >= 0 ******/
        gs_free_object(mem, cs, "colorspace");
    }
    gs_grestore(pgs);

    /* Test an explicitly masked image. */
    gs_gsave(pgs);
    {
        gs_image3_t image3;
        static const byte data3mask[] =
        {
            0x60,
            0x90,
            0x90,
            0x60
        };
        static const byte data3x2mask[] =
        {
            0x66,
            0x99,
            0x99,
            0x66,
            0x66,
            0x99,
            0x99,
            0x66
        };

        gs_image3_t_init(&image3, gray_cs, interleave_scan_lines);
        /* image */
        image3.ImageMatrix.xx = W;
        image3.ImageMatrix.yy = -H;
        image3.ImageMatrix.ty = H;
        /* data_image */
        image3.Width = W;
        image3.Height = H;
        image3.BitsPerComponent = 8;
        /* MaskDict */
        image3.MaskDict.ImageMatrix = image3.ImageMatrix;
        image3.MaskDict.Width = image3.Width;
        image3.MaskDict.Height = image3.Height;

        /* Display with 1-for-1 mask and image. */
        gs_translate(pgs, 0.5, 2.0);
        code = gx_device_begin_typed_image(dev, (gs_imager_state *) pgs,
                                       NULL, (gs_image_common_t *) & image3,
                                           NULL, &dcolor, NULL, mem, &info);
/****** TEST code >= 0 ******/
        planes[0].data = data3mask;
        planes[0].data_x = 0;
        planes[0].raster = (image3.MaskDict.Height + 7) >> 3;
        planes[1].data = data3;
        planes[1].data_x = 0;
        planes[1].raster =
            (image3.Height * image3.BitsPerComponent + 7) >> 3;
        code = gx_image_plane_data(info, planes, image3.Height);
/****** TEST code == 1 ******/
        code = gx_image_end(info, true);
/****** TEST code >= 0 ******/

        /* Display with 2-for-1 mask and image. */
        image3.MaskDict.ImageMatrix.xx *= 2;
        image3.MaskDict.ImageMatrix.yy *= 2;
        image3.MaskDict.ImageMatrix.ty *= 2;
        image3.MaskDict.Width *= 2;
        image3.MaskDict.Height *= 2;
        gs_translate(pgs, 1.5, 0.0);
        code = gx_device_begin_typed_image(dev, (gs_imager_state *) pgs,
                                       NULL, (gs_image_common_t *) & image3,
                                           NULL, &dcolor, NULL, mem, &info);
/****** TEST code >= 0 ******/
        planes[0].data = data3x2mask;
        planes[0].raster = (image3.MaskDict.Width + 7) >> 3;
        {
            int i;

            for (i = 0; i < H; ++i) {
                planes[1].data = 0;
                code = gx_image_plane_data(info, planes, 1);
                planes[0].data += planes[0].raster;
/****** TEST code == 0 ******/
                planes[1].data = data3 + i * planes[1].raster;
                code = gx_image_plane_data(info, planes, 1);
                planes[0].data += planes[0].raster;
/****** TEST code >= 0 ******/
            }
        }
/****** TEST code == 1 ******/
        code = gx_image_end(info, true);
/****** TEST code >= 0 ******/
    }
    gs_grestore(pgs);

    /* Test a chroma-keyed masked image. */
    gs_gsave(pgs);
    {
        gs_image4_t image4;
        const byte *data4 = data3;

        gs_image4_t_init(&image4, gray_cs);
        /* image */
        image4.ImageMatrix.xx = W;
        image4.ImageMatrix.yy = -H;
        image4.ImageMatrix.ty = H;
        /* data_image */
        image4.Width = W;
        image4.Height = H;
        image4.BitsPerComponent = 8;

        /* Display with a single mask color. */
        gs_translate(pgs, 0.5, 0.5);
        image4.MaskColor_is_range = false;
        image4.MaskColor[0] = 0xcc;
        do_image(image4, data4);

        /* Display a second time with a color range. */
        gs_translate(pgs, 1.5, 0.0);
        image4.MaskColor_is_range = true;
        image4.MaskColor[0] = 0x40;
        image4.MaskColor[1] = 0x90;
        do_image(image4, data4);
    }
    gs_grestore(pgs);
    gs_free_object(mem, gray_cs, "test5 gray_cs");
#undef W
#undef H
#undef do_image
    return 0;
}
Exemple #7
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;
}
Exemple #8
0
static int
pl_fapi_char_metrics(const pl_font_t * plfont, const void *vpgs,
                     gs_char char_code, float metrics[4])
{
    int code = 0;
    gs_text_enum_t penum1;
    gs_font *pfont = plfont->pfont;
    gs_font_base *pbfont = (gs_font_base *) pfont;
    gs_text_params_t text;
    gs_char buf[2];
    gs_state *rpgs = (gs_state *) vpgs;
    /* NAFF: undefined glyph would be better handled inside FAPI */
    gs_char chr = char_code;
    gs_glyph unused_glyph = gs_no_glyph;
    gs_glyph glyph;
    gs_matrix mat = {72.0, 0.0, 0.0, 72.0, 0.0, 0.0};
    gs_matrix fmat;
    gs_fapi_font tmp_ff;

    if (pfont->FontType == ft_MicroType) {
        glyph = char_code;
    } else {
        glyph = pl_tt_encode_char(pfont, chr, unused_glyph);
    }

    if (pfont->WMode & 1) {
        gs_glyph vertical = pl_font_vertical_glyph(glyph, plfont);

        if (vertical != gs_no_glyph)
            glyph = vertical;
    }

    /* undefined character */
    if (glyph == 0xffff || glyph == gs_no_glyph) {
        metrics[0] = metrics[1] = metrics[2] = metrics[3] = 0;
        code = 1;
    } else {
        gs_fapi_server *I = pbfont->FAPI;
        gs_state lpgs;
        gs_state *pgs = &lpgs;

        /* This is kind of naff, but it's *much* cheaper to copy
         * the parts of the gstate we need, than gsave/grestore
         */
        memset(pgs, 0x00, sizeof(lpgs));
        pgs->is_gstate = rpgs->is_gstate;
        pgs->memory = rpgs->memory;
        pgs->ctm = rpgs->ctm;
        pgs->in_cachedevice = CACHE_DEVICE_NOT_CACHING;
        pgs->device = rpgs->device;
        pgs->log_op = rpgs->log_op;
        *(pgs->color) = *(rpgs->color);

        tmp_ff.fapi_set_cache = I->ff.fapi_set_cache;
        I->ff.fapi_set_cache = pl_fapi_set_cache_metrics;

        gs_setmatrix(pgs, &mat);
        fmat = pfont->FontMatrix;
        pfont->FontMatrix = pfont->orig_FontMatrix;
        (void)gs_setfont(pgs, pfont);

        I->ff.is_mtx_skipped = plfont->is_xl_format;

        buf[0] = char_code;
        buf[1] = '\0';

        text.operation = TEXT_FROM_CHARS | TEXT_DO_NONE | TEXT_RETURN_WIDTH;
        text.data.chars = buf;
        text.size = 1;

        if ((code = gs_text_enum_init(&penum1, &null_text_procs,
                             NULL, NULL, &text, pfont,
                             NULL, NULL, NULL, pfont->memory)) >= 0) {

            penum1.pis = (gs_imager_state *)pgs;

            code = gs_fapi_do_char(pfont, pgs, &penum1, plfont->font_file, false,
                        NULL, NULL, char_code, glyph, 0);

            if (code >= 0 || code == gs_error_unknownerror) {
                metrics[0] = metrics[1] = 0;
                metrics[2] = penum1.returned.total_width.x;
                metrics[3] = penum1.returned.total_width.y;
                if (code < 0)
                    code = 0;
            }
        }
        pfont->FontMatrix = fmat;

        I->ff.fapi_set_cache = tmp_ff.fapi_set_cache;
    }
    return (code);
}
Exemple #9
0
static int
pl_fapi_set_cache(gs_text_enum_t * penum, const gs_font_base * pbfont,
                  const gs_string * char_name, int cid,
                  const double pwidth[2], const gs_rect * pbbox,
                  const double Metrics2_sbw_default[4], bool * imagenow)
{
    gs_state *pgs = (gs_state *) penum->pis;
    float w2[6];
    int code = 0;
    gs_fapi_server *I = pbfont->FAPI;

    if ((penum->text.operation & TEXT_DO_DRAW) && (pbfont->WMode & 1)
        && pwidth[0] == 1.0) {
        gs_rect tmp_pbbox;
        gs_matrix save_ctm;
        const gs_matrix id_ctm = { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 };
        /* This is kind of messy, but the cache entry has already been calculated
           using the in-force matrix. The problem is that we have to call gs_setcachedevice
           with the in-force matrix, not the rotated one, so we have to recalculate the extents
           to be correct for the rotated glyph.
         */

        /* save the ctm */
        gs_currentmatrix(pgs, &save_ctm);
        gs_setmatrix(pgs, &id_ctm);

        /* magic numbers - we don't completelely understand
           the translation magic used by HP.  This provides a
           good approximation */
        gs_translate(pgs, 1.0 / 1.15, -(1.0 - 1.0 / 1.15));
        gs_rotate(pgs, 90);

        gs_transform(pgs, pbbox->p.x, pbbox->p.y, &tmp_pbbox.p);
        gs_transform(pgs, pbbox->q.x, pbbox->q.y, &tmp_pbbox.q);

        w2[0] = pwidth[0];
        w2[1] = pwidth[1];
        w2[2] = tmp_pbbox.p.x;
        w2[3] = tmp_pbbox.p.y;
        w2[4] = tmp_pbbox.q.x;
        w2[5] = tmp_pbbox.q.y;

        gs_setmatrix(pgs, &save_ctm);
    } else {
        w2[0] = pwidth[0];
        w2[1] = pwidth[1];
        w2[2] = pbbox->p.x;
        w2[3] = pbbox->p.y;
        w2[4] = pbbox->q.x;
        w2[5] = pbbox->q.y;
    }

    if (pbfont->PaintType) {
        double expand = max(1.415,
                            gs_currentmiterlimit(pgs)) *
            gs_currentlinewidth(pgs) / 2;

        w2[2] -= expand;
        w2[3] -= expand;
        w2[4] += expand;
        w2[5] += expand;
    }

    if (I->ff.embolden != 0) {
        code = gs_setcharwidth((gs_show_enum *) penum, pgs, w2[0], w2[1]);
    } else {
        if ((code = gs_setcachedevice((gs_show_enum *) penum, pgs, w2)) < 0) {
            return (code);
        }
    }

    if ((penum->text.operation & TEXT_DO_DRAW) && (pbfont->WMode & 1)
        && pwidth[0] == 1.0) {
        *imagenow = false;
        return (gs_error_unknownerror);
    }

    *imagenow = true;
    return (code);
}
Exemple #10
0
/* [CTM before Form Matrix applied] <<Form dictionary>> .beginform -
 */
static int zbeginform(i_ctx_t *i_ctx_p)
{
    os_ptr op = osp;
    gx_device *cdev = gs_currentdevice_inline(igs);
    int code;
    float BBox[4], Matrix[6];
    gs_form_template_t tmplate;
    gs_point ll, ur;
    gs_fixed_rect box;

    check_type(*op, t_dictionary);
    check_dict_read(*op);

    code = read_matrix(imemory, op - 1, &tmplate.CTM);
    if (code < 0)
        return code;

    code = dict_floats_param(imemory, op, "BBox", 4, BBox, NULL);
    if (code < 0)
        return code;
    if (code == 0)
       return_error(gs_error_undefined);
    tmplate.FormID = -1;
    tmplate.BBox.p.x = BBox[0];
    tmplate.BBox.p.y = BBox[1];
    tmplate.BBox.q.x = BBox[2];
    tmplate.BBox.q.y = BBox[3];
 
    code = dict_floats_param(imemory, op, "Matrix", 6, Matrix, NULL);
    if (code < 0)
        return code;
    if (code == 0)
       return_error(gs_error_undefined);

    tmplate.form_matrix.xx = Matrix[0];
    tmplate.form_matrix.xy = Matrix[1];
    tmplate.form_matrix.yx = Matrix[2];
    tmplate.form_matrix.yy = Matrix[3];
    tmplate.form_matrix.tx = Matrix[4];
    tmplate.form_matrix.ty = Matrix[5];

    tmplate.pcpath = igs->clip_path;
    code = dev_proc(cdev, dev_spec_op)(cdev, gxdso_form_begin,
                            &tmplate, 0);

    /* return value > 0 means the device sent us back a matrix
     * and wants the CTM set to that.
     */
    if (code > 0)
    {
        gs_setmatrix(igs, &tmplate.CTM);
        gs_distance_transform(tmplate.BBox.p.x, tmplate.BBox.p.y, &tmplate.CTM, &ll);
        gs_distance_transform(tmplate.BBox.q.x, tmplate.BBox.q.y, &tmplate.CTM, &ur);

        /* A form can legitimately have negative co-ordinates in paths
         * because it can be translated. But we always clip paths to the
         * page which (clearly) can't have negative co-ordinates. NB this
         * wouldn't be a problem if we didn't reset the CTM, but that would
         * break the form capture.
         * So here we temporarily set the clip to permit negative values,
         * fortunately this works.....
         */
        /* We choose to permit negative values of the same magnitude as the
         * positive ones.
         */

        box.p.x = float2fixed(ll.x);
        box.p.y = float2fixed(ll.y);
        box.q.x = float2fixed(ur.x);
        box.q.y = float2fixed(ur.y);

        if (box.p.x < 0) {
            if(box.p.x * -1 > box.q.x)
                box.q.x = box.p.x * -1;
        } else {
            if (fabs(ur.x) > fabs(ll.x))
                box.p.x = box.q.x * -1;
            else {
                box.p.x = float2fixed(ll.x * -1);
                box.q.x = float2fixed(ll.x);
            }
        }
        if (box.p.y < 0) {
            if(box.p.y * -1 > box.q.y)
                box.q.y = box.p.y * -1;
        } else {
            if (fabs(ur.y) > fabs(ll.y))
                box.p.y = box.q.y * -1;
            else {
                box.p.y = float2fixed(ll.y * -1);
                box.q.y = float2fixed(ll.y);
            }
        }
        /* This gets undone when we grestore after the form is executed */
        code = gx_clip_to_rectangle(igs, &box);
    }

    pop(2);
    return code;
}
Exemple #11
0
int
xps_high_level_pattern(xps_context_t *ctx)
{
    gs_matrix m;
    gs_rect bbox;
    gs_fixed_rect clip_box;
    int code;
    gx_device_color *pdc = gs_currentdevicecolor_inline(ctx->pgs);
    const gs_client_pattern *ppat = gs_getpattern(&pdc->ccolor);
    gs_pattern1_instance_t *pinst =
        (gs_pattern1_instance_t *)gs_currentcolor(ctx->pgs)->pattern;

    code = gx_pattern_cache_add_dummy_entry((gs_imager_state *)ctx->pgs,
        pinst, ctx->pgs->device->color_info.depth);
    if (code < 0)
        return code;

    code = gs_gsave(ctx->pgs);
    if (code < 0)
        return code;

    dev_proc(ctx->pgs->device, get_initial_matrix)(ctx->pgs->device, &m);
    gs_setmatrix(ctx->pgs, &m);
    code = gs_bbox_transform(&ppat->BBox, &ctm_only(ctx->pgs), &bbox);
    if (code < 0) {
        gs_grestore(ctx->pgs);
        return code;
    }
    clip_box.p.x = float2fixed(bbox.p.x);
    clip_box.p.y = float2fixed(bbox.p.y);
    clip_box.q.x = float2fixed(bbox.q.x);
    clip_box.q.y = float2fixed(bbox.q.y);
    code = gx_clip_to_rectangle(ctx->pgs, &clip_box);
    if (code < 0) {
        gs_grestore(ctx->pgs);
        return code;
    }

    {
        pattern_accum_param_s param;
        param.pinst = (void *)pinst;
        param.graphics_state = (void *)ctx->pgs;
        param.pinst_id = pinst->id;

        code = (*dev_proc(ctx->pgs->device, dev_spec_op))((gx_device *)ctx->pgs->device,
            gxdso_pattern_start_accum, &param, sizeof(pattern_accum_param_s));
    }

    if (code < 0) {
        gs_grestore(ctx->pgs);
        return code;
    }

    code = xps_paint_tiling_brush(&pdc->ccolor, ctx->pgs);
    if (code) {
        gs_grestore(ctx->pgs);
        return gs_rethrow(code, "high level pattern brush function failed");
    }

    code = gs_grestore(ctx->pgs);
    if (code < 0)
        return code;

    {
        pattern_accum_param_s param;
        param.pinst = (void *)pinst;
        param.graphics_state = (void *)ctx->pgs;
        param.pinst_id = pinst->id;

        code = (*dev_proc(ctx->pgs->device, dev_spec_op))((gx_device *)ctx->pgs->device,
            gxdso_pattern_finish_accum, &param, sizeof(pattern_accum_param_s));
    }

    return code;
}
Exemple #12
0
/*
 * Enter raster graphics mode.
 *
 * The major function of this routine is to establish the raster to device
 * space transformations. This is rather involved:
 *
 * 1. The first feature to be established is the orientation of raster space
 *    relative to page space. Three state parameters are involved in
 *    determining this orientation: the logical page orientation, the current
 *    print direction, and the raster presentation mode. These are combined
 *    in the following manner:
 *
 *        tr = (print_direction / 90) + logical_page_orientation
 *
 *        raster_rotate = (presentation_mode == 0 ? tr : tr & 0x2)
 *
 * 2. The next step is to determine the location of the origin of the raster
 *    to page transformation. Intially this origin is set at the appropriate
 *    corner of the logical page, based on the orientation determined above.
 *    The origin is then shift based on the manner in which graphics mode is
 *    entered (the mode operand):
 *
 *        If entry is IMPLICIT (i.e.: via a transfer data command rather than
 *        an enter graphics mode command), translation by the existing left
 *        graphics margin is used, in the orientation of raster space.
 *
 *        If entry is via an enter graphics mode command which specifies moving
 *        the origin to the logical page boundary (NO_SCALE_LEFT_MARG (0) or
 *        SCALE_LEFT_MARG (2)), action depends on whether or not horizontal
 *        access of print direction space and of raster space are the same:
 *
 *            if there are the same, the origin is left unchanged
 *
 *            if they are not the same, the origin is shifted 1/6" (1200 centi-
 *            points) in the positive horizontal raster space axis.
 *
 *        The latter correction is not documented by HP, and there is no clear
 *        reason why it should apply, but it has been verified to be the case
 *        for all HP products testd.
 *
 *        If entry is via an enter graphics mode command with specifies use
 *        of the current point (NO_SCALE_CUR_PT(1) or SCALE_CUR_PT(3)), the
 *        current point is transformed to raster space and its "horizontal"
 *        component is used as the new graphics margin.
 *
 *    Irrespective of how the "horizontal" component of the raster image origin
 *    is specified, the vertical component is always derived from the current
 *    addressable point, by converting the point to raster space.
 *
 * 3. Next, the scale of the raster to page space transformation is established.
 *    This depends on whether or not PCL raster scaling is to be employed.
 *    For raster scaling to be used, all of the following must hold:
 *
 *        the scale_raster flag in the PCL raster state must be set
 *        the current palette must be writable
 *        the raster source height and width must have been explicitly set
 *
 *    The scale_raster flag in the PCL raster state is normally set by the
 *    enter raster graphics command. Hence, if graphics mode is entered
 *    explicitly, the first requirement follows the behavior of the HP Color
 *    LaserJet 5/5M. The DeskJet 1600C/CM behaves differently: it will never
 *    user raster scaling if graphics mode is entered implicitly.
 *
 *    The reason for the second requirement is undoubtedly related to some
 *    backwards compatibility requirement, but is otherwise obscure. The
 *    restriction is, however, both document and uniformly applied by all
 *    HP products that support raster scaling.
 *
 *    If raster scaling is not used, the scale of raster space is determined
 *    by the ratio of the graphics resolution (set by the graphics resolution
 *    command) and unit of page space (centi-points). This factor is applied
 *    in both scan directions.
 *
 *    If scaling is employed, the situation is somewhat more complicated. It
 *    is necessary, in this case, to know which of the raster destination
 *    dimensions have been explicitly set:
 *
 *        If both dimensions are specified, the ration of these dimensions
 *        to the source raster width and height determine the raster scale.
 *
 *        If only one destination dimension is specified, the ratio of this
 *        dimension to the corresponding source dimension determins the
 *        raster scale for both dimensions; With strange interactions with 
 *        the 1200centipoint margin and rotated pages (Bug emulation).
 *
 *        If neither dimension is specified, the page printable region is
 *        transformed to raster space, the intersection of this with the
 *        positive quadrant is taken. The dimensions of the resulting region
 *        are compared with the dimensions of the source raster. The smaller
 *        of the two dest_dim / src_dim ratios is used as the ratio for 
 *        the raster scale in both dimensions (i.e.: select the largest
 *        isotropic scaling that does not cause clipping).
 *
 * 4. Finally, the extent of raster space must be determined. This is done by
 *    converting the page printable region to raster space and intersecting
 *    the result with the positive quadrant. This region is used to determine
 *    the useable source raster width and height.
 *        
 */
   int
pcl_enter_graphics_mode(
    pcl_state_t *       pcs,
    pcl_gmode_entry_t   mode
)
{
    floatp                  scale_x, scale_y;
    pcl_xfm_state_t *       pxfmst = &(pcs->xfm_state);
    pcl_raster_state_t *    prstate = &(pcs->raster_state);
    float                   gmargin_cp = (float)prstate->gmargin_cp;
    gs_point                cur_pt;
    gs_matrix               rst2lp, rst2dev, lp2rst;
    gs_rect                 print_rect;
    uint                    src_wid, src_hgt;
    int                     rot;
    int                     code = 0;
    double                  dwid, dhgt;
    int                     clip_x, clip_y;
    /*
     * Check if the raster is to be clipped fully; see rtrstst.h for details.
     * Since this is a discontinuous effect, the equality checks below
     * should be made while still in centipoints.
     */
    prstate->clip_all = ( (pcs->cap.x == pxfmst->pd_size.x) ||
                          (pcs->cap.y == pxfmst->pd_size.y)   );

    /* create to raster space to logical page space transformation */
    rot = pxfmst->lp_orient + pxfmst->print_dir;
    if (prstate->pres_mode_3)
        rot &= 0x2;
    rot = (rot - pxfmst->lp_orient) & 0x3;
    if (prstate->y_advance == -1)
        rot = (rot + 2) & 0x3;
    pcl_make_rotation(rot, pxfmst->lp_size.x, pxfmst->lp_size.y, &rst2lp);
    pcl_invert_mtx(&rst2lp, &lp2rst);

    /* convert the current point to raster space */
    cur_pt.x = (double)pcs->cap.x + adjust_pres_mode(pcs);
    cur_pt.y = (double)pcs->cap.y;
    pcl_xfm_to_logical_page_space(pcs, &cur_pt);
    gs_point_transform(cur_pt.x, cur_pt.y, &lp2rst, &cur_pt);

    /* translate the origin of the forward transformation */
    if (((int)mode & 0x1) != 0)
        gmargin_cp = cur_pt.x;
    gs_matrix_translate(&rst2lp, gmargin_cp, cur_pt.y, &rst2lp);
    prstate->gmargin_cp = gmargin_cp;

    /* isotropic scaling with missing parameter is based on clipped raster dimensions */

    /* transform the clipping window to raster space */
    get_raster_print_rect(pcs->memory, &(pxfmst->lp_print_rect), &print_rect, &rst2lp);
    dwid = print_rect.q.x - print_rect.p.x;
    dhgt = print_rect.q.y - print_rect.p.y;

    clip_x = pxfmst->lp_print_rect.p.x;  /* if neg then: */
    clip_y = pxfmst->lp_print_rect.p.y;  /* = 1200centipoints */

    /* set the matrix scale */
    if ( !prstate->scale_raster       ||
         !prstate->src_width_set      ||
         !prstate->src_height_set     ||
         (pcs->ppalet->pindexed->pfixed  && mode == IMPLICIT) ) {
        scale_x = 7200.0 / (floatp)prstate->resolution;
        scale_y = scale_x;

    } else if (prstate->dest_width_set) {
	scale_x = (floatp)prstate->dest_width_cp / (floatp)prstate->src_width;

	if ( clip_x < 0 && pxfmst->lp_orient == 3 ) { 
	    scale_y = (floatp)(prstate->dest_width_cp - clip_y ) / (floatp)prstate->src_width;
	    if ( rot == 2 && scale_y <=  2* prstate->src_width) /* empirical test 1 */
		scale_y = scale_x;   
	}
	else if ( clip_x < 0 && pxfmst->lp_orient == 1 && rot == 3 ) {
	    scale_y = (floatp)(prstate->dest_width_cp - clip_y) / (floatp)prstate->src_width;

	    if ( prstate->dest_width_cp <= 7200 )  /* empirical test 2 */
		scale_y = (floatp)(prstate->dest_width_cp + clip_y) / (floatp)prstate->src_width;
	}
	else 
	    scale_y = scale_x;

        if (prstate->dest_height_set) 
	    scale_y = (floatp)prstate->dest_height_cp / (floatp)prstate->src_height;

    } else if (prstate->dest_height_set) {    	 
	scale_x = scale_y = (floatp)prstate->dest_height_cp / (floatp)prstate->src_height;
    } else {

        /* select isotropic scaling with no clipping */
	scale_x = (floatp)dwid / (floatp)prstate->src_width;
	scale_y = (floatp)dhgt / (floatp)prstate->src_height;
        if (scale_x > scale_y)
            scale_x = scale_y;
        else
            scale_y = scale_x;
    }

    gs_matrix_scale(&rst2lp, scale_x, scale_y, &rst2lp);
    gs_matrix_multiply(&rst2lp, &(pxfmst->lp2dev_mtx), &rst2dev);

    rst2dev.tx = (double)((int)(rst2dev.tx + 0.5));
    rst2dev.ty = (double)((int)(rst2dev.ty + 0.5));
    /*
     * Set up the graphic stat for rasters. This turns out to be more difficult
     * than might first be imagined.
     *
     * One problem is that two halftones may be needed simultaneously:
     *
     *     the foreground CRD and halftone, in case the current "texture" is a
     *     a solid color or an uncolored pattern
     *
     *     the palette CRD and halftone, to be used in rendering the raster
     *     itself
     *
     * Since the graphic state can only hold one CRD and one halftone method
     * at a time, this presents a bit of a problem.
     *
     * To get around the problem, an extra graphic state is necessary. Patterns
     * in the graphic library are given their own graphic state. Hence, by
     * replacing a solid color with an uncolored pattern that takes the
     * foreground value everywhere, the desired effect can be achieved. Code
     * in pcpatrn.c handles these matters.
     *
     * The second problem is a limitation in the graphic library's support of
     * CIE color spaces. These spaces require a joint cache, which is only
     * created when the color space is installed in the graphic state. However,
     * the current color space at the time a raster is rendered may need to
     * be a pattern color space, so that the proper interaction between the
     * raster and the texture generated by the pattern. To work around this
     * problem, we install the raster's color space in the current graphic
     * state, perform a gsave, then place what may be a patterned color space
     * in the new graphic state.
     */
    pcl_set_graphics_state(pcs);
    pcl_set_drawing_color(pcs, pcl_pattern_raster_cspace, 0, true);
    pcl_gsave(pcs);
    pcl_set_drawing_color(pcs, pcs->pattern_type, pcs->current_pattern_id, true);
    gs_setmatrix(pcs->pgs, &rst2dev);

    /* translate the origin of the forward transformation */
    /* tansform the clipping window to raster space; udpate source dimensions */
    get_raster_print_rect(pcs->memory, &(pxfmst->lp_print_rect), &print_rect, &rst2lp);

    /* min size is 1 pixel */
    src_wid = max(1, (uint)(floor(print_rect.q.x) - floor(print_rect.p.x)));
    src_hgt = max(1, (uint)(floor(print_rect.q.y) - floor(print_rect.p.y)));
    if (prstate->src_width_set && (src_wid > prstate->src_width))
        src_wid = prstate->src_width;
    if (prstate->src_height_set && (src_hgt > prstate->src_height))
        src_hgt = prstate->src_height;

    if (src_wid <= 0 || src_hgt <= 0) {
        pcl_grestore(pcs);
        return 1; /* hack, we want to return a non critical warning */
    }
    /* determine (conservatively) if the region of interest has been
       marked */
    pcs->page_marked = true;
    if ((code = pcl_start_raster(src_wid, src_hgt, pcs)) >= 0)
        prstate->graphics_mode = true;
    else
        pcl_grestore(pcs);
    return code;
}
Exemple #13
0
int
pxSetPageDefaultCTM(px_args_t *par, px_state_t *pxs)
{	gs_make_identity(&pxs->pxgs->text_ctm);
	return gs_setmatrix(pxs->pgs, &pxs->initial_matrix);
}