Esempio n. 1
0
/* Reset a px_gstate_t, initially or at the beginning of a page. */
void
px_gstate_reset(px_gstate_t *pxgs)
{	pxgs->brush.type = pxpGray;
	pxgs->brush.value.gray = 0;
	pxgs->char_angle = 0;
	pxgs->char_bold_value = 0;
	pxgs->char_scale.x = pxgs->char_scale.y = 1;
	pxgs->char_shear.x = pxgs->char_shear.y = 0;
	/* The order of transforms is arbitrary, */
	/* because the transforms are all no-ops. */
	pxgs->char_transforms[0] = pxct_rotate;
	pxgs->char_transforms[1] = pxct_shear;
	pxgs->char_transforms[2] = pxct_scale;
	pxgs->char_sub_mode = eNoSubstitution;
	pxgs->clip_mode = eNonZeroWinding;
	pxgs->color_space = eRGB;
	pxgs->palette.size = 0;
	pxgs->palette.data = 0;
	pxgs->palette_is_shared = false;
	pxgs->base_font = 0;
	/* halftone_method was set above. */
	pxgs->fill_mode = eNonZeroWinding;
	pxgs->dashed = false;
	pxgs->pen.type = pxpGray;
	pxgs->pen.value.gray = 0;
	/* temp_pattern_dict was set at allocation time. */
	gs_make_identity(&pxgs->text_ctm);
	pxgs->char_matrix_set = false;
	pxgs->symbol_map = 0;
	pxgs->writing_mode = eHorizontal;
}
Esempio n. 2
0
/*
 * Transition from stream context to text context.
 */
int
pdf_from_stream_to_text(gx_device_pdf *pdev)
{
    pdf_text_state_t *pts = pdev->text->text_state;

    gs_make_identity(&pts->out.matrix);
    pts->line_start.x = pts->line_start.y = 0;
    pts->continue_line = false; /* Not sure, probably doesn't matter. */
    pts->buffer.count_chars = 0;
    pts->buffer.count_moves = 0;
    return 0;
}
Esempio n. 3
0
/* Create a Type 0 wrapper for a CIDFont/CMap pair. */
static int
type0_from_cidfont_cmap(gs_font_type0 **ppfont0, gs_font *font,
			gs_cmap_t *pcmap, int wmode, const gs_matrix *psmat,
			gs_memory_t *mem)
{
    gs_font_type0 *font0 = (gs_font_type0 *)
	gs_font_alloc(mem, &st_gs_font_type0, &gs_font_procs_default, NULL,
		      "gs_type0_from_cidfont(font)");
    /* We allocate Encoding dynamically only for the sake of the GC. */
    uint *encoding = (uint *)
	gs_alloc_bytes(mem, sizeof(uint), "gs_type0_from_cidfont(Encoding)");
    gs_font **fdep =
	gs_alloc_struct_array(mem, 1, gs_font *, &st_gs_font_ptr_element,
			      "gs_type0_from_cidfont(FDepVector)");
    int code;

    if (font0 == 0 || encoding == 0 || fdep == 0) {
	gs_free_object(mem, fdep, "gs_type0_from_cidfont(FDepVector)");
	gs_free_object(mem, encoding, "gs_type0_from_cidfont(Encoding)");
	gs_free_object(mem, font0, "gs_type0_from_cidfont(font)");
	return_error(gs_error_VMerror);
    }
    if (psmat)
	font0->FontMatrix = *psmat;
    else
	gs_make_identity(&font0->FontMatrix);
    font0->FontType = ft_composite;
    font0->procs.init_fstack = gs_type0_init_fstack;
    font0->procs.define_font = gs_no_define_font;
    font0->procs.make_font = 0; /* not called */
    font0->procs.next_char_glyph = gs_type0_next_char_glyph;
    font0->key_name = font->key_name;
    font0->font_name = font->font_name;
    font0->data.FMapType = fmap_CMap;
    encoding[0] = 0;
    font0->data.Encoding = encoding;
    font0->data.encoding_size = 1;
    fdep[0] = font;
    font0->data.FDepVector = fdep;
    font0->data.fdep_size = 1;
    font0->data.CMap = pcmap;
    font0->data.SubsVector.data = 0;
    font0->data.SubsVector.size = 0;
    code = gs_definefont(font->dir, (gs_font *)font0);
    if (code < 0)
	return code;
    *ppfont0 = font0;
    return 0;
}
Esempio n. 4
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;
}
Esempio n. 5
0
/* 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;
}
Esempio n. 6
0
/* Build a ShadingType 1 (Function-based) shading. */
static int
build_shading_1(i_ctx_t *i_ctx_p, const ref * op, const gs_shading_params_t * pcommon,
                gs_shading_t ** ppsh, gs_memory_t *mem)
{
    gs_shading_Fb_params_t params;
    int code;
    static const float default_Domain[4] = {0, 1, 0, 1};
    ref *pmatrix;

    *(gs_shading_params_t *)&params = *pcommon;
    gs_make_identity(&params.Matrix);
    params.Function = 0;
    code = dict_floats_param_errorinfo(i_ctx_p, op, "Domain",
                                  4, params.Domain, default_Domain);
    if (code < 0)
        goto out;
    if (params.Domain[0] > params.Domain[1] || params.Domain[2] > params.Domain[3]) {
        gs_errorinfo_put_pair_from_dict(i_ctx_p, op, "Domain");
        code = gs_note_error(gs_error_rangecheck);
        goto out; /* CPSI 3017 and CET 12-14b reject un-normalised domain */
    }
    if (dict_find_string(op, "Matrix", &pmatrix) > 0 ) {
        code = read_matrix(imemory, pmatrix, &params.Matrix);
        if (code < 0) {
            gs_errorinfo_put_pair_from_dict(i_ctx_p, op, "Matrix");
            goto out;
        }
    }
    code = build_shading_function(i_ctx_p, op, &params.Function, 2, mem, params.Domain);
    if (code < 0)
        goto out;
    if (params.Function == 0) {  /* Function is required */
        code = gs_note_error(gs_error_undefined);
        gs_errorinfo_put_pair_from_dict(i_ctx_p, op, "Function");
        goto out;
    }
    code = check_indexed_vs_function(i_ctx_p, op, params.ColorSpace, params.Function);
    if (code < 0)
        goto out;
    code = gs_shading_Fb_init(ppsh, &params, mem);
 out:;
    if (code < 0 && params.Function)
        gs_free_object(mem, params.Function, "Function");
    return code;
}
Esempio n. 7
0
/* Fill in stick/arc font boilerplate. */
static void
hpgl_fill_in_stick_arc_font(gs_font_base *pfont, long unique_id)
{	/* The way the code is written requires FontMatrix = identity. */
	gs_make_identity(&pfont->FontMatrix);
	pfont->FontType = ft_user_defined;
	pfont->PaintType = 1;		/* stroked fonts */
	pfont->BitmapWidths = false;
	pfont->ExactSize = fbit_use_outlines;
	pfont->InBetweenSize = fbit_use_outlines;
	pfont->TransformedChar = fbit_use_outlines;
	pfont->procs.encode_char = hpgl_stick_arc_encode_char; /* FIX ME (void *) */
	/* p.y of the FontBBox is a guess, because of descenders. */
	/* Because of descenders, we have no real idea what the */
	/* FontBBox should be. */
	pfont->FontBBox.p.x = 0;
	pfont->FontBBox.p.y = -0.333;
	pfont->FontBBox.q.x = 0.667;
	pfont->FontBBox.q.y = 0.667;
	uid_set_UniqueID(&pfont->UID, unique_id);
	pfont->encoding_index = 1;	/****** WRONG ******/
	pfont->nearest_encoding_index = 1;	/****** WRONG ******/
}
Esempio n. 8
0
/* a transformation if one is supplied. */
static int
upath_stroke(i_ctx_t *i_ctx_p, gs_matrix *pmat, bool upath_compat)
{
    os_ptr op = osp;
    int code, npop;
    gs_matrix mat;

    if ((code = read_matrix(imemory, op, &mat)) >= 0) {
        if ((code = upath_append(op - 1, i_ctx_p, upath_compat)) >= 0) {
            if (pmat)
                *pmat = mat;
            else
                code = gs_concat(igs, &mat);
        }
        npop = 2;
    } else {
        if ((code = upath_append(op, i_ctx_p, upath_compat)) >= 0)
            if (pmat)
                gs_make_identity(pmat);
        npop = 1;
    }
    return (code < 0 ? code : npop);
}
Esempio n. 9
0
int
gs_type1_glyph_info(gs_font *font, gs_glyph glyph, const gs_matrix *pmat,
		    int members, gs_glyph_info_t *info)
{
    gs_font_type1 *const pfont = (gs_font_type1 *)font;
    gs_type1_data *const pdata = &pfont->data;
    int wmode = ((members & GLYPH_INFO_WIDTH1) != 0);
    int piece_members = members & (GLYPH_INFO_NUM_PIECES | GLYPH_INFO_PIECES);
    int width_members = (members & ((GLYPH_INFO_WIDTH0 << wmode) | (GLYPH_INFO_VVECTOR0 << wmode)));
    int default_members = members & ~(piece_members | GLYPH_INFO_WIDTHS |
				     GLYPH_INFO_VVECTOR0 | GLYPH_INFO_VVECTOR1 |
				     GLYPH_INFO_OUTLINE_WIDTHS);
    int code = 0;
    gs_glyph_data_t gdata;

    if (default_members) {
	code = gs_default_glyph_info(font, glyph, pmat, default_members, info);

	if (code < 0)
	    return code;
    } else
	info->members = 0;

    if (default_members == members)
	return code;		/* all done */

    gdata.memory = pfont->memory;
    if ((code = pdata->procs.glyph_data(pfont, glyph, &gdata)) < 0)
	return code;		/* non-existent glyph */

    if (piece_members) {
	code = gs_type1_glyph_pieces(pfont, &gdata, members, info);
	if (code < 0)
	    return code;
	info->members |= piece_members;
    }

    if (width_members) {
	gx_path path;
	/*
	 * Interpret the CharString until we get to the [h]sbw.
	 */
	gs_imager_state gis;
	gs_type1_state cis;
	int value;

	/* Initialize just enough of the imager state. */
	if (pmat)
	    gs_matrix_fixed_from_matrix(&gis.ctm, pmat);
	else {
	    gs_matrix imat;

	    gs_make_identity(&imat);
	    gs_matrix_fixed_from_matrix(&gis.ctm, &imat);
	}
	gis.flatness = 0;
	code = gs_type1_interp_init(&cis, &gis, NULL /* no path needed */,
				    NULL, NULL, true, 0, pfont);
	if (code < 0)
	    return code;
	cis.no_grid_fitting = true;
	gx_path_init_bbox_accumulator(&path);
	cis.path = &path;
	code = pdata->interpret(&cis, &gdata, &value);
	switch (code) {
	case 0:		/* done with no [h]sbw, error */
	                /* Adobe interpreters ignore the error! */
	    info->width[wmode].x = 0;
	    info->width[wmode].y = 0;
	    info->v.x = 0;
	    info->v.y = 0;
	    break;
	default:		/* code < 0, error */
	    return code;
	case type1_result_callothersubr:	/* unknown OtherSubr */
	    return_error(gs_error_rangecheck); /* can't handle it */
	case type1_result_sbw:
	    info->width[wmode].x = fixed2float(cis.width.x);
	    info->width[wmode].y = fixed2float(cis.width.y);
	    info->v.x = fixed2float(cis.lsb.x);
	    info->v.y = fixed2float(cis.lsb.y);
	    break;
	}
	info->members |= width_members | (GLYPH_INFO_VVECTOR0 << wmode);
    }

    gs_glyph_data_free(&gdata, "gs_type1_glyph_info");
    return code;
}
Esempio n. 10
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;
}
Esempio n. 11
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;
}
Esempio n. 12
0
static int
pdf_pattern(gx_device_pdf *pdev, const gx_drawing_color *pdc,
	    const gx_color_tile *p_tile, const gx_color_tile *m_tile,
	    cos_stream_t *pcs_image, pdf_resource_t **ppres)
{
    pdf_resource_t *pres;
    int code = pdf_alloc_resource(pdev, resourcePattern, pdc->mask.id, ppres,
				  0L);
    cos_stream_t *pcos;
    cos_dict_t *pcd;
    cos_dict_t *pcd_Resources = cos_dict_alloc(pdev, "pdf_pattern(Resources)");
    const gx_color_tile *tile = (p_tile ? p_tile : m_tile);
    const gx_strip_bitmap *btile = (p_tile ? &p_tile->tbits : &m_tile->tmask);
    bool mask = p_tile == 0;
    gs_point step;
    gs_matrix smat;

    if (code < 0)
	return code;
    if (!tile_size_ok(pdev, p_tile, m_tile))
	return_error(gs_error_limitcheck);
    /*
     * We currently can't handle Patterns whose X/Y step isn't parallel
     * to the coordinate axes.
     */
    if (is_xxyy(&tile->step_matrix))
	step.x = tile->step_matrix.xx, step.y = tile->step_matrix.yy;
    else if (is_xyyx(&tile->step_matrix))
	step.x = tile->step_matrix.yx, step.y = tile->step_matrix.xy;
    else
	return_error(gs_error_rangecheck);
    if (pcd_Resources == 0)
	return_error(gs_error_VMerror);
    gs_make_identity(&smat);
    smat.xx = btile->rep_width / (pdev->HWResolution[0] / 72.0);
    smat.yy = btile->rep_height / (pdev->HWResolution[1] / 72.0);
    smat.tx = tile->step_matrix.tx / (pdev->HWResolution[0] / 72.0);
    smat.ty = tile->step_matrix.ty / (pdev->HWResolution[1] / 72.0);
    pres = *ppres;
    {
	cos_dict_t *pcd_XObject = cos_dict_alloc(pdev, "pdf_pattern(XObject)");
	char key[MAX_REF_CHARS + 3];
	cos_value_t v;

	if (pcd_XObject == 0)
	    return_error(gs_error_VMerror);
	sprintf(key, "/R%ld", pcs_image->id);
	COS_OBJECT_VALUE(&v, pcs_image);
	if ((code = cos_dict_put(pcd_XObject, (byte *)key, strlen(key), &v)) < 0 ||
	    (code = cos_dict_put_c_key_object(pcd_Resources, "/XObject",
					      COS_OBJECT(pcd_XObject))) < 0
	    )
	    return code;
    }
    if ((code = cos_dict_put_c_strings(pcd_Resources, "/ProcSet",
				       (mask ? "[/PDF/ImageB]" :
					"[/PDF/ImageC]"))) < 0)
	return code;
    cos_become(pres->object, cos_type_stream);
    pcos = (cos_stream_t *)pres->object;
    pcd = cos_stream_dict(pcos);
    if ((code = cos_dict_put_c_key_int(pcd, "/PatternType", 1)) < 0 ||
	(code = cos_dict_put_c_key_int(pcd, "/PaintType",
				       (mask ? 2 : 1))) < 0 ||
	(code = cos_dict_put_c_key_int(pcd, "/TilingType",
				       tile->tiling_type)) < 0 ||
	(code = cos_dict_put_c_key_object(pcd, "/Resources",
					  COS_OBJECT(pcd_Resources))) < 0 ||
	(code = cos_dict_put_c_strings(pcd, "/BBox", "[0 0 1 1]")) < 0 ||
	(code = cos_dict_put_matrix(pcd, "/Matrix", &smat)) < 0 ||
	(code = cos_dict_put_c_key_real(pcd, "/XStep", step.x / btile->rep_width)) < 0 ||
	(code = cos_dict_put_c_key_real(pcd, "/YStep", step.y / btile->rep_height)) < 0
	) {
	return code;
    }

    {
	char buf[MAX_REF_CHARS + 6 + 1]; /* +6 for /R# Do\n */

	sprintf(buf, "/R%ld Do\n", pcs_image->id);
	cos_stream_add_bytes(pcos, (const byte *)buf, strlen(buf));
    }

    return 0;
}
Esempio n. 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);
}
Esempio n. 14
0
static int
match_page_size(const gs_point * request, const gs_rect * medium, int policy,
		int orient, bool roll, float *best_mismatch, gs_matrix * pmat,
		gs_point * pmsize)
{
    double rx = request->x, ry = request->y;

    if ((rx <= 0) || (ry <= 0))
	return_error(e_rangecheck);
    if (policy == 7) {
		/* (Adobe) hack: just impose requested values */
	*best_mismatch = 0;
	gs_make_identity(pmat);
	*pmsize = *request;
    } else {
        int fit_direct  = rx - medium->p.x >= -5 && rx - medium->q.x <= 5 
                       && ry - medium->p.y >= -5 && ry - medium->q.y <= 5;
	int fit_rotated = rx - medium->p.y >= -5 && rx - medium->q.y <= 5 
                       && ry - medium->p.x >= -5 && ry - medium->q.x <= 5;
        
	/* Fudge matches from a non-standard page size match (4 element array) */
	/* as worse than an exact match from a standard (2 element array), but */
	/* better than for a rotated match to a standard pagesize. This should */
	/* prevent rotation unless we have to (particularly for raster file    */
	/* formats like TIFF, JPEG, PNG, PCX, BMP, etc. and also should allow  */
	/* exact page size specification when there is a range PageSize entry. */
	/* As the comment in gs_setpd.ps says "Devices that care will provide  */
	/* a real InputAttributes dictionary (most without a range pagesize)   */
        if ( fit_direct && fit_rotated) {
	    make_adjustment_matrix(request, medium, pmat, false, orient < 0 ? 0 : orient);
	    if (medium->p.x < medium->q.x || medium->p.y < medium->q.y)
		*best_mismatch = (float)0.001;		/* fudge a match to a range as a small number */
	    else	/* should be 0 for an exact match */
	        *best_mismatch = fabs((rx - medium->p.x) * (medium->q.x - rx)) +
	    			fabs((ry - medium->p.y) * (medium->q.y - ry));
        } else if ( fit_direct ) {
            int rotate = orient < 0 ? 0 : orient;

	    make_adjustment_matrix(request, medium, pmat, false, (rotate + 1) & 2);
	    *best_mismatch = fabs((medium->p.x - rx) * (medium->q.x - rx)) +
	    			fabs((medium->p.y - ry) * (medium->q.y - ry)) + 
            			    (pmat->xx == 0.0 || (rotate & 1) == 1 ? 0.01 : 0);	/* rotated */
        } else if ( fit_rotated ) {
            int rotate = (orient < 0 ? 1 : orient);

	    make_adjustment_matrix(request, medium, pmat, false, rotate | 1);
	    *best_mismatch = fabs((medium->p.y - rx) * (medium->q.y - rx)) +
	    			fabs((medium->p.x - ry) * (medium->q.x - ry)) + 
            			    (pmat->xx == 0.0 || (rotate & 1) == 1 ? 0.01 : 0);	/* rotated */
        } else {
	    int rotate =
		(orient >= 0 ? orient :
		 (rx < ry) ^ (medium->q.x < medium->q.y));
	    bool larger =
		(rotate & 1 ? medium->q.y >= rx && medium->q.x >= ry :
		 medium->q.x >= rx && medium->q.y >= ry);
	    bool adjust = false;
	    float mismatch = medium->q.x * medium->q.y - rx * ry;

	    switch (policy) {
	        default:		/* exact match only */
		    return 0;
	        case 3:		/* nearest match, adjust */
		    adjust = true;
	        case 5:		/* nearest match, don't adjust */
		    if (fabs(mismatch) >= fabs(*best_mismatch))
		        return 0;
		    break;
	        case 4:		/* next larger match, adjust */
		    adjust = true;
	        case 6:		/* next larger match, don't adjust */
		    if (!larger || mismatch >= *best_mismatch)
		        return 0;
		    break;
	    }
	    if (adjust)
	        make_adjustment_matrix(request, medium, pmat, !larger, rotate);
	    else {
	        gs_rect req_rect;
                if(rotate & 1) { 
                    req_rect.p.x = ry;
                    req_rect.p.y = rx;
                } else {
                    req_rect.p.x = rx;
                    req_rect.p.y = ry;
                }
	        req_rect.q = req_rect.p;
	        make_adjustment_matrix(request, &req_rect, pmat, false, rotate);
	    }
	    *best_mismatch = fabs(mismatch);
        }
        if (pmat->xx == 0) {	/* Swap request X and Y. */
	    double temp = rx;

	    rx = ry, ry = temp;
        }
#define ADJUST_INTO(req, mmin, mmax)\
      (req < mmin ? mmin : req > mmax ? mmax : req)
        pmsize->x = ADJUST_INTO(rx, medium->p.x, medium->q.x);
        pmsize->y = ADJUST_INTO(ry, medium->p.y, medium->q.y);
#undef ADJUST_INTO
    }
    return 1;
}
Esempio n. 15
0
/* makefont */
int
gs_makefont(gs_font_dir *pdir, const gs_font *pfont, const gs_matrix *pmat,
  gs_font **ppfont, gs_font **pdfont)
{	int code;
	gs_font *prev = 0, *pf_out = pdir->scaled_fonts;
	gs_matrix newmat;
	*pdfont = 0;
	gs_make_identity(&newmat);	/* fill in tags */
	if ( (code = gs_matrix_multiply(&pfont->FontMatrix, pmat, &newmat)) < 0 )
	  return code;
	/* Check for the font already being in the scaled font cache. */
	/* Only attempt to share fonts if the current font has */
	/* a real UniqueID (i.e., not -1). */
#ifdef DEBUG
if ( gs_debug['m'] )
   {	dprintf2("[m]UniqueID=%ld, FontType=%d,\n",
	  pfont->data.base.UniqueID, pfont->FontType);
	dprintf6("[m]  new FontMatrix=[%g %g %g %g %g %g]\n",
	  pmat->xx, pmat->xy, pmat->yx, pmat->yy,
	  pmat->tx, pmat->ty);
   }
#endif
	if ( pfont->data.base.UniqueID != -1 )
	  for ( ; pf_out != 0; prev = pf_out, pf_out = pf_out->next )
		if (	pf_out->data.base.UniqueID == pfont->data.base.UniqueID &&
			pf_out->FontType == pfont->FontType &&
			pf_out->FontMatrix.xx == newmat.xx &&
			pf_out->FontMatrix.xy == newmat.xy &&
			pf_out->FontMatrix.yx == newmat.yx &&
			pf_out->FontMatrix.yy == newmat.yy &&
			pf_out->FontMatrix.tx == newmat.tx &&
			pf_out->FontMatrix.ty == newmat.ty
		   )
		   {	*ppfont = pf_out;
			if_debug1('m', "[m]found font=%lx\n", (ulong)pf_out);
			return 0;
		   }
	pf_out = (gs_font *)(*pdir->alloc)(1, sizeof(gs_font), "gs_makefont");
	if ( !pf_out ) return_error(gs_error_VMerror);
	*pf_out = *pfont;
	pf_out->FontMatrix = newmat;
	if ( pdir->ssize == pdir->smax )
	  { /* Must discard a cached scaled font. */
	    /* Scan for the oldest font if we didn't already. */
	    if ( !prev )
	      for ( prev = pdir->scaled_fonts;
		    prev->next != 0;
		    prev = prev->next
		  ) ;
	    if_debug1('m', "[m]discarding font %lx\n", (ulong)prev);
	    *pdfont = prev;
	    prev->prev->next = 0;
	  }
	else
	  pdir->ssize++;
	link_first(pdir->scaled_fonts, pf_out);
	pf_out->base = pfont->base;
	pf_out->dir = pdir;
	*ppfont = pf_out;
	if_debug1('m', "[m]new font=%lx\n", (ulong)pf_out);
	return 1;
}
Esempio n. 16
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;
}
Esempio n. 17
0
int
xps_parse_canvas(xps_context_t *ctx, char *base_uri, xps_resource_t *dict, xps_item_t *root)
{
    xps_resource_t *new_dict = NULL;
    xps_item_t *node;
    char *opacity_mask_uri;
    int code;

    char *transform_att;
    char *clip_att;
    char *opacity_att;
    char *opacity_mask_att;

    xps_item_t *transform_tag = NULL;
    xps_item_t *clip_tag = NULL;
    xps_item_t *opacity_mask_tag = NULL;

    gs_matrix transform;

    transform_att = xps_att(root, "RenderTransform");
    clip_att = xps_att(root, "Clip");
    opacity_att = xps_att(root, "Opacity");
    opacity_mask_att = xps_att(root, "OpacityMask");

    for (node = xps_down(root); node; node = xps_next(node))
    {
        if (!strcmp(xps_tag(node), "Canvas.Resources") && xps_down(node))
        {
            code = xps_parse_resource_dictionary(ctx, &new_dict, base_uri, xps_down(node));
            if (code)
                return gs_rethrow(code, "cannot load Canvas.Resources");
            if (new_dict && new_dict != dict)
            {
                new_dict->parent = dict;
                dict = new_dict;
            }
        }

        if (!strcmp(xps_tag(node), "Canvas.RenderTransform"))
            transform_tag = xps_down(node);
        if (!strcmp(xps_tag(node), "Canvas.Clip"))
            clip_tag = xps_down(node);
        if (!strcmp(xps_tag(node), "Canvas.OpacityMask"))
            opacity_mask_tag = xps_down(node);
    }

    opacity_mask_uri = base_uri;
    xps_resolve_resource_reference(ctx, dict, &transform_att, &transform_tag, NULL);
    xps_resolve_resource_reference(ctx, dict, &clip_att, &clip_tag, NULL);
    xps_resolve_resource_reference(ctx, dict, &opacity_mask_att, &opacity_mask_tag, &opacity_mask_uri);

    gs_gsave(ctx->pgs);

    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);
    gs_concat(ctx->pgs, &transform);

    if (clip_att || clip_tag)
    {
        if (clip_att)
            xps_parse_abbreviated_geometry(ctx, clip_att);
        if (clip_tag)
            xps_parse_path_geometry(ctx, dict, clip_tag, 0);
        xps_clip(ctx);
    }

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

    for (node = xps_down(root); node; node = xps_next(node))
    {
        code = xps_parse_element(ctx, base_uri, dict, node);
        if (code)
        {
            xps_end_opacity(ctx, opacity_mask_uri, dict, opacity_att, opacity_mask_tag);
            gs_grestore(ctx->pgs);
            return gs_rethrow(code, "cannot parse child of Canvas");
        }
    }

    xps_end_opacity(ctx, opacity_mask_uri, dict, opacity_att, opacity_mask_tag);

    gs_grestore(ctx->pgs);

    if (new_dict)
        xps_free_resource_dictionary(ctx, new_dict);

    return 0;
}
Esempio n. 18
0
int
xps_init_truetype_font(xps_context_t *ctx, xps_font_t *font)
{
    font->font = (void*) gs_alloc_struct(ctx->memory, gs_font_type42, &st_gs_font_type42, "xps_font type42");
    if (!font->font)
        return gs_throw(gs_error_VMerror, "out of memory");

    /* no shortage of things to initialize */
    {
        gs_font_type42 *p42 = (gs_font_type42*) font->font;

        /* Common to all fonts: */

        p42->next = 0;
        p42->prev = 0;
        p42->memory = ctx->memory;

        p42->dir = ctx->fontdir; /* NB also set by gs_definefont later */
        p42->base = font->font; /* NB also set by gs_definefont later */
        p42->is_resource = false;
        gs_notify_init(&p42->notify_list, gs_memory_stable(ctx->memory));
        p42->id = gs_next_ids(ctx->memory, 1);

        p42->client_data = font; /* that's us */

        /* this is overwritten in grid_fit() */
        gs_make_identity(&p42->FontMatrix);
        gs_make_identity(&p42->orig_FontMatrix); /* NB ... original or zeroes? */

        p42->FontType = ft_TrueType;
        p42->BitmapWidths = false;
        p42->ExactSize = fbit_use_outlines;
        p42->InBetweenSize = fbit_use_outlines;
        p42->TransformedChar = fbit_use_outlines;
        p42->WMode = 0;
        p42->PaintType = 0;
        p42->StrokeWidth = 0;
        p42->is_cached = 0;

        p42->procs.define_font = gs_no_define_font;
        p42->procs.make_font = gs_no_make_font;
        p42->procs.font_info = gs_type42_font_info;
        p42->procs.same_font = gs_default_same_font;
        p42->procs.encode_char = xps_true_callback_encode_char;
        p42->procs.decode_glyph = xps_true_callback_decode_glyph;
        p42->procs.enumerate_glyph = gs_type42_enumerate_glyph;
        p42->procs.glyph_info = gs_type42_glyph_info;
        p42->procs.glyph_outline = gs_type42_glyph_outline;
        p42->procs.glyph_name = xps_true_callback_glyph_name;
        p42->procs.init_fstack = gs_default_init_fstack;
        p42->procs.next_char_glyph = gs_default_next_char_glyph;
        p42->procs.build_char = xps_true_callback_build_char;

        memset(p42->font_name.chars, 0, sizeof(p42->font_name.chars));
        xps_load_sfnt_name(font, (char*)p42->font_name.chars);
        p42->font_name.size = strlen((char*)p42->font_name.chars);

        memset(p42->key_name.chars, 0, sizeof(p42->key_name.chars));
        strcpy((char*)p42->key_name.chars, (char*)p42->font_name.chars);
        p42->key_name.size = strlen((char*)p42->key_name.chars);

        /* Base font specific: */

        p42->FontBBox.p.x = 0;
        p42->FontBBox.p.y = 0;
        p42->FontBBox.q.x = 0;
        p42->FontBBox.q.y = 0;

        uid_set_UniqueID(&p42->UID, p42->id);

        p42->encoding_index = ENCODING_INDEX_UNKNOWN;
        p42->nearest_encoding_index = ENCODING_INDEX_ISOLATIN1;

        p42->FAPI = 0;
        p42->FAPI_font_data = 0;

        /* Type 42 specific: */

        p42->data.string_proc = xps_true_callback_string_proc;
        p42->data.proc_data = font;

        gs_type42_font_init(p42, font->subfontid);
        p42->data.get_glyph_index = xps_true_get_glyph_index;
    }

    gs_definefont(ctx->fontdir, font->font);

    return 0;
}
Esempio n. 19
0
/* Initialize the common parts of image structures. */
void
gs_image_common_t_init(gs_image_common_t * pic)
{
    gs_make_identity(&pic->ImageMatrix);
}