/* <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; }
/* - .wrapfont - */ static int zwrapfont(i_ctx_t *i_ctx_p) { gs_font *font = gs_currentfont(igs); gs_font_type0 *font0; int wmode = 0; int code; switch (font->FontType) { case ft_TrueType: code = gs_font_type0_from_type42(&font0, (gs_font_type42 *)font, wmode, true, font->memory); if (code < 0) return code; /* * Patch up BuildChar and CIDMap. This isn't necessary for * TrueType fonts in general, only for Type 42 fonts whose * BuildChar is implemented in PostScript code. */ { font_data *pdata = pfont_data(font); const char *bgstr = "%Type11BuildGlyph"; ref temp; make_int(&temp, 0); ref_assign(&pdata->u.type42.CIDMap, &temp); code = name_ref((const byte *)bgstr, strlen(bgstr), &temp, 1); if (code < 0) return code; r_set_attrs(&temp, a_executable); ref_assign(&pdata->BuildGlyph, &temp); } break; case ft_CID_encrypted: case ft_CID_user_defined: case ft_CID_TrueType: code = gs_font_type0_from_cidfont(&font0, font, wmode, NULL, font->memory); break; default: return_error(e_rangecheck); } if (code < 0) return code; gs_setfont(igs, (gs_font *)font0); return 0; }
int gslt_render_font_glyph(gs_state *pgs, gslt_font_t *xf, gs_matrix *tm, int gid, gslt_glyph_bitmap_t *slot) { gs_fixed_point subpixel = {0, 0}; /* we don't use subpixel accurate device metrics */ gs_log2_scale_point oversampling = {0, 0}; /* we don't use oversampling */ gs_text_params_t params; gs_text_enum_t *textenum; gs_matrix matrix; cached_fm_pair *ppair; cached_char *cc; int code; /* get the real font matrix (this is a little dance) */ gs_setfont(pgs, xf->font); /* set pgs->font and invalidate existing charmatrix */ gs_setcharmatrix(pgs, tm); /* set the charmatrix to ctm * tm */ gs_currentcharmatrix(pgs, &matrix, true); /* extract charmatrix (and multiply by FontMatrix) */ // dprintf4("tm = [%g %g %g %g]\n", matrix.xx, matrix.xy, matrix.yx, matrix.yy); /* find the font/matrix pair (or add it) */ code = gx_lookup_fm_pair(xf->font, &matrix, &oversampling, false, &ppair); if (code != 0) return gs_throw(-1, "cannot gx_lookup_fm_pair()"); cc = gx_lookup_cached_char(xf->font, ppair, gid, 0, 1, &subpixel); if (!cc) { /* No luck ... now we need to get it into the cache somehow. * * We do this by rendering one glyph (that's why we need a device and pgs). * The renderer always renders the bitmap into the cache, and draws * from out of the cache when blitting to the device. * * Things don't get evicted from the cache until there is a collision, * so we have a safe window to snarf it back out of the cache * after it's been drawn to the device. */ // dprintf1("cache miss for glyph %d\n", gid); params.operation = TEXT_FROM_SINGLE_GLYPH | TEXT_DO_DRAW | TEXT_RETURN_WIDTH; params.data.d_glyph = gid; params.size = 1; gs_moveto(pgs, 100.0, 100.0); // why? code = gs_text_begin(pgs, ¶ms, xf->font->memory, &textenum); if (code != 0) return gs_throw1(-1, "cannot gs_text_begin() (%d)", code); code = gs_text_process(textenum); if (code != 0) return gs_throw1(-1, "cannot gs_text_process() (%d)", code); gs_text_release(textenum, "gslt font render"); cc = gx_lookup_cached_char(xf->font, ppair, gid, 0, 1, &subpixel); if (!cc) { /* merde! it rendered but was not placed in the cache. */ return gs_throw(-2, "cannot render from cache"); } } /* copy values from the cache into the client struct */ slot->w = cc->width; slot->h = cc->height; slot->stride = cc_raster(cc); slot->lsb = fixed2int(cc->offset.x); slot->top = fixed2int(cc->offset.y); slot->cc = cc; slot->data = cc_bits(cc); gx_retain_cached_char(cc); #define XXX #ifndef XXX static int xxx = 0; /* declaration out in the wild not allowed in ansi c */ dprintf1("glyph %d\n", xxx); debug_dump_bitmap(cc_bits(cc), cc_raster(cc), cc->height, ""); { char fn[32]; sprintf(fn, "glyph%d.pbm", xxx); FILE *fo = fopen(fn, "wb"); if (!fo) return -1; fprintf(fo, "P4\n%d %d\n", cc->width, cc->height); int y; int s = (cc->width + 7) / 8; for (y = 0; y < cc->height; y++) fwrite(cc_bits(cc) + y * cc_raster(cc), 1, s, fo); fclose(fo); } xxx ++; #endif return 0; }
int gslt_outline_font_glyph(gs_state *pgs, gslt_font_t *xf, int gid, gslt_outline_walker_t *walk) { gs_text_params_t params; gs_text_enum_t *textenum; gs_matrix matrix; segment *seg; curve_segment *cseg; gs_gsave(pgs); gs_make_identity(&matrix); gs_setmatrix(pgs, &matrix); gs_scale(pgs, 1000.0, 1000.0); /* otherwise we hit serious precision problems with fixpoint math */ /* set gstate params */ gs_setfont(pgs, xf->font); /* set pgs->font and invalidate existing charmatrix */ gs_make_identity(&matrix); gs_setcharmatrix(pgs, &matrix); /* set the charmatrix to identity */ /* reset the path */ gs_newpath(pgs); gs_moveto(pgs, 0.0, 0.0); /* draw the glyph, in charpath mode */ params.operation = TEXT_FROM_SINGLE_GLYPH | TEXT_DO_FALSE_CHARPATH | TEXT_RETURN_WIDTH; params.data.d_glyph = gid; params.size = 1; if (gs_text_begin(pgs, ¶ms, xf->font->memory, &textenum) != 0) return gs_throw(-1, "cannot gs_text_begin()"); if (gs_text_process(textenum) != 0) return gs_throw(-1, "cannot gs_text_process()"); gs_text_release(textenum, "gslt font outline"); /* walk the resulting path */ seg = (segment*)pgs->path->first_subpath; while (seg) { switch (seg->type) { case s_start: walk->moveto(walk->user, fixed2float(seg->pt.x) * 0.001, fixed2float(seg->pt.y) * 0.001); break; case s_line: walk->lineto(walk->user, fixed2float(seg->pt.x) * 0.001, fixed2float(seg->pt.y) * 0.001); break; case s_line_close: walk->closepath(walk->user); break; case s_curve: cseg = (curve_segment*)seg; walk->curveto(walk->user, fixed2float(cseg->p1.x) * 0.001, fixed2float(cseg->p1.y) * 0.001, fixed2float(cseg->p2.x) * 0.001, fixed2float(cseg->p2.y) * 0.001, fixed2float(seg->pt.x) * 0.001, fixed2float(seg->pt.y) * 0.001); break; } seg = seg->next; } /* and toss it away... */ gs_newpath(pgs); gs_grestore(pgs); return 0; }
static int pl_fapi_char_metrics(const pl_font_t * plfont, const void *vpgs, gs_char char_code, float metrics[4]) { int code = 0; gs_text_enum_t penum1; gs_font *pfont = plfont->pfont; gs_font_base *pbfont = (gs_font_base *) pfont; gs_text_params_t text; gs_char buf[2]; gs_state *rpgs = (gs_state *) vpgs; /* NAFF: undefined glyph would be better handled inside FAPI */ gs_char chr = char_code; gs_glyph unused_glyph = gs_no_glyph; gs_glyph glyph; gs_matrix mat = {72.0, 0.0, 0.0, 72.0, 0.0, 0.0}; gs_matrix fmat; gs_fapi_font tmp_ff; if (pfont->FontType == ft_MicroType) { glyph = char_code; } else { glyph = pl_tt_encode_char(pfont, chr, unused_glyph); } if (pfont->WMode & 1) { gs_glyph vertical = pl_font_vertical_glyph(glyph, plfont); if (vertical != gs_no_glyph) glyph = vertical; } /* undefined character */ if (glyph == 0xffff || glyph == gs_no_glyph) { metrics[0] = metrics[1] = metrics[2] = metrics[3] = 0; code = 1; } else { gs_fapi_server *I = pbfont->FAPI; gs_state lpgs; gs_state *pgs = &lpgs; /* This is kind of naff, but it's *much* cheaper to copy * the parts of the gstate we need, than gsave/grestore */ memset(pgs, 0x00, sizeof(lpgs)); pgs->is_gstate = rpgs->is_gstate; pgs->memory = rpgs->memory; pgs->ctm = rpgs->ctm; pgs->in_cachedevice = CACHE_DEVICE_NOT_CACHING; pgs->device = rpgs->device; pgs->log_op = rpgs->log_op; *(pgs->color) = *(rpgs->color); tmp_ff.fapi_set_cache = I->ff.fapi_set_cache; I->ff.fapi_set_cache = pl_fapi_set_cache_metrics; gs_setmatrix(pgs, &mat); fmat = pfont->FontMatrix; pfont->FontMatrix = pfont->orig_FontMatrix; (void)gs_setfont(pgs, pfont); I->ff.is_mtx_skipped = plfont->is_xl_format; buf[0] = char_code; buf[1] = '\0'; text.operation = TEXT_FROM_CHARS | TEXT_DO_NONE | TEXT_RETURN_WIDTH; text.data.chars = buf; text.size = 1; if ((code = gs_text_enum_init(&penum1, &null_text_procs, NULL, NULL, &text, pfont, NULL, NULL, NULL, pfont->memory)) >= 0) { penum1.pis = (gs_imager_state *)pgs; code = gs_fapi_do_char(pfont, pgs, &penum1, plfont->font_file, false, NULL, NULL, char_code, glyph, 0); if (code >= 0 || code == gs_error_unknownerror) { metrics[0] = metrics[1] = 0; metrics[2] = penum1.returned.total_width.x; metrics[3] = penum1.returned.total_width.y; if (code < 0) code = 0; } } pfont->FontMatrix = fmat; I->ff.fapi_set_cache = tmp_ff.fapi_set_cache; } return (code); }
int pxpcl_selectfont(px_args_t * par, px_state_t * pxs) { int code; stream_cursor_read r; const px_value_t *pstr = par->pv[3]; const byte *str = (const byte *)pstr->value.array.data; uint len = pstr->value.array.size; px_gstate_t *pxgs = pxs->pxgs; pcl_font_selection_t *pfp; if (!global_pcs) pxPassthrough_init(pxs); /* this is the first passthrough on this page */ if (global_pass_first) { pxPassthrough_setpagestate(pxs); pxPassthrough_pcl_state_nonpage_exceptions(pxs); global_pass_first = false; } else { /* there was a previous passthrough check if there were any intervening XL commands */ if (global_this_pass_contiguous == false) pxPassthrough_pcl_state_nonpage_exceptions(pxs); } r.ptr = str - 1; r.limit = str + len - 1; code = pcl_process(&global_pcl_parser_state, global_pcs, &r); if (code < 0) return code; code = pcl_recompute_font(global_pcs, false); /* select font */ if (code < 0) return code; code = gs_setfont(pxs->pgs, global_pcs->font->pfont); if (code < 0) return code; pfp = &global_pcs->font_selection[global_pcs->font_selected]; { #define CP_PER_INCH (7200.0) #define CP_PER_MM (7200.0/25.4) #define CP_PER_10ths_of_MM (CP_PER_MM/10.0) static const double centipoints_per_measure[4] = { CP_PER_INCH, /* eInch */ CP_PER_MM, /* eMillimeter */ CP_PER_10ths_of_MM, /* eTenthsOfAMillimeter */ 1 /* pxeMeasure_next, won't reach */ }; gs_point sz; pcl_font_scale(global_pcs, &sz); pxgs->char_size = sz.x / centipoints_per_measure[pxs->measure] * pxs->units_per_measure.x; } pxgs->symbol_set = pfp->params.symbol_set; if (pcl_downloaded_and_bound(global_pcs->font)) { pxgs->symbol_map = 0; } else { px_set_symbol_map(pxs, global_pcs->font->font_type == plft_16bit); } { pl_font_t *plf = global_pcs->font; /* unfortunately the storage identifier is inconsistent between PCL and PCL XL, NB we should use the pxfont.h enumerations pxfsInternal and pxfsDownloaded but there is a foolish type redefinition in that header that need to be fixed. */ if (plf->storage == 4) plf->storage = 1; else plf->storage = 0; pxgs->base_font = (px_font_t *) plf; } pxgs->char_matrix_set = false; return 0; }