X-Git-Url: https://git.sesse.net/?p=rdpsrv;a=blobdiff_plain;f=Xserver%2Flib%2Ffont%2FSpeedo%2Fdo_char.c;fp=Xserver%2Flib%2Ffont%2FSpeedo%2Fdo_char.c;h=22ac5a92e77ef2ab7bc7624c4c03ed3c692d77e3;hp=0000000000000000000000000000000000000000;hb=b6e6afccf37f4ad0515ef2a698f714fdf1bf23b3;hpb=e3340a110a3b01756b8e67531395a33b40a17d37 diff --git a/Xserver/lib/font/Speedo/do_char.c b/Xserver/lib/font/Speedo/do_char.c new file mode 100644 index 0000000..22ac5a9 --- /dev/null +++ b/Xserver/lib/font/Speedo/do_char.c @@ -0,0 +1,1022 @@ +/* $XConsortium: do_char.c /main/5 1995/10/24 11:22:28 gildea $ */ + +/* + +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 +#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