/* Returns exec_cont - a function, which must be called by caller after this function. */ static int type1exec_bbox(i_ctx_t *i_ctx_p, gs_text_enum_t *penum, gs_type1exec_state * pcxs, gs_font * pfont, op_proc_t *exec_cont) { os_ptr op = osp; gs_type1_state *const pcis = &pcxs->cis; gs_font_base *const pbfont = (gs_font_base *) pfont; op_proc_t cont = (pbfont->PaintType == 0 && penum->orig_font->PaintType == 0 ? bbox_finish_fill : bbox_finish_stroke); ref *pcdevproc; /* * We appear to have a valid bounding box. If we don't have Metrics for * this character, start interpreting the CharString; do the * setcachedevice as soon as we know the (side bearing and) width. */ if ((pcxs->present == metricsNone && !pcxs->use_FontBBox_as_Metrics2) || (penum->orig_font->WMode && zchar_get_CDevProc(pbfont, &pcdevproc))) { /* Get the width from the CharString, * then set the cache device. */ /* We pass here when WMode==1 and the font has CDevProc, * because we do need sbw as CDevProc's argument. * A more natural way would be not setting pcxs->use_FontBBox_as_Metrics2 * when the font has CDevProc, except for missing sbw in the glyph. * We prefer to pass here because we've got examples * of Tyoe 1 fonts with empty glyphs, i.e. with no sbw, * so we don't want to assume that they'll never appear in a CID font. * In that case penum->FontBBox_as_Metrics2 will go here to zchar_set_cache. */ ref cnref; ref other_subr; int code; /* Since an OtherSubr callout might change osp, */ /* save the character name now. */ ref_assign(&cnref, op - 1); code = type1_continue_dispatch(i_ctx_p, pcxs, op, &other_subr, 4); op = osp; /* OtherSubrs might change it */ switch (code) { default: /* code < 0 or done, error */ return ((code < 0 ? code : gs_note_error(e_invalidfont))); case type1_result_callothersubr: /* unknown OtherSubr */ return type1_call_OtherSubr(i_ctx_p, pcxs, bbox_getsbw_continue, &other_subr); case type1_result_sbw: /* [h]sbw, done */ break; } type1_cis_get_metrics(pcis, pcxs->sbw); return zchar_set_cache(i_ctx_p, pbfont, &cnref, NULL, pcxs->sbw + 2, &pcxs->char_bbox, cont, exec_cont, NULL); } else { /* We have the width and bounding box: */ /* set up the cache device now. */ return zchar_set_cache(i_ctx_p, pbfont, op - 1, (pcxs->present == metricsSideBearingAndWidth && !pcxs->use_FontBBox_as_Metrics2 ? pcxs->sbw : NULL), pcxs->sbw + 2, &pcxs->char_bbox, cont, exec_cont, (pcxs->use_FontBBox_as_Metrics2 ? pcxs->sbw : NULL)); } }
/* * 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). * Returns exec_cont - a function, which must be called by caller after this function. */ int zchar_set_cache(i_ctx_t *i_ctx_p, const gs_font_base * pbfont, const ref * pcnref, const double psb[2], const double pwidth[2], const gs_rect * pbbox, op_proc_t cont, op_proc_t *exec_cont, const double Metrics2_sbw_default[4]) { os_ptr op = osp; ref *pcdevproc, *valueref; int have_cdevproc; ref rpop; ref cid, *cidptr; bool metrics2; bool metrics2_use_default = false; double w2[10]; gs_text_enum_t *penum = op_show_find(i_ctx_p); 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) { double expand = max(1.415, gs_currentmiterlimit(igs)) * gs_currentlinewidth(igs) / 2; w2[2] -= expand, w2[3] -= expand; w2[4] += expand, w2[5] += expand; } /* Check for Metrics2. */ { int code = zchar_get_metrics2(pbfont, pcnref, w2 + 6); if (code < 0) return code; metrics2 = code > 0; } /* * For FontType 9 and 11, if Metrics2 is missing, the caller provides * default Metrics2 values derived from the FontBBox. */ if (!metrics2 && Metrics2_sbw_default != NULL) { w2[6] = Metrics2_sbw_default[2]; w2[7] = Metrics2_sbw_default[3]; w2[8] = Metrics2_sbw_default[0]; w2[9] = Metrics2_sbw_default[1]; metrics2 = true; metrics2_use_default = true; } /* Check for CDevProc or "short-circuiting". */ have_cdevproc = zchar_get_CDevProc(pbfont, &pcdevproc); /* Obscure test. The CDevProc is supposed to be called with the original CID but what we get passed * here is the TT GID. So the CDevProc won't do the right thing. We need to extract the CID from the * enumerator, and use that instead. */ cidptr = (ref *)pcnref; if (pbfont->FontType == ft_CID_TrueType && dict_find_string(&pfont_data(gs_font_parent(pbfont))->dict, "File", &valueref) > 0) { if (pbfont->key_name.size != pbfont->font_name.size || strncmp((const char *)pbfont->key_name.chars, (const char *)pbfont->font_name.chars, pbfont->key_name.size)) { if (penum->returned.current_glyph >= GS_MIN_CID_GLYPH) { make_int(&cid, penum->returned.current_glyph - GS_MIN_CID_GLYPH); } else { make_int(&cid, penum->returned.current_glyph); } cidptr = &cid; } } if (have_cdevproc || zchar_show_width_only(penum)) { int i; op_proc_t zsetc; int nparams; if (have_cdevproc) { check_proc_only(*pcdevproc); zsetc = zsetcachedevice2; /* If we have cdevproc and the font type is CID type 0, we'll throw away Metrics2_sbw_default that is calculated from FontBBox. */ if (!metrics2 || (penum->current_font->FontType == ft_CID_encrypted && metrics2_use_default)) { 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, cidptr); push_op_estack(cont); push_op_estack(zsetc); ++esp; ref_assign(esp, pcdevproc); return o_push_estack; } { int code = (metrics2 ? gs_text_setcachedevice2(penum, w2) : gs_text_setcachedevice(penum, 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]); } *exec_cont = cont; 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). * Returns exec_cont - a function, which must be called by caller after this function. */ int zchar_set_cache(i_ctx_t *i_ctx_p, const gs_font_base * pbfont, const ref * pcnref, const double psb[2], const double pwidth[2], const gs_rect * pbbox, op_proc_t cont, op_proc_t *exec_cont, const double Metrics2_sbw_default[4]) { os_ptr op = osp; ref *pcdevproc; int have_cdevproc; ref rpop; bool metrics2; bool metrics2_use_default = false; double w2[10]; gs_text_enum_t *penum = op_show_find(i_ctx_p); 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) { double expand = max(1.415, gs_currentmiterlimit(igs)) * gs_currentlinewidth(igs) / 2; w2[2] -= expand, w2[3] -= expand; w2[4] += expand, w2[5] += expand; } /* Check for Metrics2. */ { int code = zchar_get_metrics2(pbfont, pcnref, w2 + 6); if (code < 0) return code; metrics2 = code > 0; } /* * For FontType 9 and 11, if Metrics2 is missing, the caller provides * default Metrics2 values derived from the FontBBox. */ if (!metrics2 && Metrics2_sbw_default != NULL) { w2[6] = Metrics2_sbw_default[2]; w2[7] = Metrics2_sbw_default[3]; w2[8] = Metrics2_sbw_default[0]; w2[9] = Metrics2_sbw_default[1]; metrics2 = true; metrics2_use_default = true; } /* Check for CDevProc or "short-circuiting". */ have_cdevproc = zchar_get_CDevProc(pbfont, &pcdevproc); if (have_cdevproc || zchar_show_width_only(penum)) { int i; op_proc_t zsetc; int nparams; if (have_cdevproc) { check_proc_only(*pcdevproc); zsetc = zsetcachedevice2; /* If we have cdevproc and the font type is CID type 0, we'll throw away Metrics2_sbw_default that is calculated from FontBBox. */ if (!metrics2 || (penum->current_font->FontType == ft_CID_encrypted && metrics2_use_default)) { 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_text_setcachedevice2(penum, w2) : gs_text_setcachedevice(penum, 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]); } *exec_cont = cont; return 0; }