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; }
/* * 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); }
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); }