int
charstring_execchar(i_ctx_t *i_ctx_p, int font_type_mask)
{
    gs_text_enum_t *penum = op_show_find(i_ctx_p);
    gs_font *pfont;
    os_ptr op = osp;
    int code = font_param(op - 3, &pfont);

    if (code < 0)
        return code;
    if (penum == 0 ||
        pfont->FontType >= sizeof(font_type_mask) * 8 ||
        !(font_type_mask & (1 << (int)pfont->FontType)))
        return_error(e_undefined);
    code = charstring_execchar_aux(i_ctx_p, penum, pfont);
    if (code < 0 && igs->in_cachedevice == CACHE_DEVICE_CACHING) {
        /* Perform the cache cleanup, when the cached character data
           has been allocated (gx_alloc_char_bits) but
           the character has not been added to the cache (gx_add_cached_char)
           due to a falure in the character renderer.
         */
        gs_show_enum *const penum_s = (gs_show_enum *)penum;

        if (penum_s->cc != NULL) {
            gx_free_cached_char(pfont->dir, penum_s->cc);
            penum_s->cc = NULL;
        }
    }
    return code;
}
/* Make a transformed font (common code for makefont/scalefont). */
static int
make_font(i_ctx_t *i_ctx_p, const gs_matrix * pmat)
{
    os_ptr op = osp;
    os_ptr fp = op - 1;
    gs_font *oldfont, *newfont;
    int code;
    ref *pencoding = 0;

    code = font_param(fp, &oldfont);
    if (code < 0)
        return code;
    {
        uint space = ialloc_space(idmemory);

        ialloc_set_space(idmemory, r_space(fp));
        if (dict_find_string(fp, "Encoding", &pencoding) > 0 &&
            !r_is_array(pencoding)
            )
            code = gs_note_error(e_invalidfont);
        else {
                /*
                 * Temporarily substitute the new dictionary
                 * for the old one, in case the Encoding changed.
                 */
            ref olddict;

            olddict = *pfont_dict(oldfont);
            *pfont_dict(oldfont) = *fp;
            code = gs_makefont(ifont_dir, oldfont, pmat, &newfont);
            *pfont_dict(oldfont) = olddict;
        }
        ialloc_set_space(idmemory, space);
    }
    if (code < 0)
        return code;
    /*
     * We have to allow for the possibility that the font's Encoding
     * is different from that of the base font.  Note that the
     * font_data of the new font was simply copied from the old one.
     */
    if (pencoding != 0 &&
        !obj_eq(imemory, pencoding, &pfont_data(newfont)->Encoding)
        ) {
        if (newfont->FontType == ft_composite)
            return_error(e_rangecheck);
        /* We should really do validity checking here.... */
        ref_assign(&pfont_data(newfont)->Encoding, pencoding);
        lookup_gs_simple_font_encoding((gs_font_base *) newfont);
    }
    *fp = *pfont_dict(newfont);
    pop(1);
    return 0;
}
/* <font> setfont - */
int
zsetfont(i_ctx_t *i_ctx_p)
{
    os_ptr op = osp;
    gs_font *pfont;
    int code = font_param(op, &pfont);

    if (code < 0 || (code = gs_setfont(igs, pfont)) < 0)
        return code;
    pop(1);
    return code;
}
/* <font> .registerfont - */
static int
zregisterfont(i_ctx_t *i_ctx_p)
{
    os_ptr op = osp;
    gs_font *pfont;
    int code = font_param(op, &pfont);

    if (code < 0)
        return code;
    pfont->is_resource = true;
    pop(1);
    return 0;
}
/* <cid9font> <cid> .type9mapcid <charstring> <font_index> */
int
ztype9mapcid(i_ctx_t *i_ctx_p)
{
    os_ptr op = osp;
    gs_font *pfont;
    gs_font_cid0 *pfcid;
    int code = font_param(op - 1, &pfont);
    gs_glyph_data_t gdata;
    int fidx;

    if (code < 0)
        return code;
    if (pfont->FontType != ft_CID_encrypted)
        return_error(e_invalidfont);
    check_type(*op, t_integer);
    pfcid = (gs_font_cid0 *)pfont;
    gdata.memory = pfont->memory;
    code = pfcid->cidata.glyph_data((gs_font_base *)pfcid,
                        (gs_glyph)(gs_min_cid_glyph + op->value.intval),
                                    &gdata, &fidx);

    /* return code; original error-sensitive & fragile code */
    if (code < 0) { /* failed to load glyph data, put CID 0 */
       int default_fallback_CID = 0 ;

       if_debug2('J', "[J]ztype9cidmap() use CID %d instead of glyph-missing CID %d\n", default_fallback_CID, op->value.intval);

       op->value.intval = default_fallback_CID;

       /* reload glyph for default_fallback_CID */

       code = pfcid->cidata.glyph_data((gs_font_base *)pfcid,
                    (gs_glyph)(gs_min_cid_glyph + default_fallback_CID),
                                   &gdata, &fidx);

       if (code < 0) {
           if_debug1('J', "[J]ztype9cidmap() could not load default glyph (CID %d)\n", op->value.intval);
           return_error(e_invalidfont);
       }

    }

    /****** FOLLOWING IS NOT GENERAL W.R.T. ALLOCATION OF GLYPH DATA ******/
    make_const_string(op - 1,
                      a_readonly | imemory_space((gs_ref_memory_t *)pfont->memory),
                      gdata.bits.size,
                      gdata.bits.data);
    make_int(op, fidx);
    return code;
}
Exemple #6
0
/* <file> <cid9font> .writefont9 - */
static int
zwritefont9(i_ctx_t *i_ctx_p)
{
    os_ptr op = osp;
    gs_font *pfont;
    gs_font_cid0 *pfcid;
    int code = font_param(op, &pfont);
    stream *s;

    if (code < 0)
	return code;
    if (pfont->FontType != ft_CID_encrypted)
	return_error(e_invalidfont);
    check_write_file(s, op - 1);
    pfcid = (gs_font_cid0 *)pfont;
    code = psf_write_cid0_font(s, pfcid,
			       WRITE_TYPE2_NO_LENIV | WRITE_TYPE2_CHARSTRINGS,
			       NULL, 0, NULL);
    if (code >= 0)
	pop(2);
    return code;
}
Exemple #7
0
/*   <bitmap> <cid> <type32font> <str22> .makeglyph32 <<same with substr>> */
static int
zmakeglyph32(i_ctx_t *i_ctx_p)
{
    os_ptr op = osp;
    bool long_form;
    uint msize;
    double metrics[10];
    int wx, llx, lly, urx, ury;
    int width, height, raster;
    gs_font *pfont;
    int code;
    byte *str;

    check_array(op[-4]);
    msize = r_size(op - 4);
    switch (msize) {
        case 10:
            long_form = true;
            break;
        case 6:
            long_form = false;
            break;
        default:
            return_error(gs_error_rangecheck);
    }
    code = num_params(op[-4].value.refs + msize - 1, msize, metrics);
    if (code < 0)
        return code;
    if (~code & 0x3c)		/* check llx .. ury for integers */
        return_error(gs_error_typecheck);
    check_read_type(op[-3], t_string);
    llx = (int)metrics[2];
    lly = (int)metrics[3];
    urx = (int)metrics[4];
    ury = (int)metrics[5];
    width = urx - llx;
    height = ury - lly;
    raster = (width + 7) >> 3;
    if (width < 0 || height < 0 || r_size(op - 3) != raster * height)
        return_error(gs_error_rangecheck);
    check_int_leu(op[-2], 65535);
    code = font_param(op - 1, &pfont);
    if (code < 0)
        return code;
    if (pfont->FontType != ft_CID_bitmap)
        return_error(gs_error_invalidfont);
    check_write_type(*op, t_string);
    if (r_size(op) < 22)
        return_error(gs_error_rangecheck);
    str = op->value.bytes;
    if (long_form || metrics[0] != (wx = (int)metrics[0]) ||
        metrics[1] != 0 || height == 0 ||
        ((wx | width | height | (llx + 128) | (lly + 128)) & ~255) != 0
        ) {
        /* Use the long form. */
        int i, n = (long_form ? 10 : 6);

        str[0] = 0;
        str[1] = long_form;
        for (i = 0; i < n; ++i) {
            int v = (int)metrics[i];  /* no floating point widths yet */

            str[2 + 2 * i] = (byte)(v >> 8);
            str[2 + 2 * i + 1] = (byte)v;
        }
        r_set_size(op, 2 + n * 2);
    } else {
/*
 * Check the path against FontBBox before drawing.  The original operands
 * of type1execchar are still on the o-stack.
 * Returns exec_cont - a function, which must be called by caller after this function.
 */
static int
bbox_draw(i_ctx_t *i_ctx_p, int (*draw)(gs_state *), op_proc_t *exec_cont)
{
    os_ptr op = osp;
    gs_rect bbox;
    gs_font *pfont;
    gs_text_enum_t *penum;
    gs_font_base * pbfont;
    gs_font_type1 * pfont1;
    gs_type1exec_state cxs;
    int code;

    if (igs->in_cachedevice < 2)	/* not caching */
        return nobbox_draw(i_ctx_p, draw);
    if ((code = font_param(op - 3, &pfont)) < 0)
        return code;
    penum = op_show_find(i_ctx_p);
    if (penum == 0 || !font_uses_charstrings(pfont))
        return_error(e_undefined);
    if ((code = gs_pathbbox(igs, &bbox)) < 0) {
        /*
         * If the matrix is singular, all user coordinates map onto a
         * straight line.  Don't bother rendering the character at all.
         */
        if (code == e_undefinedresult) {
            pop(4);
            gs_newpath(igs);
            return 0;
        }
        return code;
    }
    if (draw == gs_stroke) {
        /* Expand the bounding box by the line width. */
        float width = gs_currentlinewidth(igs) * 1.41422;

        bbox.p.x -= width, bbox.p.y -= width;
        bbox.q.x += width, bbox.q.y += width;
    }
    pbfont = (gs_font_base *)pfont;
    if (rect_within(bbox, pbfont->FontBBox))	/* within bounds */
        return nobbox_draw(i_ctx_p, draw);
    /* Enlarge the FontBBox to save work in the future. */
    rect_merge(pbfont->FontBBox, bbox);
    /* Dismantle everything we've done, and start over. */
    gs_text_retry(penum);
    pfont1 = (gs_font_type1 *) pfont;
    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 {
        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 = metricsSideBearingAndWidth;
    }
    code = type1_exec_init(&cxs.cis, penum, igs, pfont1);
    if (code < 0)
        return code;
    cxs.char_bbox = pfont1->FontBBox;
    code = type1exec_bbox(i_ctx_p, penum, &cxs, pfont, exec_cont);
    return code;
}
static int
bbox_finish(i_ctx_t *i_ctx_p, op_proc_t cont, op_proc_t *exec_cont)
{   /* Returns exec_cont - a function, which must be called by caller after this function. */
    os_ptr op = osp;
    gs_font *pfont;
    int code;
    gs_text_enum_t *penum = op_show_find(i_ctx_p);
    gs_type1exec_state cxs;	/* stack allocate to avoid sandbars */
    gs_type1_state *const pcis = &cxs.cis;
    double sbxy[2];
    gs_point sbpt;
    gs_point *psbpt = 0;
    os_ptr opc = op;
    const ref *opstr;
    ref other_subr;

    if (!r_has_type(opc, t_string)) {
        check_op(3);
        code = num_params(op, 2, sbxy);
        if (code < 0)
            return code;
        sbpt.x = sbxy[0];
        sbpt.y = sbxy[1];
        psbpt = &sbpt;
        opc -= 2;
        check_type(*opc, t_string);
    }
    code = font_param(opc - 3, &pfont);
    if (code < 0)
        return code;
    if (penum == 0 || !font_uses_charstrings(pfont))
        return_error(e_undefined);
    {
        gs_font_type1 *const pfont1 = (gs_font_type1 *) pfont;
        int lenIV = pfont1->data.lenIV;

        if (lenIV > 0 && r_size(opc) <= lenIV)
            return_error(e_invalidfont);
        check_estack(5);	/* in case we need to do a callout */
        code = type1_exec_init(pcis, penum, igs, pfont1);
        if (code < 0)
            return code;
        if (psbpt)
            gs_type1_set_lsb(pcis, psbpt);
    }
    opstr = opc;
  icont:
    code = type1_continue_dispatch(i_ctx_p, &cxs, opstr, &other_subr,
                                   (psbpt ? 6 : 4));
    op = osp;		/* OtherSubrs might have altered it */
    switch (code) {
        case 0:		/* all done */
            /* Call the continuation now. */
            if (psbpt)
                pop(2);
            *exec_cont = cont;
            return 0;
        case type1_result_callothersubr:	/* unknown OtherSubr */
            push_op_estack(cont);	/* call later */
            return type1_call_OtherSubr(i_ctx_p, &cxs, bbox_continue,
                                        &other_subr);
        case type1_result_sbw:	/* [h]sbw, just continue */
            opstr = 0;
            goto icont;
        default:		/* code < 0, error */
            return code;
    }
}