summaryrefslogtreecommitdiff
path: root/src/Speedo/do_char.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/Speedo/do_char.c')
-rw-r--r--src/Speedo/do_char.c1022
1 files changed, 1022 insertions, 0 deletions
diff --git a/src/Speedo/do_char.c b/src/Speedo/do_char.c
new file mode 100644
index 0000000..0ae416b
--- /dev/null
+++ b/src/Speedo/do_char.c
@@ -0,0 +1,1022 @@
+/* $Xorg: do_char.c,v 1.3 2000/08/17 19:46:24 cpqbld Exp $ */
+
+/*
+
+Copyright 1989-1991, Bitstream Inc., Cambridge, MA.
+You are hereby granted permission under all Bitstream propriety rights to
+use, copy, modify, sublicense, sell, and redistribute the Bitstream Speedo
+software and the Bitstream Charter outline font for any purpose and without
+restrictions; provided, that this notice is left intact on all copies of such
+software or font and that Bitstream's trademark is acknowledged as shown below
+on all unmodified copies of such font.
+
+BITSTREAM CHARTER is a registered trademark of Bitstream Inc.
+
+
+BITSTREAM INC. DISCLAIMS ANY AND ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+WITHOUT LIMITATION THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE. BITSTREAM SHALL NOT BE LIABLE FOR ANY DIRECT OR INDIRECT
+DAMAGES, INCLUDING BUT NOT LIMITED TO LOST PROFITS, LOST DATA, OR ANY OTHER
+INCIDENTAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF OR IN ANY WAY CONNECTED
+WITH THE SPEEDO SOFTWARE OR THE BITSTREAM CHARTER OUTLINE FONT.
+
+*/
+
+/***************************** D O - C H A R . C *****************************
+ * *
+ * This is the top level module for processing one simple or composite *
+ * character.
+ * *
+ ****************************************************************************/
+
+#include "spdo_prv.h" /* General definitions for Speedo */
+
+#define DEBUG 0
+
+#if DEBUG
+#include <stdio.h>
+#define SHOW(X) printf("X = %d\n", X)
+#else
+#define SHOW(X)
+#endif
+
+/***** GLOBAL VARIABLES *****/
+
+/***** GLOBAL FUNCTIONS *****/
+
+/***** EXTERNAL VARIABLES *****/
+
+/***** EXTERNAL FUNCTIONS *****/
+
+/***** STATIC VARIABLES *****/
+
+/***** STATIC FUNCTIONS *****/
+
+#if PROTOS_AVAIL
+static boolean sp_make_simp_char(PROTO_DECL2 ufix8 FONTFAR *pointer,ufix8 format);
+static boolean sp_make_comp_char(PROTO_DECL2 ufix8 FONTFAR *pointer);
+static ufix8 FONTFAR *sp_get_char_org(PROTO_DECL2 ufix16 char_index,boolean top_level);
+static fix15 sp_get_posn_arg(PROTO_DECL2 ufix8 FONTFAR *STACKFAR *ppointer,ufix8 format);
+static fix15 sp_get_scale_arg(PROTO_DECL2 ufix8 FONTFAR *STACKFAR *ppointer,ufix8 format);
+#else
+static boolean sp_make_simp_char(); /* Process simple character data */
+static boolean sp_make_comp_char(); /* Process compound character data */
+static ufix8 FONTFAR *sp_get_char_org(); /* Look up char in character directory */
+static fix15 sp_get_posn_arg(); /* Read Xpos Ypos args in DOCH instruction */
+static fix15 sp_get_scale_arg(); /* read Xscale Yscale args in DOCH instruction */
+#endif
+
+
+FUNCTION ufix16 get_char_id(char_index)
+GDECL
+ufix16 char_index; /* Index to character in char directory */
+/*
+ * Returns character id for specified character index in currently
+ * selected font.
+ * Reports Error 10 and returns 0 if no font selected.
+ * Reports Error 12 and returns 0 if character data not available.
+ */
+{
+ufix8 FONTFAR *pointer; /* Pointer to character data */
+
+if (!sp_globals.specs_valid) /* Font specs not defined? */
+ {
+ report_error(10); /* Report font not specified */
+ return (ufix16)0; /* Return zero character id */
+ }
+
+pointer = sp_get_char_org(char_index, TRUE); /* Get pointer to character data */
+if (pointer == NULL) /* Character data not available? */
+ {
+ report_error(12); /* Report character data not avail */
+ return (ufix16)0; /* Return zero character id */
+ }
+
+return 0xffff & NEXT_WORD(pointer); /* Return character id */
+}
+
+
+#if INCL_METRICS
+FUNCTION fix31 get_char_width(char_index)
+GDECL
+ufix16 char_index; /* Index to character in char directory */
+/*
+ * Returns character set width for specified character index in currently
+ * selected font in units of 1/65536 em.
+ * Reports Error 10 and returns 0 if no font selected.
+ * Reports Error 12 and returns 0 if character data not available.
+ */
+{
+ufix8 FONTFAR *pointer; /* Pointer to character data */
+fix31 set_width; /* Set width of character */
+
+if (!sp_globals.specs_valid) /* Font specs not defined? */
+ {
+ report_error(10); /* Report font not specified */
+ return (fix31)0; /* Return zero character width */
+ }
+
+pointer = sp_get_char_org(char_index, TRUE); /* Get pointer to character data */
+if (pointer == NULL) /* Character data not available? */
+ {
+ report_error(12); /* Report character data not avail */
+ return (fix31)0; /* Return zero character width */
+ }
+
+pointer += 2; /* Skip over character id */
+set_width = (fix31)NEXT_WORD(pointer); /* Read set width and Convert units */
+set_width = ((set_width << 16) + (sp_globals.metric_resolution >> 1)) / sp_globals.metric_resolution;
+return set_width; /* Return in 1/65536 em units */
+}
+#endif
+
+#if INCL_METRICS
+FUNCTION fix15 get_track_kern(track, point_size)
+GDECL
+fix15 track; /* Track required (0 - 3) */
+fix15 point_size; /* Point size (units of whole points) */
+/*
+ * Returns inter-character spacing adjustment in units of 1/256
+ * points for the specified kerning track and point size.
+ * If the specified point size is larger than the maximum point
+ * size for the specified track, the adjustment for the maximum
+ * point size is used.
+ * If the specified point size is smaller than the minimum point
+ * size for the specified track, the adjustment for the minimum
+ * point size is used.
+ * If the specified point size is between the minimum point size
+ * and the maximum point size for the specified track, the
+ * adjustment is interpolated linearly between the minimum and
+ * maximum adjustments.
+ * Reports Error 10 and returns 0 if no font selected.
+ * Reports Error 13 and returns 0 if track kerning data not in font.
+ */
+{
+ufix8 FONTFAR *pointer; /* Pointer to character data */
+fix15 no_tracks; /* Number of kerning tracks in font */
+ufix8 format; /* Track kerning format byte */
+fix15 i; /* Track counter */
+fix15 min_pt_size; /* Minimum point size for track */
+fix15 max_pt_size; /* Maximum point size for track */
+fix15 min_adj; /* Adjustment for min point size */
+fix15 max_adj; /* Adjustment for max point size */
+fix31 delta_pt_size;/* Max point size - min point size */
+fix31 delta_adj; /* Min adjustment - max adjustment */
+fix15 adj = 0; /* Interpolated adjustment */
+
+if (track == 0) /* Track zero selected? */
+ {
+ return adj; /* Return zero track kerning adjustment */
+ }
+
+if (!sp_globals.specs_valid) /* Font specs not defined? */
+ {
+ report_error(10); /* Report font not specified */
+ return adj; /* Return zero track kerning adjustment */
+ }
+
+no_tracks = sp_globals.kern.no_tracks; /* Number of kerning tracks */
+if (track > no_tracks) /* Required track not available? */
+ {
+ report_error(13); /* Report track kerning data not avail */
+ return adj; /* Return zero track kerning adjustment */
+ }
+
+pointer = sp_globals.kern.tkorg; /* Point to start of track kern data */
+for (i = 0; i < track; i++) /* Read until track required is read */
+ {
+ format = NEXT_BYTE(pointer); /* Read track kerning format byte */
+ min_pt_size = (format & BIT0)?
+ NEXT_WORD(pointer):
+ (fix15)NEXT_BYTE(pointer);
+ min_adj = (format & BIT1)?
+ NEXT_WORD(pointer):
+ (fix15)NEXT_BYTE(pointer);
+ max_pt_size = (format & BIT2)?
+ NEXT_WORD(pointer):
+ (fix15)NEXT_BYTE(pointer);
+ max_adj = (format & BIT3)?
+ NEXT_WORD(pointer):
+ (fix15)NEXT_BYTE(pointer);
+ }
+
+if (point_size <= min_pt_size) /* Smaller than minimum point size? */
+ {
+ return min_adj; /* Return minimum adjustment (1/256 points) */
+ }
+
+if (point_size >= max_pt_size) /* Larger than maximum point size? */
+ {
+ return max_adj; /* Return maximum adjustment (1/256 points) */
+ }
+
+delta_pt_size = (fix31)(max_pt_size - min_pt_size);
+delta_adj = (fix31)(min_adj - max_adj);
+adj = (fix15)(min_adj -
+ (((fix31)(point_size - min_pt_size) * delta_adj +
+ (delta_pt_size >> 1)) / delta_pt_size));
+return adj; /* Return interpolated adjustment (1/256 points) */
+}
+#endif
+
+#if INCL_METRICS
+FUNCTION fix31 get_pair_kern(char_index1, char_index2)
+GDECL
+ufix16 char_index1; /* Index to first character in char directory */
+ufix16 char_index2; /* Index to second character in char directory */
+/*
+ * Returns inter-character spacing adjustment in units of 1/65536 em
+ * for the specified pair of characters.
+ * Reports Error 10 and returns 0 if no font selected.
+ * Reports Error 14 and returns 0 if pair kerning data not in font.
+ */
+{
+ufix8 FONTFAR *origin; /* Pointer to first kerning pair record */
+ufix8 FONTFAR *pointer; /* Pointer to character data */
+ufix16 tmpufix16; /* Temporary workspace */
+fix15 no_pairs; /* Number of kerning pairs in font */
+ufix8 format; /* Track kerning format byte */
+boolean long_id; /* TRUE if 2-byte character ids */
+fix15 rec_size; /* Number of bytes in kern pair record */
+fix15 n; /* Number of remaining kern pairs */
+fix15 nn; /* Number of kern pairs in first partition */
+fix15 base; /* Index to first record in rem kern pairs */
+fix15 i; /* Index to kern pair being tested */
+fix31 adj = 0; /* Returned value of adjustment */
+fix15 adj_base; /* Adjustment base for relative adjustments */
+
+if (!sp_globals.specs_valid) /* Font specs not defined? */
+ {
+ report_error(10); /* Report font not specified */
+ return adj; /* Return zero pair kerning adjustment */
+ }
+
+no_pairs = sp_globals.kern.no_pairs; /* Number of kerning pairs */
+if (no_pairs == 0) /* Pair kerning data not available? */
+ {
+ report_error(14); /* Report pair kerning data not avail */
+ return adj; /* Return zero pair kerning adjustment */
+ }
+
+pointer = sp_globals.kern.pkorg; /* Point to start of pair kern data */
+format = NEXT_BYTE(pointer); /* Read pair kerning format byte */
+if (!(format & BIT0)) /* One-byte adjustment values? */
+ adj_base = NEXT_WORD(pointer); /* Read base adjustment */
+origin = pointer; /* First byte of kerning pair data */
+rec_size = format + 3; /* Compute kerning pair record size */
+long_id = format & BIT1; /* Set flag for 2-byte char index */
+
+n = no_pairs; /* Consider all kerning pairs */
+base = 0; /* Set base at first kern pair record */
+while (n != 0) /* While 1 or more kern pairs remain ... */
+ {
+ nn = n >> 1; /* Size of first partition */
+ i = base + nn; /* Index to record to be tested */
+ pointer = origin + (i * rec_size);
+ tmpufix16 = NEXT_CHNDX(pointer, long_id);
+ if (char_index1 < tmpufix16)
+ {
+ n = nn; /* Number remaining in first partition */
+ continue;
+ }
+ if (char_index1 > tmpufix16)
+ {
+ n -= nn + 1; /* Number remaining in second partition */
+ base = i + 1; /* Base index for second partition */
+ continue;
+ }
+ tmpufix16 = NEXT_CHNDX(pointer, long_id);
+ if (char_index2 < tmpufix16)
+ {
+ n = nn; /* Number remaining in first partition */
+ continue;
+ }
+ if (char_index2 > tmpufix16)
+ {
+ n -= nn + 1; /* Number remaining in second partition */
+ base = i + 1; /* Base index for second partition */
+ continue;
+ }
+ adj = (format & BIT0)?
+ (fix31)NEXT_WORD(pointer):
+ (fix31)(adj_base + (fix15)NEXT_BYTE(pointer));
+ adj = ((adj << 16) + (sp_globals.orus_per_em >> 1)) / sp_globals.orus_per_em; /* Convert units */
+ n = 0; /* No more to consider */
+ }
+return adj; /* Return pair kerning adjustment */
+}
+#endif
+
+
+#if INCL_METRICS
+#ifdef old
+FUNCTION boolean get_char_bbox(char_index, bbox)
+GDECL
+ufix16 char_index;
+bbox_t *bbox;
+{
+/*
+ * returns true if character exists, false if it doesn't
+ * provides transformed character bounding box in 1/65536 pixels
+ * in the provided bbox_t structure. Bounding box may be
+ * conservative in the event that the transformation is not
+ * normal or the character is compound.
+ */
+
+ufix8 FONTFAR *pointer;
+fix15 tmp;
+point_t Pmin, Pmax;
+
+#if REENTRANT_ALLOC
+plaid_t plaid;
+sp_globals.plaid = &plaid;
+#endif
+
+if (!sp_globals.specs_valid) /* Font specs not defined? */
+ {
+ report_error(10); /* Report font not specified */
+ return FALSE; /* Error return */
+ }
+
+init_tcb(); /* Initialize transformation control block */
+
+pointer = sp_get_char_org(char_index, TRUE); /* Point to start of character data */
+if (pointer == NULL) /* Character data not available? */
+ {
+ report_error(12); /* Report character data not avail */
+ return FALSE; /* Error return */
+ }
+
+pointer += 2; /* Skip over character id */
+tmp = NEXT_WORD(pointer); /* Read set width */
+
+tmp = NEXT_BYTE(pointer);
+if (tmp & BIT1) /* Optional data in header? */
+ {
+ tmp = (ufix8)NEXT_BYTE(pointer); /* Read size of optional data */
+ pointer += tmp; /* Skip optional data */
+ }
+
+pointer = plaid_tcb(pointer, tmp); /* Process plaid data */
+pointer = read_bbox(pointer, &Pmin, &Pmax,(boolean)FALSE); /* Read bounding box */
+bbox->xmin = (fix31)Pmin.x << sp_globals.poshift;
+bbox->xmax = (fix31)Pmax.x << sp_globals.poshift;
+bbox->ymin = (fix31)Pmin.y << sp_globals.poshift;
+bbox->ymax = (fix31)Pmax.y << sp_globals.poshift;
+return TRUE;
+}
+
+#else /* new code, 4/25/91 */
+
+FUNCTION boolean get_char_bbox(char_index, bbox)
+GDECL
+ufix16 char_index;
+bbox_t *bbox;
+{
+/*
+ * returns true if character exists, false if it doesn't
+ * provides transformed character bounding box in 1/65536 pixels
+ * in the provided bbox_t structure. Bounding box may be
+ * conservative in the event that the transformation is not
+ * normal or the character is compound.
+ */
+
+ufix8 FONTFAR *pointer;
+fix15 tmp;
+fix15 format;
+ufix16 pix_adj;
+point_t Pmin, Pmax;
+
+#if REENTRANT_ALLOC
+plaid_t plaid;
+sp_globals.plaid = &plaid;
+#endif
+
+if (!sp_globals.specs_valid) /* Font specs not defined? */
+ {
+ report_error(10); /* Report font not specified */
+ return FALSE; /* Error return */
+ }
+
+init_tcb(); /* Initialize transformation control block */
+
+pointer = sp_get_char_org(char_index, TRUE); /* Point to start of character data */
+if (pointer == NULL) /* Character data not available? */
+ {
+ report_error(12); /* Report character data not avail */
+ return FALSE; /* Error return */
+ }
+
+pointer += 2; /* Skip over character id */
+tmp = NEXT_WORD(pointer); /* Read set width */
+
+format = NEXT_BYTE(pointer);
+if (format & BIT1) /* Optional data in header? */
+ {
+ tmp = (ufix8)NEXT_BYTE(pointer); /* Read size of optional data */
+ pointer += tmp; /* Skip optional data */
+ }
+
+if (format & BIT0)
+ {
+ pix_adj = sp_globals.onepix << 1; /* Allow 2 pixel expansion ... */
+ }
+else
+ {
+ pix_adj = 0;
+ }
+
+pointer = plaid_tcb(pointer, format); /* Process plaid data */
+pointer = read_bbox(pointer, &Pmin, &Pmax,(boolean)FALSE); /* Read bounding box */
+
+Pmin.x -= pix_adj; /* ... of components of ... */
+Pmin.y -= pix_adj; /* ... compound ... */
+Pmax.x += pix_adj; /* ... character ... */
+Pmax.y += pix_adj; /* ... bounding box. */
+
+
+bbox->xmin = (fix31)Pmin.x << sp_globals.poshift;
+bbox->xmax = (fix31)Pmax.x << sp_globals.poshift;
+bbox->ymin = (fix31)Pmin.y << sp_globals.poshift;
+bbox->ymax = (fix31)Pmax.y << sp_globals.poshift;
+return TRUE;
+}
+#endif /* new code */
+
+#endif
+
+
+#if INCL_ISW
+FUNCTION boolean make_char_isw(char_index,imported_setwidth)
+GDECL
+ufix16 char_index;
+ufix32 imported_setwidth;
+{
+fix15 xmin; /* Minimum X ORU value in font */
+fix15 xmax; /* Maximum X ORU value in font */
+fix15 ymin; /* Minimum Y ORU value in font */
+fix15 ymax; /* Maximum Y ORU value in font */
+ufix16 return_value;
+
+sp_globals.import_setwidth_act = TRUE;
+/* convert imported width to orus */
+sp_globals.imported_width = (sp_globals.metric_resolution *
+ imported_setwidth) >> 16;
+return_value = do_make_char(char_index);
+
+if (sp_globals.isw_modified_constants)
+ {
+ /* reset fixed point constants */
+ xmin = read_word_u(sp_globals.font_org + FH_FXMIN);
+ ymin = read_word_u(sp_globals.font_org + FH_FYMIN);
+ ymax = read_word_u(sp_globals.font_org + FH_FYMAX);
+ sp_globals.constr.data_valid = FALSE;
+ xmax = read_word_u(sp_globals.font_org + FH_FXMAX);
+ if (!setup_consts(xmin,xmax,ymin,ymax))
+ {
+ report_error(3); /* Requested specs out of range */
+ return FALSE;
+ }
+ }
+return (return_value);
+}
+
+FUNCTION boolean make_char(char_index)
+GDECL
+ufix16 char_index; /* Index to character in char directory */
+{
+sp_globals.import_setwidth_act = FALSE;
+return (do_make_char(char_index));
+}
+
+FUNCTION static boolean do_make_char(char_index)
+#else
+FUNCTION boolean make_char(char_index)
+#endif
+/*
+ * Outputs specified character using the currently selected font and
+ * scaling and output specifications.
+ * Reports Error 10 and returns FALSE if no font specifications
+ * previously set.
+ * Reports Error 12 and returns FALSE if character data not available.
+ */
+GDECL
+ufix16 char_index;
+{
+ufix8 FONTFAR *pointer; /* Pointer to character data */
+fix15 x_orus;
+fix15 tmpfix15;
+ufix8 format;
+
+#if INCL_ISW
+sp_globals.isw_modified_constants = FALSE;
+#endif
+
+#if REENTRANT_ALLOC
+
+plaid_t plaid;
+
+#if INCL_BLACK || INCL_SCREEN || INCL_2D
+intercepts_t intercepts;
+sp_globals.intercepts = &intercepts;
+#endif
+
+sp_globals.plaid = &plaid;
+#endif
+
+if (!sp_globals.specs_valid) /* Font specs not defined? */
+ {
+ report_error(10); /* Report font not specified */
+ return FALSE; /* Error return */
+ }
+
+#if INCL_MULTIDEV
+#if INCL_OUTLINE
+if (sp_globals.output_mode == MODE_OUTLINE && !sp_globals.outline_device_set)
+ {
+ report_error(2);
+ return FALSE;
+ }
+else
+#endif
+ if (!sp_globals.bitmap_device_set)
+ {
+ report_error(2);
+ return FALSE;
+ }
+#endif
+
+
+init_tcb(); /* Initialize transformation control block */
+
+pointer = sp_get_char_org(char_index, TRUE); /* Point to start of character data */
+SHOW(pointer);
+if (pointer == NULL) /* Character data not available? */
+ {
+ report_error(12); /* Report character data not avail */
+ return FALSE; /* Error return */
+ }
+
+pointer += 2; /* Skip over character id */
+x_orus = NEXT_WORD(pointer); /* Read set width */
+#if INCL_SQUEEZING || INCL_ISW
+sp_globals.setwidth_orus = x_orus;
+#endif
+
+#if INCL_ISW
+if (sp_globals.import_setwidth_act)
+ x_orus = sp_globals.imported_width;
+#endif
+sp_globals.Psw.x = (fix15)((fix31)
+ (((fix31)x_orus * (sp_globals.specs.xxmult>>16) +
+ ( ((fix31)x_orus * (sp_globals.specs.xxmult&0xffffL) )>>16)
+ ) << sp_globals.pixshift) / sp_globals.metric_resolution);
+
+sp_globals.Psw.y = (fix15)(
+ (fix31)(
+ ((fix31)x_orus * (sp_globals.specs.yxmult>>16) +
+ ( ((fix31)x_orus * (sp_globals.specs.yxmult&0xffffL) )>>16)
+ ) << sp_globals.pixshift) / sp_globals.metric_resolution);
+
+format = NEXT_BYTE(pointer);
+if (format & BIT1) /* Optional data in header? */
+ {
+ tmpfix15 = (ufix8)NEXT_BYTE(pointer); /* Read size of optional data */
+ pointer += tmpfix15; /* Skip optional data */
+ }
+if (format & BIT0)
+ {
+ return sp_make_comp_char(pointer); /* Output compound character */
+ }
+else
+ {
+ return sp_make_simp_char(pointer, format); /* Output simple character */
+ }
+}
+
+FUNCTION static boolean sp_make_simp_char(pointer, format)
+GDECL
+ufix8 FONTFAR *pointer; /* Pointer to first byte of position argument */
+ufix8 format; /* Character format byte */
+/*
+ * Called by sp_make_char() to output a simple (non-compound) character.
+ * Returns TRUE on completion.
+ */
+{
+point_t Pmin, Pmax; /* Transformed corners of bounding box */
+#if INCL_SQUEEZING || INCL_ISW
+ufix8 FONTFAR *save_pointer;
+#endif
+#if INCL_ISW
+fix31 char_width;
+fix31 isw_scale;
+#endif
+
+#if INCL_SQUEEZING
+sp_globals.squeezing_compound = FALSE;
+if ((sp_globals.pspecs->flags & SQUEEZE_LEFT) ||
+ (sp_globals.pspecs->flags & SQUEEZE_RIGHT) ||
+ (sp_globals.pspecs->flags & SQUEEZE_TOP) ||
+ (sp_globals.pspecs->flags & SQUEEZE_BOTTOM) )
+ {
+ /* get the bounding box data before processing the character */
+ save_pointer = pointer;
+ preview_bounding_box (pointer, format);
+ pointer = save_pointer;
+ }
+#endif
+#if (INCL_ISW)
+if (sp_globals.import_setwidth_act)
+ {
+ save_pointer = pointer;
+ preview_bounding_box (pointer, format);
+ pointer = save_pointer;
+ /* make sure I'm not going to get fixed point overflow */
+ isw_scale = compute_isw_scale();
+ if (sp_globals.bbox_xmin_orus < 0)
+ char_width = SQUEEZE_MULT((sp_globals.bbox_xmax_orus - sp_globals.bbox_xmin_orus), isw_scale);
+ else
+ char_width = SQUEEZE_MULT(sp_globals.bbox_xmax_orus, isw_scale);
+ if (char_width >= sp_globals.isw_xmax)
+ if (!reset_xmax(char_width))
+ return FALSE;
+ }
+#endif
+pointer = plaid_tcb(pointer, format); /* Process plaid data */
+pointer = read_bbox(pointer, &Pmin, &Pmax, FALSE); /* Read bounding box */
+if (fn_begin_char(sp_globals.Psw, Pmin, Pmax)) /* Signal start of character output */
+ {
+ do
+ {
+ proc_outl_data(pointer); /* Process outline data */
+ }
+ while (!fn_end_char()); /* Repeat if not done */
+ }
+return TRUE;
+}
+
+FUNCTION static boolean sp_make_comp_char(pointer)
+GDECL
+ufix8 FONTFAR *pointer; /* Pointer to first byte of position argument */
+/*
+ * Called by sp_make_char() to output a compound character.
+ * Returns FALSE if data for any sub-character is not available.
+ * Returns TRUE if output completed with no error.
+ */
+{
+point_t Pmin, Pmax; /* Transformed corners of bounding box */
+point_t Pssw; /* Transformed escapement vector */
+ufix8 FONTFAR *pointer_sav; /* Saved pointer to compound character data */
+ufix8 FONTFAR *sub_pointer; /* Pointer to sub-character data */
+ufix8 format; /* Format of DOCH instruction */
+ufix16 sub_char_index; /* Index to sub-character in character directory */
+fix15 x_posn; /* X position of sub-character (outline res units) */
+fix15 y_posn; /* Y position of sub-character (outline res units) */
+fix15 x_scale; /* X scale factor of sub-character (scale units) */
+fix15 y_scale; /* Y scale factor of sub-character (scale units) */
+fix15 tmpfix15; /* Temporary workspace */
+fix15 x_orus; /* Set width in outline resolution units */
+fix15 pix_adj; /* Pixel adjustment to compound char bounding box */
+#if INCL_SQUEEZING
+fix31 x_factor, x_offset, top_scale, bottom_scale;
+boolean squeezed_x, squeezed_y;
+#endif
+#if INCL_SQUEEZING || INCL_ISW
+fix15 x_offset_pix;
+#endif
+#if INCL_ISW
+fix31 char_width;
+fix31 isw_scale;
+#endif
+
+
+#if INCL_SQUEEZING
+sp_globals.squeezing_compound = TRUE;
+#endif
+pointer = read_bbox(pointer, &Pmin, &Pmax, TRUE); /* Read bounding box data */
+pix_adj = sp_globals.onepix << 1; /* Allow 2 pixel expansion ... */
+Pmin.x -= pix_adj; /* ... of components of ... */
+Pmin.y -= pix_adj; /* ... compound ... */
+Pmax.x += pix_adj; /* ... character ... */
+Pmax.y += pix_adj; /* ... bounding box. */
+
+#if INCL_SQUEEZING
+/* scale the bounding box if necessary before calling begin_char */
+squeezed_x = calculate_x_scale(&x_factor, &x_offset, 0);
+squeezed_y = calculate_y_scale(&top_scale, &bottom_scale,0,0);
+
+if (squeezed_x)
+ { /* scale the x coordinates of the bbox */
+ x_offset_pix = (fix15)(((x_offset >> 16) * sp_globals.tcb0.xppo)
+ >> sp_globals.mpshift);
+ if ((x_offset_pix >0) && (x_offset_pix < sp_globals.onepix))
+ x_offset_pix = sp_globals.onepix;
+ Pmin.x = SQUEEZE_MULT (x_factor, Pmin.x) + x_offset_pix - pix_adj;
+ Pmax.x = SQUEEZE_MULT (x_factor, Pmax.x) + x_offset_pix + pix_adj;
+ }
+if (squeezed_y)
+ { /* scale the y coordinates of the bbox */
+ if ((Pmin.y) < 0)
+ Pmin.y = SQUEEZE_MULT (bottom_scale, Pmin.y) - pix_adj;
+ else
+ Pmin.y = SQUEEZE_MULT (top_scale, Pmin.y) - pix_adj;
+ if ((Pmax.y) < 0)
+ Pmax.y = SQUEEZE_MULT (bottom_scale, Pmax.y) + pix_adj;
+ else
+ Pmax.y = SQUEEZE_MULT (top_scale, Pmax.y) + pix_adj;
+ }
+#endif
+#if (INCL_ISW)
+if (sp_globals.import_setwidth_act)
+ {
+ /* make sure I'm not going to get fixed point overflow */
+ isw_scale = ((fix31)sp_globals.imported_width << 16)/
+ (fix31)sp_globals.setwidth_orus;
+ char_width = SQUEEZE_MULT((sp_globals.bbox_xmax_orus -
+ sp_globals.bbox_xmin_orus),
+isw_scale);
+ if (char_width >= sp_globals.isw_xmax)
+ if (!reset_xmax(char_width))
+ return FALSE;
+ }
+#endif
+
+if (fn_begin_char(sp_globals.Psw, Pmin, Pmax)) /* Signal start of character data */
+ {
+ pointer_sav = pointer;
+ do
+ {
+ pointer = pointer_sav; /* Point to next DOCH or END instruction */
+ while ((format = NEXT_BYTE(pointer))) /* DOCH instruction? */
+ {
+ init_tcb(); /* Initialize transformation control block */
+ x_posn = sp_get_posn_arg(&pointer, format);
+ y_posn = sp_get_posn_arg(&pointer, (ufix8)(format >> 2));
+ x_scale = sp_get_scale_arg(&pointer, (ufix8)(format & BIT4));
+ y_scale = sp_get_scale_arg(&pointer, (ufix8)(format & BIT5));
+ scale_tcb(&sp_globals.tcb, x_posn, y_posn, x_scale, y_scale); /* Scale for sub-char */
+ sub_char_index = (format & BIT6)? /* Read sub-char index */
+ 0xffff & NEXT_WORD(pointer):
+ 0xffff & NEXT_BYTE(pointer);
+ sub_pointer = sp_get_char_org(sub_char_index, FALSE); /* Point to start of sub-char */
+ if (sub_pointer == NULL) /* Character data not available? */
+ {
+ return FALSE; /* Abort character output */
+ }
+ sub_pointer += 2; /* Skip over character id */
+ x_orus = NEXT_WORD(sub_pointer); /* Read set_width of sub-character */
+
+ Pssw.x = (fix15)(
+ (fix31)(
+ ((fix31)x_orus * (sp_globals.specs.xxmult>>16) +
+ ( ((fix31)x_orus * (sp_globals.specs.xxmult&0xffffL) )>>16)
+ ) << sp_globals.pixshift) / sp_globals.metric_resolution);
+ Pssw.y = (fix15)(
+ (fix31)(
+ ((fix31)x_orus * (sp_globals.specs.yxmult>>16) +
+ ( ((fix31)x_orus * (sp_globals.specs.yxmult&0xffffL) )>>16)
+ ) << sp_globals.pixshift) / sp_globals.metric_resolution);
+
+ format = NEXT_BYTE(sub_pointer); /* Read sub-character format */
+ if (format & BIT1) /* Optional data in header? */
+ {
+ tmpfix15 = (ufix8)NEXT_BYTE(sub_pointer); /* Read size of optional data */
+ sub_pointer += tmpfix15; /* Skip optional data */
+ }
+ sub_pointer = plaid_tcb(sub_pointer, format); /* Process sub-character plaid data */
+ sub_pointer = read_bbox(sub_pointer, &Pmin, &Pmax, FALSE); /* Read bounding box */
+ fn_begin_sub_char(Pssw, Pmin, Pmax); /* Signal start of sub-character data */
+ proc_outl_data(sub_pointer); /* Process sub-character data */
+ fn_end_sub_char(); /* Signal end of sub-character data */
+ }
+ }
+ while (!fn_end_char()); /* Signal end of character; repeat if required */
+ }
+return TRUE;
+}
+
+#if INCL_LCD /* Dynamic load character data supported? */
+FUNCTION static ufix8 FONTFAR *sp_get_char_org(char_index, top_level)
+GDECL
+ufix16 char_index; /* Index of character to be accessed */
+boolean top_level; /* Not a compound character element */
+/*
+ * Called by sp_get_char_id(), sp_get_char_width(), sp_make_char() and
+ * sp_make_comp_char() to get a pointer to the start of the character data
+ * for the specified character index.
+ * Version for configuration supporting dynamic character data loading.
+ * Calls load_char_data() to load character data if not already loaded
+ * as part of the original font buffer.
+ * Returns NULL if character data not available
+ */
+{
+buff_t *pchar_data; /* Buffer descriptor requested */
+ufix8 FONTFAR *pointer; /* Pointer into character directory */
+ufix8 format; /* Character directory format byte */
+fix31 char_offset; /* Offset of char data from start of font file */
+fix31 next_char_offset; /* Offset of char data from start of font file */
+fix15 no_bytes; /* Number of bytes required for char data */
+
+if (top_level) /* Not element of compound char? */
+ {
+ if (char_index < sp_globals.first_char_idx) /* Before start of character set? */
+ return NULL;
+ char_index -= sp_globals.first_char_idx;
+ if (char_index >= sp_globals.no_chars_avail) /* Beyond end of character set? */
+ return NULL;
+ sp_globals.cb_offset = 0; /* Reset char buffer offset */
+ }
+
+pointer = sp_globals.pchar_dir;
+format = NEXT_BYTE(pointer); /* Read character directory format byte */
+pointer += char_index << 1; /* Point to indexed character entry */
+if (format) /* 3-byte entries in char directory? */
+ {
+ pointer += char_index; /* Adjust for 3-byte entries */
+ char_offset = read_long(pointer); /* Read file offset to char data */
+ next_char_offset = read_long(pointer + 3); /* Read offset to next char */
+ }
+else
+ {
+ char_offset = (fix31)(0xffff & NEXT_WORD(pointer)); /* Read file offset to char data */
+ next_char_offset = (fix31)(0xffff & NEXT_WORD(pointer)); /* Read offset to next char */
+ }
+
+no_bytes = next_char_offset - char_offset;
+if (no_bytes == 0) /* Character not in directory? */
+ return NULL;
+
+if (next_char_offset <= sp_globals.font_buff_size)/* Character data already in font buffer? */
+ return sp_globals.pfont->org + char_offset; /* Return pointer into font buffer */
+
+pchar_data = load_char_data(char_offset, no_bytes, sp_globals.cb_offset); /* Request char data load */
+if (pchar_data->no_bytes < no_bytes) /* Correct number of bytes loaded? */
+ return NULL;
+
+if (top_level) /* Not element of compound char? */
+ {
+ sp_globals.cb_offset = no_bytes;
+ }
+
+return pchar_data->org; /* Return pointer into character data buffer */
+}
+#endif
+
+#if INCL_LCD
+#else /* Dynamic load character data not supported? */
+FUNCTION static ufix8 FONTFAR *sp_get_char_org(char_index, top_level)
+GDECL
+ufix16 char_index; /* Index of character to be accessed */
+boolean top_level; /* Not a compound character element */
+/*
+ * Called by sp_get_char_id(), sp_get_char_width(), sp_make_char() and
+ * sp_make_comp_char() to get a pointer to the start of the character data
+ * for the specified character index.
+ * Version for configuration not supporting dynamic character data loading.
+ * Returns NULL if character data not available
+ */
+{
+ufix8 FONTFAR *pointer; /* Pointer into character directory */
+ufix8 format; /* Character directory format byte */
+fix31 char_offset; /* Offset of char data from start of font file */
+fix31 next_char_offset; /* Offset of char data from start of font file */
+fix15 no_bytes; /* Number of bytes required for char data */
+
+if (top_level) /* Not element of compound char? */
+ {
+ if (char_index < sp_globals.first_char_idx) /* Before start of character set? */
+ return NULL;
+ char_index -= sp_globals.first_char_idx;
+ if (char_index >= sp_globals.no_chars_avail) /* Beyond end of character set? */
+ return NULL;
+ }
+
+pointer = sp_globals.pchar_dir;
+format = NEXT_BYTE(pointer); /* Read character directory format byte */
+pointer += char_index << 1; /* Point to indexed character entry */
+if (format) /* 3-byte entries in char directory? */
+ {
+ pointer += char_index; /* Adjust for 3-byte entries */
+ char_offset = read_long(pointer); /* Read file offset to char data */
+ next_char_offset = read_long(pointer + 3); /* Read offset to next char */
+ }
+else
+ {
+ char_offset = (fix31)(0xffff & NEXT_WORD(pointer)); /* Read file offset to char data */
+ next_char_offset = (fix31)(0xffff & NEXT_WORD(pointer)); /* Read offset to next char */
+ }
+
+no_bytes = next_char_offset - char_offset;
+if (no_bytes == 0) /* Character not in directory? */
+ return NULL;
+
+return sp_globals.pfont->org + char_offset; /* Return pointer into font buffer */
+}
+#endif
+
+
+FUNCTION static fix15 sp_get_posn_arg(ppointer, format)
+GDECL
+ufix8 FONTFAR * STACKFAR *ppointer; /* Pointer to first byte of position argument */
+ufix8 format; /* Format of DOCH arguments */
+/*
+ * Called by sp_make_comp_char() to read a position argument from the
+ * specified point in the font/char buffer.
+ * Updates pointer to byte following position argument.
+ * Returns value of position argument in outline resolution units
+ */
+{
+switch (format & 0x03)
+ {
+case 1:
+ return NEXT_WORD(*ppointer);
+
+case 2:
+ return (fix15)((fix7)NEXT_BYTE(*ppointer));
+
+default:
+ return (fix15)0;
+ }
+}
+
+FUNCTION static fix15 sp_get_scale_arg(ppointer, format)
+GDECL
+ufix8 FONTFAR *STACKFAR *ppointer; /* Pointer to first byte of position argument */
+ufix8 format; /* Format of DOCH arguments */
+/*
+ * Called by sp_make_comp_char() to read a scale argument from the
+ * specified point in the font/char buffer.
+ * Updates pointer to byte following scale argument.
+ * Returns value of scale argument in scale units (normally 1/4096)
+ */
+{
+if (format)
+ return NEXT_WORD(*ppointer);
+else
+ return (fix15)ONE_SCALE;
+}
+#if INCL_ISW || INCL_SQUEEZING
+FUNCTION static void preview_bounding_box(pointer,format)
+GDECL
+ufix8 FONTFAR *pointer; /* Pointer to first byte of position argument */
+ufix8 format; /* Character format byte */
+{
+point_t Pmin, Pmax; /* Transformed corners of bounding box */
+
+ sp_globals.no_X_orus = (format & BIT2)?
+ (fix15)NEXT_BYTE(pointer):
+ 0;
+ sp_globals.no_Y_orus = (format & BIT3)?
+ (fix15)NEXT_BYTE(pointer):
+ 0;
+ pointer = read_oru_table(pointer);
+
+ /* Skip over control zone table */
+ pointer = skip_control_zone(pointer,format);
+
+ /* Skip over interpolation table */
+ pointer = skip_interpolation_table(pointer,format);
+ /* get_args has a pathological need for this value to be set */
+ sp_globals.Y_edge_org = sp_globals.no_X_orus;
+ pointer = read_bbox(pointer, &Pmin, &Pmax, TRUE); /* Read bounding bo
+x */
+
+}
+#endif
+#if INCL_ISW
+FUNCTION static boolean reset_xmax(xmax)
+GDECL
+fix31 xmax;
+
+{
+fix15 xmin; /* Minimum X ORU value in font */
+fix15 ymin; /* Minimum Y ORU value in font */
+fix15 ymax; /* Maximum Y ORU value in font */
+
+
+sp_globals.isw_modified_constants = TRUE;
+xmin = read_word_u(sp_globals.font_org + FH_FXMIN);
+ymin = read_word_u(sp_globals.font_org + FH_FYMIN);
+ymax = read_word_u(sp_globals.font_org + FH_FYMAX);
+
+if (!setup_consts(xmin,xmax,ymin,ymax))
+ {
+ report_error(3); /* Requested specs out of range */
+ return FALSE;
+ }
+sp_globals.constr.data_valid = FALSE;
+/* recompute setwidth */
+sp_globals.Psw.x = (fix15)((fix31)(
+ ((fix31)sp_globals.imported_width * (sp_globals.specs.xxmult>>16) +
+ ( ((fix31)sp_globals.imported_width *
+ (sp_globals.specs.xxmult&0xffffL) )>>16)
+ ) << sp_globals.pixshift) / sp_globals.metric_resolution);
+sp_globals.Psw.y = (fix15)(
+ (fix31)(
+ ((fix31)sp_globals.imported_width * (sp_globals.specs.yxmult>>16) +
+ ( ((fix31)sp_globals.imported_width * (sp_globals.specs.yxmult&0xffffL) )>>16)
+ ) << sp_globals.pixshift) / sp_globals.metric_resolution);
+
+return TRUE;
+}
+#endif