#define SET_SPCS
#include "spdo_prv.h"
#include "keys.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_setup_consts(PROTO_DECL2 fix15 xmin, fix15 xmax,
fix15 ymin, fix15 ymax);
static void sp_setup_tcb(PROTO_DECL2 tcb_t GLOBALFAR *ptcb);
static fix15 sp_setup_mult(PROTO_DECL2 fix31 input_mult);
static fix31 sp_setup_offset(PROTO_DECL2 fix31 input_offset);
FUNCTION boolean set_specs(
GDECL
specs_t STACKFAR *specsarg)
{
fix31 offcd;
fix31 ofcns;
fix31 cd_size;
fix31 no_bytes_min;
ufix16 font_id;
ufix16 private_off;
fix15 xmin;
fix15 xmax;
fix15 ymin;
fix15 ymax;
sp_globals.specs_valid = FALSE;
sp_globals.specs = *specsarg;
sp_globals.pspecs = &sp_globals.specs;
sp_globals.font = *sp_globals.pspecs->pfont;
sp_globals.pfont = &sp_globals.font;
sp_globals.font_org = sp_globals.font.org;
if (read_word_u(sp_globals.font_org + FH_FMVER + 4) != 0x0d0a)
{
report_error(4);
return FALSE;
}
if (read_word_u(sp_globals.font_org + FH_FMVER + 6) != 0x0000)
{
report_error(4);
return FALSE;
}
if (get_cust_no(*specsarg->pfont) == 0)
{
sp_globals.key32 = 0;
sp_globals.key4 = 0;
sp_globals.key6 = 0;
sp_globals.key7 = 0;
sp_globals.key8 = 0;
}
else
{
sp_globals.key32 = (KEY3 << 8) | KEY2;
sp_globals.key4 = KEY4;
sp_globals.key6 = KEY6;
sp_globals.key7 = KEY7;
sp_globals.key8 = KEY8;
}
sp_globals.no_chars_avail = read_word_u(sp_globals.font_org + FH_NCHRF);
sp_globals.orus_per_em = read_word_u(sp_globals.font_org + FH_ORUPM);
private_off = read_word_u(sp_globals.font_org + FH_HEDSZ);
sp_globals.hdr2_org = sp_globals.font_org + private_off;
if (private_off > EXP_FH_METRES)
{
sp_globals.metric_resolution = read_word_u(sp_globals.font_org + EXP_FH_METRES);
}
else
{
sp_globals.metric_resolution = sp_globals.orus_per_em;
}
#if INCL_METRICS
sp_globals.kern.tkorg = sp_globals.font_org + read_long(sp_globals.hdr2_org + FH_OFFTK);
sp_globals.kern.pkorg = sp_globals.font_org + read_long(sp_globals.hdr2_org + FH_OFFPK);
sp_globals.kern.no_tracks = read_word_u(sp_globals.font_org + FH_NKTKS);
sp_globals.kern.no_pairs = read_word_u(sp_globals.font_org + FH_NKPRS);
#endif
offcd = read_long(sp_globals.hdr2_org + FH_OFFCD);
ofcns = read_long(sp_globals.hdr2_org + FH_OFCNS);
cd_size = ofcns - offcd;
if ((((sp_globals.no_chars_avail << 1) + 3) != cd_size) &&
(((sp_globals.no_chars_avail * 3) + 4) != cd_size))
{
report_error(4);
return FALSE;
}
#if INCL_LCD
#if INCL_METRICS
no_bytes_min = read_long(sp_globals.hdr2_org + FH_OCHRD);
#else
no_bytes_min = read_long(sp_globals.hdr2_org + FH_OFFTK);
#endif
#else
no_bytes_min = read_long(sp_globals.hdr2_org + FH_NBYTE);
#endif
sp_globals.font_buff_size = sp_globals.pfont->no_bytes;
if (sp_globals.font_buff_size < no_bytes_min)
{
report_error(1);
return FALSE;
}
sp_globals.pchar_dir = sp_globals.font_org + offcd;
sp_globals.first_char_idx = read_word_u(sp_globals.font_org + FH_FCHRF);
#if INCL_RULES
font_id = read_word_u(sp_globals.font_org + FH_FNTID);
if (!(sp_globals.constr.font_id_valid) || (sp_globals.constr.font_id != font_id))
{
sp_globals.constr.font_id = font_id;
sp_globals.constr.font_id_valid = TRUE;
sp_globals.constr.data_valid = FALSE;
}
sp_globals.constr.org = sp_globals.font_org + ofcns;
sp_globals.constr.active = ((sp_globals.pspecs->flags & CONSTR_OFF) == 0);
#endif
xmin = read_word_u(sp_globals.font_org + FH_FXMIN);
xmax = read_word_u(sp_globals.font_org + FH_FXMAX);
ymin = read_word_u(sp_globals.font_org + FH_FYMIN);
ymax = read_word_u(sp_globals.font_org + FH_FYMAX);
if (!sp_setup_consts(xmin,xmax,ymin,ymax))
{
report_error(3);
return FALSE;
}
#if INCL_ISW
sp_globals.isw_xmax = xmax;
#endif
sp_setup_tcb(&sp_globals.tcb0);
sp_globals.output_mode = sp_globals.pspecs->flags & 0x0007;
#if INCL_USEROUT
if (!init_userout(sp_globals.pspecs))
#endif
switch (sp_globals.output_mode)
{
#if INCL_BLACK
case MODE_BLACK:
sp_globals.init_out = sp_init_black;
sp_globals.begin_char = sp_begin_char_black;
sp_globals.begin_sub_char = sp_begin_sub_char_out;
sp_globals.begin_contour = sp_begin_contour_black;
sp_globals.curve = sp_curve_out;
sp_globals.line = sp_line_black;
sp_globals.end_contour = sp_end_contour_out;
sp_globals.end_sub_char = sp_end_sub_char_out;
sp_globals.end_char = sp_end_char_black;
break;
#endif
#if INCL_SCREEN
case MODE_SCREEN:
sp_globals.init_out = sp_init_screen;
sp_globals.begin_char = sp_begin_char_screen;
sp_globals.begin_sub_char = sp_begin_sub_char_out;
sp_globals.begin_contour = sp_begin_contour_screen;
sp_globals.curve = sp_curve_screen;
sp_globals.line = sp_line_screen;
sp_globals.end_contour = sp_end_contour_screen;
sp_globals.end_sub_char = sp_end_sub_char_out;
sp_globals.end_char = sp_end_char_screen;
break;
#endif
#if INCL_OUTLINE
case MODE_OUTLINE:
sp_globals.init_out = sp_init_outline;
sp_globals.begin_char = sp_begin_char_outline;
sp_globals.begin_sub_char = sp_begin_sub_char_outline;
sp_globals.begin_contour = sp_begin_contour_outline;
sp_globals.curve = sp_curve_outline;
sp_globals.line = sp_line_outline;
sp_globals.end_contour = sp_end_contour_outline;
sp_globals.end_sub_char = sp_end_sub_char_outline;
sp_globals.end_char = sp_end_char_outline;
break;
#endif
#if INCL_2D
case MODE_2D:
sp_globals.init_out = sp_init_2d;
sp_globals.begin_char = sp_begin_char_2d;
sp_globals.begin_sub_char = sp_begin_sub_char_out;
sp_globals.begin_contour = sp_begin_contour_2d;
sp_globals.curve = sp_curve_out;
sp_globals.line = sp_line_2d;
sp_globals.end_contour = sp_end_contour_out;
sp_globals.end_sub_char = sp_end_sub_char_out;
sp_globals.end_char = sp_end_char_2d;
break;
#endif
default:
report_error(8);
return FALSE;
}
if (!fn_init_out(sp_globals.pspecs))
{
report_error(5);
return FALSE;
}
sp_globals.curves_out = sp_globals.pspecs->flags & CURVES_OUT;
if (sp_globals.pspecs->flags & BOGUS_MODE)
{
sp_globals.tcb0.xtype = sp_globals.tcb0.ytype = 4;
}
else
{
#if INCL_RULES
#else
report_error(7);
return FALSE;
#endif
}
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) )
{
#if (INCL_SQUEEZING)
#else
report_error(11);
return FALSE;
#endif
}
if ((sp_globals.pspecs->flags & CLIP_LEFT) ||
(sp_globals.pspecs->flags & CLIP_RIGHT) ||
(sp_globals.pspecs->flags & CLIP_TOP) ||
(sp_globals.pspecs->flags & CLIP_BOTTOM) )
{
#if (INCL_CLIPPING)
#else
report_error(11);
return FALSE;
#endif
}
sp_globals.specs_valid = TRUE;
return TRUE;
}
#if INCL_MULTIDEV
#if INCL_BLACK || INCL_SCREEN || INCL_2D
FUNCTION boolean set_bitmap_device(
GDECL
bitmap_t *bfuncs,
ufix16 size)
{
if (size != sizeof(sp_globals.bitmap_device))
return FALSE;
sp_globals.bitmap_device = *bfuncs;
sp_globals.bitmap_device_set = TRUE;
}
#endif
#if INCL_OUTLINE
FUNCTION boolean set_outline_device(
GDECL
outline_t *ofuncs,
ufix16 size)
{
if (size != sizeof(sp_globals.outline_device))
return FALSE;
sp_globals.outline_device = *ofuncs;
sp_globals.outline_device_set = TRUE;
}
#endif
#endif
#ifdef old
FUNCTION boolean sp_setup_consts(
GDECL
fix15 xmin,
fix15 xmax,
fix15 ymin,
fix15 ymax)
#else
static FUNCTION boolean sp_setup_consts(
GDECL
fix15 xmin,
fix15 xmax,
fix15 ymin,
fix15 ymax)
#endif
{
fix31 mult;
ufix32 num;
ufix32 numcopy;
ufix32 denom;
ufix32 denomcopy;
ufix32 pix_max;
fix31 xmult;
fix31 ymult;
fix31 offset;
fix15 i;
fix15 x, y;
fix31 pixval;
fix15 xx = 0, yy = 0;
mult = sp_globals.pspecs->xxmult >> 16;
if (mult < 0)
mult = -mult;
num = mult;
mult = sp_globals.pspecs->xymult >> 16;
if (mult < 0)
mult = -mult;
if (mult > num)
num = mult;
mult = sp_globals.pspecs->yxmult >> 16;
if (mult < 0)
mult = -mult;
if (mult > num)
num = mult;
mult = sp_globals.pspecs->yymult >> 16;
if (mult < 0)
mult = -mult;
if (mult > num)
num = mult;
num++;
denom = (ufix32)sp_globals.orus_per_em;
sp_globals.depth_adj = 0;
denomcopy = denom;
while ((num > denomcopy) && (sp_globals.depth_adj < 5))
{
denomcopy <<= 1;
denomcopy <<= 1;
sp_globals.depth_adj++;
}
numcopy = num << 2;
while ((numcopy <= denom) && (sp_globals.depth_adj > -4))
{
numcopy <<= 1;
numcopy <<= 1;
sp_globals.depth_adj--;
}
SHOW(sp_globals.depth_adj);
sp_globals.multshift = 14;
numcopy = num;
while (numcopy >= denom)
{
numcopy >>= 1;
sp_globals.multshift--;
}
sp_globals.multrnd = ((fix31)1 << sp_globals.multshift) >> 1;
SHOW(sp_globals.multshift);
pix_max = (ufix32)( 0xffff & read_word_u(sp_globals.hdr2_org + FH_PIXMX));
num = 0;
xmult = ((sp_globals.pspecs->xxmult >> 16) + 1) >> 1;
ymult = ((sp_globals.pspecs->xymult >> 16) + 1) >> 1;
offset = ((sp_globals.pspecs->xoffset >> 16) + 1) >> 1;
for (i = 0; i < 8; i++)
{
if (i == 4)
{
xmult = ((sp_globals.pspecs->yxmult >> 16) + 1) >> 1;
ymult = ((sp_globals.pspecs->yymult >> 16) + 1) >> 1;
offset = ((sp_globals.pspecs->yoffset >> 16) + 1) >> 1;
}
x = (i & BIT1)? xmin: xmax;
y = (i & BIT0)? ymin: ymax;
pixval = (fix31)x * xmult + (fix31)y * ymult + offset * denom;
if (pixval < 0)
pixval = -pixval;
if (pixval > num)
{
num = pixval;
xx = x;
yy = y;
}
}
if (xx < 0)
xx = -xx;
if (yy < 0)
yy = -yy;
num += xx + yy + ((pix_max + 2) * denom);
denom = denom << 14;
sp_globals.pixshift = -1;
while ((num <= denom) && (sp_globals.pixshift < 8))
{
num <<= 1;
sp_globals.pixshift++;
}
if (sp_globals.pixshift < 0)
return FALSE;
SHOW(sp_globals.pixshift);
sp_globals.poshift = 16 - sp_globals.pixshift;
sp_globals.onepix = (fix15)1 << sp_globals.pixshift;
sp_globals.pixrnd = sp_globals.onepix >> 1;
sp_globals.pixfix = ~0 << sp_globals.pixshift;
sp_globals.mpshift = sp_globals.multshift - sp_globals.pixshift;
if (sp_globals.mpshift < 0)
return FALSE;
sp_globals.mprnd = ((fix31)1 << sp_globals.mpshift) >> 1;
return TRUE;
}
#ifdef old
FUNCTION void sp_setup_tcb(
GDECL
tcb_t GLOBALFAR *ptcb)
#else
static FUNCTION void sp_setup_tcb(
GDECL
tcb_t GLOBALFAR *ptcb)
#endif
{
ptcb->xxmult = sp_setup_mult(sp_globals.pspecs->xxmult);
ptcb->xymult = sp_setup_mult(sp_globals.pspecs->xymult);
ptcb->xoffset = sp_setup_offset(sp_globals.pspecs->xoffset);
ptcb->yxmult = sp_setup_mult(sp_globals.pspecs->yxmult);
ptcb->yymult = sp_setup_mult(sp_globals.pspecs->yymult);
ptcb->yoffset = sp_setup_offset(sp_globals.pspecs->yoffset);
SHOW(ptcb->xxmult);
SHOW(ptcb->xymult);
SHOW(ptcb->xoffset);
SHOW(ptcb->yxmult);
SHOW(ptcb->yymult);
SHOW(ptcb->yoffset);
type_tcb(ptcb);
}
FUNCTION static fix15 sp_setup_mult(
GDECL
fix31 input_mult)
{
fix15 imshift;
fix31 imdenom;
fix31 imrnd;
imshift = 15 - sp_globals.multshift;
imdenom = (fix31)sp_globals.orus_per_em << imshift;
imrnd = imdenom >> 1;
input_mult >>= 1;
if (input_mult >= 0)
return (fix15)((input_mult + imrnd) / imdenom);
else
return -(fix15)((-input_mult + imrnd) / imdenom);
}
FUNCTION static fix31 sp_setup_offset(
GDECL
fix31 input_offset)
{
fix15 imshift;
fix31 imrnd;
imshift = 15 - sp_globals.multshift;
imrnd = ((fix31)1 << imshift) >> 1;
return (((input_offset >> 1) + imrnd) >> imshift) + sp_globals.mprnd;
}
FUNCTION void type_tcb(
GDECL
tcb_t GLOBALFAR *ptcb)
{
fix15 x_trans_type;
fix15 y_trans_type;
fix15 xx_mult;
fix15 xy_mult;
fix15 yx_mult;
fix15 yy_mult;
fix15 h_pos;
fix15 v_pos;
fix15 x_ppo;
fix15 y_ppo;
fix15 x_pos;
fix15 y_pos;
xx_mult = ptcb->xxmult;
xy_mult = ptcb->xymult;
yx_mult = ptcb->yxmult;
yy_mult = ptcb->yymult;
ptcb->mirror = ((((fix31)xx_mult*(fix31)yy_mult)-
((fix31)xy_mult*(fix31)yx_mult)) < 0) ? -1 : 1;
if (sp_globals.pspecs->flags & BOGUS_MODE)
{
ptcb->xtype = 4;
ptcb->ytype = 4;
ptcb->xppo = 0;
ptcb->yppo = 0;
ptcb->xpos = 0;
ptcb->ypos = 0;
}
else
{
h_pos = ((ptcb->xoffset >> sp_globals.mpshift) + sp_globals.pixrnd) & sp_globals.pixfix;
v_pos = ((ptcb->yoffset >> sp_globals.mpshift) + sp_globals.pixrnd) & sp_globals.pixfix;
x_trans_type = 4;
x_ppo = 0;
x_pos = 0;
y_trans_type = 4;
y_ppo = 0;
y_pos = 0;
if (xy_mult == 0)
{
if (xx_mult >= 0)
{
x_trans_type = 0;
x_ppo = xx_mult;
x_pos = h_pos;
}
else
{
x_trans_type = 1;
x_ppo = -xx_mult;
x_pos = -h_pos;
}
}
else if (xx_mult == 0)
{
if (xy_mult >= 0)
{
x_trans_type = 2;
y_ppo = xy_mult;
y_pos = h_pos;
}
else
{
x_trans_type = 3;
y_ppo = -xy_mult;
y_pos = -h_pos;
}
}
if (yx_mult == 0)
{
if (yy_mult >= 0)
{
y_trans_type = 0;
y_ppo = yy_mult;
y_pos = v_pos;
}
else
{
y_trans_type = 1;
y_ppo = -yy_mult;
y_pos = -v_pos;
}
}
else if (yy_mult == 0)
{
if (yx_mult >= 0)
{
y_trans_type = 2;
x_ppo = yx_mult;
x_pos = v_pos;
}
else
{
y_trans_type = 3;
x_ppo = -yx_mult;
x_pos = -v_pos;
}
}
ptcb->xtype = x_trans_type;
ptcb->ytype = y_trans_type;
ptcb->xppo = x_ppo;
ptcb->yppo = y_ppo;
ptcb->xpos = x_pos;
ptcb->ypos = y_pos;
}
sp_globals.normal = (ptcb->xtype != 4) && (ptcb->ytype != 4);
ptcb->xmode = 4;
ptcb->ymode = 4;
SHOW(ptcb->xtype);
SHOW(ptcb->ytype);
SHOW(ptcb->xppo);
SHOW(ptcb->yppo);
SHOW(ptcb->xpos);
SHOW(ptcb->ypos);
}
FUNCTION fix31 read_long(
GDECL
ufix8 FONTFAR *pointer)
{
fix31 tmpfix31;
tmpfix31 = (fix31)((*pointer++) ^ sp_globals.key4) << 8;
tmpfix31 += (fix31)(*pointer++) << 16;
tmpfix31 += (fix31)((*pointer) ^ sp_globals.key6);
return tmpfix31;
}
FUNCTION fix15 read_word_u(
GDECL
ufix8 FONTFAR *pointer)
{
fix15 tmpfix15;
tmpfix15 = (fix15)(*pointer++) << 8;
tmpfix15 += (fix15)(*pointer);
return tmpfix15;
}