#include "spdo_prv.h"
#define DEBUG 0
#if DEBUG
#include <stdio.h>
#define SHOW(X) printf("X = %d\n", X)
#else
#define SHOW(X)
#endif
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);
FUNCTION ufix16 get_char_id(
GDECL
ufix16 char_index)
{
ufix8 FONTFAR *pointer;
if (!sp_globals.specs_valid)
{
report_error(10);
return (ufix16)0;
}
pointer = sp_get_char_org(char_index, TRUE);
if (pointer == NULL)
{
report_error(12);
return (ufix16)0;
}
return 0xffff & NEXT_WORD(pointer);
}
#if INCL_METRICS
FUNCTION fix31 get_char_width(
GDECL
ufix16 char_index)
{
ufix8 FONTFAR *pointer;
fix31 set_width;
if (!sp_globals.specs_valid)
{
report_error(10);
return (fix31)0;
}
pointer = sp_get_char_org(char_index, TRUE);
if (pointer == NULL)
{
report_error(12);
return (fix31)0;
}
pointer += 2;
set_width = (fix31)NEXT_WORD(pointer);
set_width = ((set_width << 16) + (sp_globals.metric_resolution >> 1)) / sp_globals.metric_resolution;
return set_width;
}
#endif
#if INCL_METRICS
FUNCTION fix15 get_track_kern(
GDECL
fix15 track,
fix15 point_size)
{
ufix8 FONTFAR *pointer;
fix15 no_tracks;
ufix8 format;
fix15 i;
fix15 min_pt_size = 0;
fix15 max_pt_size = 0;
fix15 min_adj = 0;
fix15 max_adj = 0;
fix31 delta_pt_size;
fix31 delta_adj;
fix15 adj = 0;
if (track == 0)
{
return adj;
}
if (!sp_globals.specs_valid)
{
report_error(10);
return adj;
}
no_tracks = sp_globals.kern.no_tracks;
if (track > no_tracks)
{
report_error(13);
return adj;
}
pointer = sp_globals.kern.tkorg;
for (i = 0; i < track; i++)
{
format = NEXT_BYTE(pointer);
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)
{
return min_adj;
}
if (point_size >= max_pt_size)
{
return max_adj;
}
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;
}
#endif
#if INCL_METRICS
FUNCTION fix31 get_pair_kern(
GDECL
ufix16 char_index1,
ufix16 char_index2)
{
ufix8 FONTFAR *origin;
ufix8 FONTFAR *pointer;
ufix16 tmpufix16;
fix15 no_pairs;
ufix8 format;
boolean long_id;
fix15 rec_size;
fix15 n;
fix15 nn;
fix15 base;
fix15 i;
fix31 adj = 0;
fix15 adj_base = 0;
if (!sp_globals.specs_valid)
{
report_error(10);
return adj;
}
no_pairs = sp_globals.kern.no_pairs;
if (no_pairs == 0)
{
report_error(14);
return adj;
}
pointer = sp_globals.kern.pkorg;
format = NEXT_BYTE(pointer);
if (!(format & BIT0))
adj_base = NEXT_WORD(pointer);
origin = pointer;
rec_size = format + 3;
long_id = format & BIT1;
n = no_pairs;
base = 0;
while (n != 0)
{
nn = n >> 1;
i = base + nn;
pointer = origin + (i * rec_size);
tmpufix16 = NEXT_CHNDX(pointer, long_id);
if (char_index1 < tmpufix16)
{
n = nn;
continue;
}
if (char_index1 > tmpufix16)
{
n -= nn + 1;
base = i + 1;
continue;
}
tmpufix16 = NEXT_CHNDX(pointer, long_id);
if (char_index2 < tmpufix16)
{
n = nn;
continue;
}
if (char_index2 > tmpufix16)
{
n -= nn + 1;
base = i + 1;
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;
n = 0;
}
return adj;
}
#endif
#if INCL_METRICS
#ifdef old
FUNCTION boolean get_char_bbox(
GDECL
ufix16 char_index,
bbox_t *bbox)
{
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)
{
report_error(10);
return FALSE;
}
init_tcb();
pointer = sp_get_char_org(char_index, TRUE);
if (pointer == NULL)
{
report_error(12);
return FALSE;
}
pointer += 2;
tmp = NEXT_WORD(pointer);
tmp = NEXT_BYTE(pointer);
if (tmp & BIT1)
{
tmp = (ufix8)NEXT_BYTE(pointer);
pointer += tmp;
}
pointer = plaid_tcb(pointer, tmp);
pointer = read_bbox(pointer, &Pmin, &Pmax,(boolean)FALSE);
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
FUNCTION boolean get_char_bbox(
GDECL
ufix16 char_index,
bbox_t *bbox)
{
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)
{
report_error(10);
return FALSE;
}
init_tcb();
pointer = sp_get_char_org(char_index, TRUE);
if (pointer == NULL)
{
report_error(12);
return FALSE;
}
pointer += 2;
tmp = NEXT_WORD(pointer);
format = NEXT_BYTE(pointer);
if (format & BIT1)
{
tmp = (ufix8)NEXT_BYTE(pointer);
pointer += tmp;
}
if (format & BIT0)
{
pix_adj = sp_globals.onepix << 1;
}
else
{
pix_adj = 0;
}
pointer = plaid_tcb(pointer, format);
pointer = read_bbox(pointer, &Pmin, &Pmax,(boolean)FALSE);
Pmin.x -= pix_adj;
Pmin.y -= pix_adj;
Pmax.x += pix_adj;
Pmax.y += pix_adj;
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
#endif
#if INCL_ISW
FUNCTION boolean make_char_isw(
GDECL
ufix16 char_index,
ufix32 imported_setwidth)
{
fix15 xmin;
fix15 xmax;
fix15 ymin;
fix15 ymax;
ufix16 return_value;
sp_globals.import_setwidth_act = TRUE;
sp_globals.imported_width = (sp_globals.metric_resolution *
imported_setwidth) >> 16;
return_value = do_make_char(char_index);
if (sp_globals.isw_modified_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);
return FALSE;
}
}
return (return_value);
}
FUNCTION boolean make_char(
GDECL
ufix16 char_index)
{
sp_globals.import_setwidth_act = FALSE;
return (do_make_char(char_index));
}
FUNCTION static boolean do_make_char(GDECL ufix16 char_index)
#else
FUNCTION boolean make_char(GDECL ufix16 char_index)
#endif
{
ufix8 FONTFAR *pointer;
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)
{
report_error(10);
return FALSE;
}
#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();
pointer = sp_get_char_org(char_index, TRUE);
SHOW(pointer);
if (pointer == NULL)
{
report_error(12);
return FALSE;
}
pointer += 2;
x_orus = NEXT_WORD(pointer);
#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)
{
tmpfix15 = (ufix8)NEXT_BYTE(pointer);
pointer += tmpfix15;
}
if (format & BIT0)
{
return sp_make_comp_char(pointer);
}
else
{
return sp_make_simp_char(pointer, format);
}
}
FUNCTION static boolean sp_make_simp_char(
GDECL
ufix8 FONTFAR *pointer,
ufix8 format)
{
point_t Pmin, Pmax;
#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) )
{
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;
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);
pointer = read_bbox(pointer, &Pmin, &Pmax, FALSE);
if (fn_begin_char(sp_globals.Psw, Pmin, Pmax))
{
do
{
proc_outl_data(pointer);
}
while (!fn_end_char());
}
return TRUE;
}
FUNCTION static boolean sp_make_comp_char(
GDECL
ufix8 FONTFAR *pointer)
{
point_t Pmin, Pmax;
point_t Pssw;
ufix8 FONTFAR *pointer_sav;
ufix8 FONTFAR *sub_pointer;
ufix8 format;
ufix16 sub_char_index;
fix15 x_posn;
fix15 y_posn;
fix15 x_scale;
fix15 y_scale;
fix15 tmpfix15;
fix15 x_orus;
fix15 pix_adj;
#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);
pix_adj = sp_globals.onepix << 1;
Pmin.x -= pix_adj;
Pmin.y -= pix_adj;
Pmax.x += pix_adj;
Pmax.y += pix_adj;
#if INCL_SQUEEZING
squeezed_x = calculate_x_scale(&x_factor, &x_offset, 0);
squeezed_y = calculate_y_scale(&top_scale, &bottom_scale,0,0);
if (squeezed_x)
{
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)
{
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)
{
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))
{
pointer_sav = pointer;
do
{
pointer = pointer_sav;
while ((format = NEXT_BYTE(pointer)))
{
init_tcb();
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);
sub_char_index = (format & BIT6)?
0xffff & NEXT_WORD(pointer):
0xffff & NEXT_BYTE(pointer);
sub_pointer = sp_get_char_org(sub_char_index, FALSE);
if (sub_pointer == NULL)
{
return FALSE;
}
sub_pointer += 2;
x_orus = NEXT_WORD(sub_pointer);
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);
if (format & BIT1)
{
tmpfix15 = (ufix8)NEXT_BYTE(sub_pointer);
sub_pointer += tmpfix15;
}
sub_pointer = plaid_tcb(sub_pointer, format);
sub_pointer = read_bbox(sub_pointer, &Pmin, &Pmax, FALSE);
fn_begin_sub_char(Pssw, Pmin, Pmax);
proc_outl_data(sub_pointer);
fn_end_sub_char();
}
}
while (!fn_end_char());
}
return TRUE;
}
#if INCL_LCD
FUNCTION static ufix8 FONTFAR *sp_get_char_org(
GDECL
ufix16 char_index,
boolean top_level)
{
buff_t *pchar_data;
ufix8 FONTFAR *pointer;
ufix8 format;
fix31 char_offset;
fix31 next_char_offset;
fix15 no_bytes;
if (top_level)
{
if (char_index < sp_globals.first_char_idx)
return NULL;
char_index -= sp_globals.first_char_idx;
if (char_index >= sp_globals.no_chars_avail)
return NULL;
sp_globals.cb_offset = 0;
}
pointer = sp_globals.pchar_dir;
format = NEXT_BYTE(pointer);
pointer += char_index << 1;
if (format)
{
pointer += char_index;
char_offset = read_long(pointer);
next_char_offset = read_long(pointer + 3);
}
else
{
char_offset = (fix31)(0xffff & NEXT_WORD(pointer));
next_char_offset = (fix31)(0xffff & NEXT_WORD(pointer));
}
no_bytes = next_char_offset - char_offset;
if (no_bytes == 0)
return NULL;
if (next_char_offset <= sp_globals.font_buff_size)
return sp_globals.pfont->org + char_offset;
pchar_data = load_char_data(char_offset, no_bytes, sp_globals.cb_offset);
if (pchar_data->no_bytes < no_bytes)
return NULL;
if (top_level)
{
sp_globals.cb_offset = no_bytes;
}
return pchar_data->org;
}
#endif
#if INCL_LCD
#else
FUNCTION static ufix8 FONTFAR *sp_get_char_org(
GDECL
ufix16 char_index,
boolean top_level)
{
ufix8 FONTFAR *pointer;
ufix8 format;
fix31 char_offset;
fix31 next_char_offset;
fix15 no_bytes;
if (top_level)
{
if (char_index < sp_globals.first_char_idx)
return NULL;
char_index -= sp_globals.first_char_idx;
if (char_index >= sp_globals.no_chars_avail)
return NULL;
}
pointer = sp_globals.pchar_dir;
format = NEXT_BYTE(pointer);
pointer += char_index << 1;
if (format)
{
pointer += char_index;
char_offset = read_long(pointer);
next_char_offset = read_long(pointer + 3);
}
else
{
char_offset = (fix31)(0xffff & NEXT_WORD(pointer));
next_char_offset = (fix31)(0xffff & NEXT_WORD(pointer));
}
no_bytes = next_char_offset - char_offset;
if (no_bytes == 0)
return NULL;
return sp_globals.pfont->org + char_offset;
}
#endif
FUNCTION static fix15 sp_get_posn_arg(
GDECL
ufix8 FONTFAR * STACKFAR *ppointer,
ufix8 format)
{
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(
GDECL
ufix8 FONTFAR *STACKFAR *ppointer,
ufix8 format)
{
if (format)
return NEXT_WORD(*ppointer);
else
return (fix15)ONE_SCALE;
}
#if INCL_ISW || INCL_SQUEEZING
FUNCTION static void preview_bounding_box(
GDECL
ufix8 FONTFAR *pointer,
ufix8 format)
{
point_t Pmin, Pmax;
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);
pointer = skip_control_zone(pointer,format);
pointer = skip_interpolation_table(pointer,format);
sp_globals.Y_edge_org = sp_globals.no_X_orus;
pointer = read_bbox(pointer, &Pmin, &Pmax, TRUE);
}
#endif
#if INCL_ISW
FUNCTION static boolean reset_xmax(
GDECL
fix31 xmax)
{
fix15 xmin;
fix15 ymin;
fix15 ymax;
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);
return FALSE;
}
sp_globals.constr.data_valid = FALSE;
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