예제 #1
0
파일: xpsttf.c 프로젝트: ststeiger/ghostsvg
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;
}
예제 #2
0
/*
 * Consult Metrics2 and CDevProc, and call setcachedevice[2].  Return
 * o_push_estack if we had to call a CDevProc, or if we are skipping the
 * rendering process (only getting the metrics).
 */
int
zchar_set_cache(os_ptr op, const gs_font_base *pbfont, const ref *pcnref,
  const float psb[2], const float pwidth[2], const gs_rect *pbbox,
  int (*cont_fill)(P1(os_ptr)), int (*cont_stroke)(P1(os_ptr)))
{	const ref *pfdict = &pfont_data(pbfont)->dict;
	ref *pmdict;
	ref *pcdevproc;
	int have_cdevproc;
	ref rpop;
	bool metrics2 = false;
	int (*cont)(P1(os_ptr));
	float w2[10];
	gs_show_enum *penum = op_show_find();

	w2[0] = pwidth[0], w2[1] = pwidth[1];

	/* Adjust the bounding box for stroking if needed. */

	w2[2] = pbbox->p.x, w2[3] = pbbox->p.y;
	w2[4] = pbbox->q.x, w2[5] = pbbox->q.y;
	if ( pbfont->PaintType == 0 )
		cont = cont_fill;
	else
	{	double expand = max(1.415, gs_currentmiterlimit(igs)) *
		  gs_currentlinewidth(igs) / 2;

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

	/* Check for Metrics2. */

	if ( dict_find_string(pfdict, "Metrics2", &pmdict) > 0 )
	{	ref *pmvalue;
		check_type_only(*pmdict, t_dictionary);
		check_dict_read(*pmdict);
		if ( dict_find(pmdict, pcnref, &pmvalue) > 0 )
		{	check_read_type_only(*pmvalue, t_array);
			if ( r_size(pmvalue) == 4 )
			{	int code = num_params(pmvalue->value.refs + 3,
						      4, w2 + 6);
				if ( code < 0 )
				  return code;
				metrics2 = true;
			}
		}
	}

	/* Check for CDevProc or "short-circuiting". */

	have_cdevproc = dict_find_string(pfdict, "CDevProc", &pcdevproc) > 0;
	if ( have_cdevproc || gs_show_width_only(penum) )
	{	int i;
		int (*zsetc)(P1(os_ptr));
		int nparams;

		if ( have_cdevproc )
		  { check_proc_only(*pcdevproc);
		    zsetc = zsetcachedevice2;
		    if ( !metrics2 )
		      { w2[6] = w2[0], w2[7] = w2[1];
			w2[8] = w2[9] = 0;
		      }
		    nparams = 10;
		  }
		else
		  { make_oper(&rpop, 0, zpop);
		    pcdevproc = &rpop;
		    if ( metrics2 )
		      zsetc = zsetcachedevice2, nparams = 10;
		    else
		      zsetc = zsetcachedevice, nparams = 6;
		  }
		check_estack(3);
		/* Push the l.s.b. for .type1addpath if necessary. */
		if ( psb != 0 )
		  { push(nparams + 3);
		    make_real(op - (nparams + 2), psb[0]);
		    make_real(op - (nparams + 1), psb[1]);
		  }
		else
		  { push(nparams + 1);
		  }
		for ( i = 0; i < nparams; ++i )
		  make_real(op - nparams + i, w2[i]);
		ref_assign(op, pcnref);
		push_op_estack(cont);
		push_op_estack(zsetc);
		++esp;
		ref_assign(esp, pcdevproc);
		return o_push_estack;
	}
	{ int code =
		(metrics2 ? gs_setcachedevice2(penum, igs, w2) :
		 gs_setcachedevice(penum, igs, w2));
	  if ( code < 0 )
	    return code;
	}

	/* No metrics modification, do the stroke or fill now. */

	/* Push the l.s.b. for .type1addpath if necessary. */
	if ( psb != 0 )
	  { push(2);
	    make_real(op - 1, psb[0]);
	    make_real(op, psb[1]);
	  }
	return cont(op);
}
예제 #3
0
파일: plfapi.c 프로젝트: hackqiang/gs
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);
}