summaryrefslogtreecommitdiff
path: root/pl/pluchar.c
diff options
context:
space:
mode:
Diffstat (limited to 'pl/pluchar.c')
-rw-r--r--pl/pluchar.c718
1 files changed, 718 insertions, 0 deletions
diff --git a/pl/pluchar.c b/pl/pluchar.c
new file mode 100644
index 000000000..1191f1178
--- /dev/null
+++ b/pl/pluchar.c
@@ -0,0 +1,718 @@
+/* Portions Copyright (C) 2001 artofcode LLC.
+ Portions Copyright (C) 1996, 2001 Artifex Software Inc.
+ Portions Copyright (C) 1988, 2000 Aladdin Enterprises.
+ This software is based in part on the work of the Independent JPEG Group.
+ All Rights Reserved.
+
+ This software is distributed under license and may not be copied, modified
+ or distributed except as expressly authorized under the terms of that
+ license. Refer to licensing information at http://www.artifex.com/ or
+ contact Artifex Software, Inc., 101 Lucas Valley Road #110,
+ San Rafael, CA 94903, (415)492-9861, for further information. */
+/*$Id$ */
+
+/* plchar.c */
+/* PCL font handling library -- operations on individual characters */
+#include "math_.h"
+#include "memory_.h"
+#include "stdio_.h" /* for gdebug.h */
+#include "gdebug.h"
+#include "gserror.h"
+#include "gserrors.h"
+#include "gstypes.h"
+#include "gsmemory.h"
+#include "gsstruct.h"
+#include "gsmatrix.h"
+#include "gsstate.h"
+#include "gschar.h"
+#include "gsimage.h"
+#include "gspaint.h"
+#include "gspath.h"
+#include "gsbittab.h"
+#include "gxarith.h" /* for igcd */
+#include "gxfont.h"
+#include "gxfont42.h"
+#include "plfont.h"
+#include "plvalue.h"
+#include "gscoord.h"
+#include "gsstate.h"
+#include "gxdevice.h"
+#include "gxdevmem.h"
+#include "gxpath.h"
+/* We really shouldn't need the following, but currently they are needed */
+/* for pgs->path and penum->log2_current_scale in pl_tt_build_char. */
+#include "gxfixed.h"
+#include "gxchar.h"
+#include "gxfcache.h"
+#include "gzstate.h"
+
+/* agfa includes */
+#undef true
+#undef false
+#undef frac_bits
+#include "cgconfig.h"
+#include "ufstport.h"
+#include "shareinc.h"
+#include "gxfapiu.h"
+
+
+/* ---------------- UFST utilities ---------------- */
+
+#define UFST_SCALE 16
+#define FXD_ONE (1L << UFST_SCALE) /* fixed point 1.0000 */
+
+static const pl_font_t * plfont_last; /* last selected font */
+static const gs_matrix pl_identmtx = { identity_matrix_body };
+
+extern IF_STATE if_state;
+extern PIF_STATE pIFS;
+/*
+ * Set up a generic FONTCONTEXT structure.
+ *
+ * NB: UFST automatically inverts the y-axis when generating a bitmap, so
+ * it is necessary to account for that change in this routine.
+ */
+void
+pl_init_fc(
+ const pl_font_t * plfont,
+ gs_state * pgs,
+ int need_outline,
+ FONTCONTEXT * pfc,
+ bool width_request)
+{
+ gs_font * pfont = plfont->pfont;
+
+ /* set the current tranformation matrix - EM's... if this is a
+ width request we don't necessarily have a current graphics
+ state... use identity for resolution and ctm */
+ gs_matrix mat;
+ floatp xres, yres;
+
+ if ( width_request ) {
+ gs_make_identity(&mat);
+ xres = yres = 1;
+ } else {
+ gs_currentmatrix(pgs, &mat);
+ xres = gs_currentdevice(pgs)->HWResolution[0];
+ yres = gs_currentdevice(pgs)->HWResolution[1];
+ }
+ pfc->font_id = 0;
+ pfc->xspot = F_ONE;
+ pfc->yspot = F_ONE;
+ /* symbol set id used for no symbol set mapping */
+ pfc->ssnum = 0x8000;
+ /* filled in if downloaded font and/or symbol set. */
+ pfc->font_hdr = NULL;
+ pfc->dl_ssnum = 0;
+ /* union selector for transformation type m0..m3 - pcl uses pt.
+ size */
+ pfc->fc_type = FC_MAT2_TYPE;
+ /* calculate point size, set size etc based on current CTM in EM's */
+ {
+ floatp hx = hypot(mat.xx, mat.xy);
+ floatp hy = hypot(mat.yx, mat.yy);
+ /* fixed point scaling */
+ floatp mscale = 1L << 16;
+ pfc->s.m2.matrix_scale = 16;
+ pfc->s.m2.point_size = (int)((hy * plfont->pts_per_inch / yres) + 0.5) * 8; /* 1/8ths */
+ pfc->s.m2.set_size = (int)((hx * plfont->pts_per_inch / xres) + 0.5) * 8;
+ pfc->s.m2.m[0] = mscale * mat.xx / hx;
+ pfc->s.m2.m[1] = mscale * -mat.xy / hx;
+ pfc->s.m2.m[2] = mscale * mat.yx / hy;
+ pfc->s.m2.m[3] = mscale * -mat.yy / hy;
+ pfc->s.m2.world_scale = 16;
+ pfc->s.m2.xworld_res = mscale * xres;
+ pfc->s.m2.yworld_res = mscale * yres;
+ }
+
+ if ( need_outline ) {
+ pfc->s.m2.m[1] = -pfc->s.m2.m[1];
+ pfc->s.m2.m[3] = -pfc->s.m2.m[3];
+ }
+
+ /* always use our own symbol set mapping */
+ pfc->ExtndFlags = EF_NOSYMSETMAP;
+ if (plfont->is_xl_format) {
+ pfc->ExtndFlags = EF_XLFONT_TYPE;
+ if ((pfont->WMode & 0x1) != 0) /* vertical substitution */
+ pfc->ExtndFlags |= EF_VERTSUBS_TYPE;
+ }
+ else if (plfont->scaling_technology == plfst_TrueType && plfont->large_sizes) {
+ pfc->ExtndFlags = EF_FORMAT16_TYPE | EF_GALLEYSEG_TYPE;
+ if ((pfont->WMode & 0x1) != 0) /* vertical substitution */
+ pfc->ExtndFlags |= EF_VERTSUBS_TYPE;
+ }
+ pfc->ExtndFlags |= EF_NOUSBOUNDBOX; /* UFST 5.0+ addition */
+
+ /* handle artificial emboldening */
+ if (plfont->bold_fraction && !need_outline) {
+ pfc->pcl6bold = 32768 * plfont->bold_fraction;
+ }
+ else
+ pfc->pcl6bold = 0;
+ /* set the format */
+ pfc->format = FC_PCL6_EMU | FC_INCHES_TYPE;
+ pfc->format |= (need_outline ? FC_LINEAR_TYPE : FC_BITMAP_TYPE);
+}
+
+/*
+ * Set the current UFST font (any type).
+ */
+static int
+pl_set_ufst_font(const pl_font_t * plfont, FONTCONTEXT * pfc)
+{
+ uint status = CGIFfont(FSA pfc);
+
+ if (status != 0)
+ dprintf1("CGIFfont error %d\n", status);
+ else
+ plfont_last = plfont; /* record this font for use in call-backs */
+ return status;
+}
+
+/*
+ * Set the current path from a character outline. This is more general than
+ * may be necessary, depending on how the UFST module is compiled.
+ */
+static int
+image_outline_char(
+ PIFOUTLINE pols,
+ const gs_matrix_fixed * pmat,
+ gx_path * ppath,
+ gs_font * pfont )
+{
+ UW16 il, numLoops = pols->ol.num_loops;
+ byte * pbase = (byte *)&pols->ol.loop;
+ int ishift = fixed_fraction_bits + pols->VLCpower;
+ fixed tx = pmat->tx_fixed, ty = pmat->ty_fixed;
+
+ for (il = 0; il < numLoops; il++) {
+ OUTLINE_LOOP * ploop = &pols->ol.loop[il];
+ uint numSegmts = ploop->num_segmts;
+ byte * pseg = pbase + ploop->segmt_offset;
+ PINTRVECTOR pcoord = (PINTRVECTOR)(pbase + ploop->coord_offset);
+ int code;
+
+ while (numSegmts-- > 0) {
+ int segtype = *pseg++;
+ int ip, npts;
+ gs_fixed_point pt[3];
+
+ if (segtype == 2 || segtype > 3)
+ return_error(gs_error_rangecheck);
+
+ npts = (segtype == 3 ? 3 : 1);
+ for (ip = 0; ip < npts; ip++, ++pcoord) {
+ pt[ip].x = (pcoord->x << ishift) + tx;
+ pt[ip].y = (pcoord->y << ishift) + ty;
+ }
+
+ switch (segtype) {
+
+ case 0: /* moveto */
+ code = gx_path_add_point(ppath, pt[0].x, pt[0].y);
+ break;
+
+ case 1: /* lineto */
+ code = gx_path_add_line(ppath, pt[0].x, pt[0].y);
+ break;
+
+ case 3: /* curveto */
+ code = gx_path_add_curve( ppath,
+ pt[0].x, pt[0].y,
+ pt[1].x, pt[1].y,
+ pt[2].x, pt[2].y );
+ }
+ if (code < 0)
+ return code;
+ }
+ if ((code = gx_path_close_subpath(ppath)) < 0)
+ return code;
+ }
+ return 0;
+}
+
+/*
+ * Get the widt from a UFST character (any type). The caller should have
+ * set the font type in advance.
+ */
+static int
+pl_ufst_char_width(
+ uint char_code,
+ const void * pgs,
+ gs_point * pwidth,
+ FONTCONTEXT * pfc )
+{
+
+ UW16 chIdloc = char_code;
+ UW16 fontWidth[2];
+ int status;
+ WIDTH_LIST_INPUT_ENTRY fcode;
+ if (pwidth != NULL)
+ pwidth->x = pwidth->y = 0;
+
+ CGIFchIdptr(FSA (VOID *)&chIdloc, NULL);
+ fcode.CharType.TT_unicode = char_code;
+ if ((status = CGIFwidth2(FSA &fcode, 1, 4, fontWidth)) != 0) {
+ dprintf1("CGIFwidth error %d\n", status);
+ return status;
+ }
+ if (fontWidth[0] == ERR_char_unavailable || fontWidth[1] == 0)
+ return 1;
+ else if (pwidth != NULL) {
+ floatp fontw = (floatp)fontWidth[0] / (floatp)fontWidth[1];
+ int code = gs_distance_transform(fontw, 0.0, &pl_identmtx, pwidth);
+
+ return code < 0 ? code : 0;
+ } else
+ return 0;
+}
+
+/*
+ * Generate a UFST character.
+ */
+static int
+pl_ufst_make_char(
+ gs_show_enum * penum,
+ gs_state * pgs,
+ gs_font * pfont,
+ gs_char chr,
+ FONTCONTEXT * pfc )
+{
+ gs_imager_state * pis = (gs_imager_state *)pgs;
+ MEM_HANDLE memhdl;
+ UW16 status, chIdloc = chr;
+ gs_matrix sv_ctm, tmp_ctm;
+ int wasValid;
+
+ /* ignore illegitimate characters */
+ if (chr == 0xffff)
+ return 0;
+
+ CGIFchIdptr(FSA (VOID *)&chIdloc, NULL);
+ if ( (status = CGIFchar_handle(FSA chr, &memhdl, 0)) != 0 &&
+ status != ERR_fixed_space ) {
+
+ /* if too large for a bitmap, try an outline */
+ if (status >= ERR_bm_gt_oron && status <= ERRdu_pix_range) {
+ pfc->format = (pfc->format & ~FC_BITMAP_TYPE) | FC_CUBIC_TYPE;
+ if ((status = CGIFfont(FSA pfc)) == 0) {
+ CGIFchIdptr(FSA (VOID *)&chIdloc, NULL);
+ status = CGIFchar_handle(FSA chr, &memhdl, 0);
+ }
+ }
+ if (status != 0) {
+ dprintf2("CGIFchar_handle error %d for char=0x%x\n", status, chr);
+ gs_setcharwidth(penum, pgs, 0.0, 0.0);
+ return 0; /* returning status causes the job to be aborted */
+ }
+ }
+
+ wasValid = pgs->char_tm_valid;
+ /* move to device space */
+ gs_currentmatrix(pgs, &sv_ctm);
+ gs_make_identity(&tmp_ctm);
+ tmp_ctm.tx = sv_ctm.tx;
+ tmp_ctm.ty = sv_ctm.ty;
+ gs_setmatrix(pgs, &tmp_ctm);
+ pgs->char_tm_valid = wasValid;
+
+ if (FC_ISBITMAP(pfc)) {
+ PIFBITMAP psbm = (PIFBITMAP)MEMptr(memhdl);
+ float wbox[6];
+ gs_image_t image;
+ gs_image_enum * ienum;
+ int code;
+ gs_point aw;
+
+ /* set up the cache device */
+ gs_distance_transform( (floatp)psbm->escapement / psbm->du_emx,
+ 0.0,
+ &sv_ctm,
+ &aw );
+
+ wbox[0] = aw.x;
+ wbox[1] = aw.y;
+ wbox[2] = psbm->xorigin / 16.0 + psbm->left_indent;
+ wbox[3] = -psbm->yorigin / 16.0 + psbm->top_indent;
+ wbox[4] = psbm->black_width + wbox[2];
+ wbox[5] = psbm->black_depth + wbox[3];
+
+ /* if (status == ERR_fixed_space)
+ * we are relying on ufst to
+ * send a zero sized image; we then cache the escapements of the space character
+ * psbm->bm = psbm->width = psbm->height = 0;
+ * note that the outline code can't be reached on ERR_fixed_space
+ */
+
+ if ((code = gs_setcachedevice(penum, pgs, wbox)) < 0) {
+ MEMfree(FSA CACHE_POOL, memhdl);
+ gs_setmatrix(pgs, &sv_ctm);
+ return code;
+ }
+
+ /* set up the image */
+ ienum = gs_image_enum_alloc(pgs->memory, "pl_ufst_make_char");
+ if (ienum == 0) {
+ MEMfree(FSA CACHE_POOL, memhdl);
+ gs_setmatrix(pgs, &sv_ctm);
+ return_error(gs_error_VMerror);
+ }
+ gs_image_t_init_mask(&image, true);
+ image.Width = psbm->width << 3;
+ image.Height = psbm->depth;
+ gs_make_identity(&image.ImageMatrix);
+ image.ImageMatrix.tx = -psbm->xorigin / 16.0;
+ image.ImageMatrix.ty = psbm->yorigin / 16.0;
+ image.adjust = true;
+ code = image_bitmap_char( ienum,
+ &image,
+ (byte *)psbm->bm,
+ psbm->width,
+ 0,
+ NULL,
+ pgs );
+ gs_free_object(pgs->memory, ienum, "pl_ufst_make_char");
+ MEMfree(FSA CACHE_POOL, memhdl);
+ gs_setmatrix(pgs, &sv_ctm);
+ return (code < 0 ? code : 0);
+
+ } else { /* outline */
+ PIFOUTLINE pols = (PIFOUTLINE)MEMptr(memhdl);
+ float scale = pow(2, pols->VLCpower);
+ float wbox[6];
+ int code;
+ gs_point aw;
+
+ /* set up the cache device */
+ gs_distance_transform( (floatp)pols->escapement / pols->du_emx,
+ 0.0,
+ &sv_ctm,
+ &aw );
+ wbox[0] = aw.x;
+ wbox[1] = aw.y;
+ wbox[2] = scale * pols->left;
+ wbox[3] = scale * pols->bottom;
+ wbox[4] = scale * pols->right;
+ wbox[5] = scale * pols->top;
+
+ if (status == ERR_fixed_space) {
+ MEMfree(FSA CACHE_POOL, memhdl);
+ code = gs_setcharwidth(penum, pgs, wbox[0], wbox[1]);
+ gs_setmatrix(pgs, &sv_ctm);
+ return code;
+ } else if ((code = gs_setcachedevice(penum, pgs, wbox)) < 0) {
+ MEMfree(FSA CACHE_POOL, memhdl);
+ gs_setmatrix(pgs, &sv_ctm);
+ return code;
+ }
+
+ code = image_outline_char(pols, &pis->ctm, pgs->path, pfont);
+ if (code >= 0) {
+ code = gs_fill(pgs);
+ }
+ MEMfree(FSA CACHE_POOL, memhdl);
+ gs_setmatrix(pgs, &sv_ctm);
+ return (code < 0 ? code : 0);
+ }
+}
+
+
+/* ---------------- TrueType font support ---------------- */
+
+/* Look up a character in the TrueType character-to-TT-glyph map. */
+/* Return a pointer to the glyph's slot (chr != gs_no_char) or where */
+/* it should be added (chr == gs_no_char). */
+static pl_tt_char_glyph_t *
+pl_tt_lookup_char(const pl_font_t *plfont, gs_glyph glyph)
+{ uint size = plfont->char_glyphs.size;
+ uint skip = plfont->char_glyphs.skip;
+ uint index = glyph % size;
+ pl_tt_char_glyph_t *ptcg;
+ pl_tt_char_glyph_t *result = 0;
+
+ while ( (ptcg = plfont->char_glyphs.table + index)->chr != gs_no_char ?
+ ptcg->chr != glyph : ptcg->glyph
+ )
+ { if ( ptcg->chr == gs_no_char )
+ result = ptcg;
+ index = (index >= skip ? index : index + size) - skip;
+ }
+ return (result ? result : ptcg);
+}
+
+/* Get a string from a TrueType font. */
+static int
+pl_tt_string_proc(gs_font_type42 *pfont, ulong offset, uint length,
+ const byte **pdata)
+{ pl_font_t *plfont = pfont->client_data;
+
+ *pdata = plfont->header + plfont->offsets.GT +
+ (plfont->large_sizes ? 6 : 4) + offset;
+ return 0;
+}
+
+/* Return the vertical substitute for a glyph, if it has one; */
+/* otherwise return gs_no_glyph. */
+static gs_glyph
+pl_font_vertical_glyph(gs_glyph glyph, const pl_font_t *plfont)
+{ long VT = plfont->offsets.VT;
+ const byte *vtseg;
+ uint i, len;
+
+ if ( VT < 0 )
+ return gs_no_glyph;
+ vtseg = plfont->header + VT;
+ if ( plfont->large_sizes )
+ len = pl_get_uint32(vtseg + 2),
+ i = 6;
+ else
+ len = pl_get_uint16(vtseg + 2),
+ i = 4;
+ len += i;
+ for ( ; i < len; i += 4 )
+ if ( glyph == pl_get_uint16(vtseg + i) )
+ return pl_get_uint16(vtseg + i + 2);
+ return gs_no_glyph;
+}
+#define access(base, length, vptr)\
+ (*pfont->data.string_proc)(pfont, (ulong)(base), length, &vptr)
+
+#ifndef gs_imager_state_DEFINED
+# define gs_imager_state_DEFINED
+typedef struct gs_imager_state_s gs_imager_state;
+#endif
+
+/* Opaque type for a path */
+#ifndef gx_path_DEFINED
+# define gx_path_DEFINED
+typedef struct gx_path_s gx_path;
+#endif
+
+/* ---------------- MicroType font support ---------------- */
+/*
+ * MicroType accepts unicode values a glyph identifiers, so no explicit
+ * encoding is necessary.
+ */
+static gs_glyph
+pl_mt_encode_char(gs_font * pfont, gs_char pchr, gs_glyph_space_t not_used)
+{
+ return (gs_glyph)pchr;
+}
+
+
+/*
+ * Set the current UFST font to be a MicroType font.
+ */
+static int
+pl_set_mt_font(
+ gs_state *pgs,
+ const pl_font_t * plfont,
+ int need_outline,
+ FONTCONTEXT * pfc )
+{
+ pl_init_fc(plfont, pgs, need_outline, pfc, /* width request iff */ pgs == NULL);
+ pfc->font_id = ((gs_font_base *)(plfont->pfont))->UID.id;
+#ifdef UFST_FROM_ROM
+ pfc->format |= FC_ROM_TYPE | FC_NOUSBOUNDBOX;
+#endif
+ pfc->format |= FC_FCO_TYPE;
+ return pl_set_ufst_font(plfont, pfc);
+}
+
+/* Render a MicroType character. */
+static int
+pl_mt_build_char(
+ gs_show_enum * penum,
+ gs_state * pgs,
+ gs_font * pfont,
+ gs_char chr,
+ gs_glyph glyph )
+{
+ const pl_font_t * plfont = (const pl_font_t *)pfont->client_data;
+ FONTCONTEXT fc;
+
+ if ( pl_set_mt_font( pgs,
+ plfont,
+ gs_show_in_charpath(penum),
+ &fc ) != 0 )
+ return 0;
+ return pl_ufst_make_char(penum, pgs, pfont, chr, &fc);
+}
+
+#define MAX_LIST_SIZE 100
+int list_size = 0;
+
+typedef struct pl_glyph_width_node_s pl_glyph_width_node_t;
+
+struct pl_glyph_width_node_s {
+ uint char_code;
+ uint font_id;
+ gs_point width;
+ pl_glyph_width_node_t *next;
+};
+
+pl_glyph_width_node_t *head = NULL;
+/* add at the front of the list */
+
+int
+pl_glyph_width_cache_node_add(gs_memory_t *mem, gs_id font_id, uint char_code, gs_point *pwidth)
+{
+ pl_glyph_width_node_t *node =
+ (pl_glyph_width_node_t *)gs_alloc_bytes(mem,
+ sizeof(pl_glyph_width_node_t),
+ "pl_glyph_width_cache_node_add");
+ if ( node == NULL )
+ return -1;
+ if ( head == NULL ) {
+ head = node;
+ head->next = NULL;
+ } else {
+ node->next = head;
+ head = node;
+ }
+
+ head->char_code = char_code;
+ head->font_id = font_id;
+ head->width = *pwidth;
+ list_size++;
+ return 0;
+}
+
+int
+pl_glyph_width_cache_node_search(gs_id font_id, uint char_code, gs_point *pwidth)
+{
+ pl_glyph_width_node_t *current = head;
+ while ( current ) {
+ if ( char_code == current->char_code && font_id == current->font_id ) {
+ *pwidth = current->width;
+ return 0;
+ }
+ current = current->next;
+ }
+ return -1;
+}
+
+void
+pl_glyph_width_list_remove(gs_memory_t *mem)
+{
+ pl_glyph_width_node_t *current = head;
+ while (current) {
+ pl_glyph_width_node_t *next = current->next;
+ gs_free_object(mem, current, "pl_glyph_width_list_remove");
+ current = next;
+ }
+ head = NULL;
+ list_size = 0;
+ return;
+}
+
+
+/* Get character existence and escapement for an MicroType font. */
+static int
+pl_mt_char_width(
+ const pl_font_t * plfont,
+ const void * pgs,
+ uint char_code,
+ gs_point * pwidth )
+{
+ FONTCONTEXT fc;
+ int code;
+ if ( list_size > MAX_LIST_SIZE )
+ pl_glyph_width_list_remove(plfont->pfont->memory);
+ code = pl_glyph_width_cache_node_search(plfont->pfont->id, char_code, pwidth);
+ if ( code < 0 ) /* not found */ {
+ /* FIXME inconsitant error code return values follow */
+ if (pl_set_mt_font(NULL /* graphics state */, plfont, false, &fc) != 0)
+ return 0;
+ code = pl_ufst_char_width(char_code, pgs, pwidth, &fc);
+ if ( code == 0 )
+ code = pl_glyph_width_cache_node_add(plfont->pfont->memory,
+ plfont->pfont->id,
+ char_code, pwidth);
+ }
+ return code;
+}
+
+static int
+pl_mt_char_metrics(const pl_font_t *plfont, const void *pgs, uint char_code, float metrics[4])
+{
+ gs_point width;
+ metrics[0] = metrics[1] = metrics[2] = metrics[3] = 0;
+ if ( 0 == pl_mt_char_width(plfont, pgs, char_code, &width) ) {
+ /* width is correct,
+ stefan foo: lsb is missing. */
+ metrics[2] = width.x;
+ /* metrics[0] = left_side_bearing;
+ */
+ }
+ return 0;
+}
+
+/*
+ * Callback from UFST to pass PCLEO IF character data starting with header.
+ *
+ * For TrueType fonts, the glyph table within a font is indexed by the glyph
+ * id., rather than the unicode. The char_glyphs table in the font maps the
+ * latter to the former.
+ */
+LPUB8 pl_PCLchId2ptr(FSP UW16 chId)
+{
+ const pl_font_t * plfont = plfont_last;
+
+ if (plfont_last == NULL)
+ return NULL; /* something wrong */
+
+ /* check for a TrueType font */
+ if (plfont->char_glyphs.table != NULL) {
+ pl_tt_char_glyph_t * ptcg = pl_tt_lookup_char(plfont, chId);
+
+ if (ptcg->chr == gs_no_char)
+ return NULL; /* something wrong */
+ chId = ptcg->glyph;
+ }
+ return (LPUB8)pl_font_lookup_glyph(plfont, chId)->data;
+}
+
+/*
+ * callback from UFST to pass PCLEO TT character data starting with header.
+ */
+LPUB8 pl_PCLglyphID2Ptr(FSP UW16 chId)
+{
+ if (plfont_last == NULL)
+ return NULL; /* something wrong */
+ else
+ return (LPUB8)(pl_font_lookup_glyph(plfont_last, chId)->data);
+}
+
+/*
+ * callback from UFST to pass PCLEO compound character data starting
+ * with header.
+ */
+LPUB8 pl_PCLEO_charptr(LPUB8 pfont_hdr, UW16 char_code)
+{
+ if (plfont_last == NULL || plfont_last->header != pfont_hdr) {
+ dprintf2("fontheader active=0x%x requested=0x%x\n",
+ (plfont_last == NULL ? 0 : plfont_last->header),
+ pfont_hdr );
+ return NULL; /* something wrong */
+ } else
+ return pl_PCLchId2ptr(FSA char_code);
+}
+
+void plu_set_callbacks()
+{
+ gx_set_UFST_Callbacks(pl_PCLEO_charptr, pl_PCLchId2ptr, pl_PCLglyphID2Ptr);
+ /* nothing */
+}
+
+void
+pl_mt_init_procs(gs_font_base *pfont)
+{ pfont->procs.encode_char = pl_mt_encode_char;
+ pfont->procs.build_char = pl_mt_build_char;
+#define plfont ((pl_font_t *)pfont->client_data)
+ plfont->char_width = pl_mt_char_width;
+ plfont->char_metrics = pl_mt_char_metrics;
+#undef plfont
+}
+