/* Get a Type 42 character metrics and set the cache device. */ int zchar42_set_cache(i_ctx_t *i_ctx_p, gs_font_base *pbfont, ref *cnref, uint glyph_index, op_proc_t cont, op_proc_t *exec_cont, bool put_lsb) { double sbw[4]; double w[2]; int present; int code = zchar_get_metrics(pbfont, cnref, sbw); if (code < 0) return code; present = code; if (present == metricsNone) { float sbw42[4]; int i; code = gs_type42_wmode_metrics((gs_font_type42 *)pbfont, glyph_index, false, sbw42); if (code < 0) return code; present = metricsSideBearingAndWidth; for (i = 0; i < 4; ++i) sbw[i] = sbw42[i]; w[0] = sbw[2]; w[1] = sbw[3]; if (gs_rootfont(igs)->WMode) { /* for vertically-oriented metrics */ code = gs_type42_wmode_metrics((gs_font_type42 *)pbfont, glyph_index, true, sbw42); if (code < 0) { /* no vertical metrics */ if (pbfont->FontType == ft_CID_TrueType) { sbw[0] = sbw[2] / 2; sbw[1] = pbfont->FontBBox.q.y; sbw[2] = 0; sbw[3] = pbfont->FontBBox.p.y - pbfont->FontBBox.q.y; } } else { sbw[0] = sbw[2] / 2; sbw[1] = (pbfont->FontBBox.q.y + pbfont->FontBBox.p.y - sbw42[3]) / 2; sbw[2] = sbw42[2]; sbw[3] = sbw42[3]; } } } else { w[0] = sbw[2]; w[1] = sbw[3]; } return zchar_set_cache(i_ctx_p, pbfont, cnref, (put_lsb && present == metricsSideBearingAndWidth ? sbw : NULL), w, &pbfont->FontBBox, cont, exec_cont, gs_rootfont(igs)->WMode ? sbw : NULL); }
/* Continue from an OtherSubr callout while getting metrics. */ static int bbox_getsbw_continue(i_ctx_t *i_ctx_p) { os_ptr op = osp; ref other_subr; gs_type1exec_state *pcxs = r_ptr(esp, gs_type1exec_state); gs_type1_state *const pcis = &pcxs->cis; int code; code = type1_continue_dispatch(i_ctx_p, pcxs, NULL, &other_subr, 4); op = osp; /* in case z1_push/pop_proc was called */ switch (code) { default: /* code < 0 or done, error */ op_type1_free(i_ctx_p); return ((code < 0 ? code : gs_note_error(e_invalidfont))); case type1_result_callothersubr: /* unknown OtherSubr */ return type1_push_OtherSubr(i_ctx_p, pcxs, bbox_getsbw_continue, &other_subr); case type1_result_sbw: { /* [h]sbw, done */ double sbw[4]; const gs_font_base *const pbfont = (const gs_font_base *)pcis->pfont; gs_rect bbox; op_proc_t cont = (pbfont->PaintType == 0 ? bbox_finish_fill : bbox_finish_stroke), exec_cont = 0; /* Get the metrics before freeing the state. */ type1_cis_get_metrics(pcis, sbw); bbox = pcxs->char_bbox; op_type1_free(i_ctx_p); code = zchar_set_cache(i_ctx_p, pbfont, op - 1, sbw, sbw + 2, &bbox, cont, &exec_cont, NULL); if (code >= 0 && exec_cont != 0) code = (*exec_cont)(i_ctx_p); return code; } } }
/* 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)); } }