]> git.sesse.net Git - rdpsrv/blob - Xserver/lib/font/Speedo/set_spcs.c
Import X server from vnc-3.3.7.
[rdpsrv] / Xserver / lib / font / Speedo / set_spcs.c
1 /* $XConsortium: set_spcs.c,v 1.6 94/02/10 10:18:23 gildea Exp $ */
2
3 /*
4
5 Copyright 1989-1991, Bitstream Inc., Cambridge, MA.
6 You are hereby granted permission under all Bitstream propriety rights to
7 use, copy, modify, sublicense, sell, and redistribute the Bitstream Speedo
8 software and the Bitstream Charter outline font for any purpose and without
9 restrictions; provided, that this notice is left intact on all copies of such
10 software or font and that Bitstream's trademark is acknowledged as shown below
11 on all unmodified copies of such font.
12
13 BITSTREAM CHARTER is a registered trademark of Bitstream Inc.
14
15
16 BITSTREAM INC. DISCLAIMS ANY AND ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
17 WITHOUT LIMITATION THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
18 PARTICULAR PURPOSE.  BITSTREAM SHALL NOT BE LIABLE FOR ANY DIRECT OR INDIRECT
19 DAMAGES, INCLUDING BUT NOT LIMITED TO LOST PROFITS, LOST DATA, OR ANY OTHER
20 INCIDENTAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF OR IN ANY WAY CONNECTED
21 WITH THE SPEEDO SOFTWARE OR THE BITSTREAM CHARTER OUTLINE FONT.
22
23 */
24
25
26 /*************************** S E T _ S P C S . C *****************************
27  *                                                                           *
28  * This module implements all sp_set_specs() functionality.                  *
29  *                                                                           *
30  ****************************************************************************/
31 #define SET_SPCS
32 #include "spdo_prv.h"               /* General definitions for Speedo    */
33 #include "keys.h"
34
35 #define   DEBUG      0
36
37 #if DEBUG
38 #include <stdio.h>
39 #define SHOW(X) printf("X = %d\n", X)
40 #else
41 #define SHOW(X)
42 #endif
43
44 /***** GLOBAL VARIABLES *****/
45
46 /***** GLOBAL FUNCTIONS *****/
47
48 /****** EXTERNAL VARIABLES *****/
49
50 /***** STATIC VARIABLES *****/
51
52
53 /****** STATIC FUNCTIONS *****/
54
55 #if PROTOS_AVAIL
56 static boolean sp_setup_consts(PROTO_DECL2 fix15 xmin, fix15 xmax,
57         fix15 ymin, fix15 ymax);
58 static void sp_setup_tcb(PROTO_DECL2 tcb_t GLOBALFAR *ptcb);
59 static fix15 sp_setup_mult(PROTO_DECL2 fix31 input_mult);
60 static fix31 sp_setup_offset(PROTO_DECL2 fix31 input_offset);
61 #else
62 static void    sp_setup_tcb();      /* Set up transformation control block */
63 static fix15 sp_setup_mult();       /* Convert mult to internal form */
64 static fix31 sp_setup_offset();     /* Convert offset to internal form */
65 static boolean sp_setup_consts();   /* Set up scaling constants */
66 #endif
67
68
69 \f
70 FUNCTION boolean set_specs(specsarg)
71 GDECL
72 specs_t STACKFAR *specsarg;     /* Bundle of conversion specifications */
73 /* 
74  * Called by host software to set character generation specifications
75  */
76 {
77 ufix8 FONTFAR  *pointer;       /* Pointer to font data */
78 fix31   offcd;         /* Offset to start of character directory */
79 fix31   ofcns;         /* Offset to start of constraint data */ 
80 fix31   cd_size;       /* Size of character directory */
81 fix31   no_bytes_min;  /* Min number of bytes in font buffer */
82 ufix16  font_id;       /* Font ID */
83 ufix16  private_off;   /* offset to private header */
84 fix15   xmin;          /* Minimum X ORU value in font */
85 fix15   xmax;          /* Maximum X ORU value in font */
86 fix15   ymin;          /* Minimum Y ORU value in font */
87 fix15   ymax;          /* Maximum Y ORU value in font */
88
89 sp_globals.specs_valid = FALSE;           /* Flag specs not valid */
90
91 sp_globals.specs = *specsarg;   /* copy specs structure into sp_globals */
92 sp_globals.pspecs = &sp_globals.specs;
93 sp_globals.font = *sp_globals.pspecs->pfont;
94 sp_globals.pfont = &sp_globals.font;
95 sp_globals.font_org = sp_globals.font.org;
96
97 if (read_word_u(sp_globals.font_org + FH_FMVER + 4) != 0x0d0a)
98     {
99     report_error(4);           /* Font format error */
100     return FALSE;
101     }
102 if (read_word_u(sp_globals.font_org + FH_FMVER + 6) != 0x0000)
103     {
104     report_error(4);           /* Font format error */
105     return FALSE;
106     }
107
108 if (get_cust_no(*specsarg->pfont) == 0)
109         {
110         sp_globals.key32 = 0;
111         sp_globals.key4 = 0;
112         sp_globals.key6 = 0;
113         sp_globals.key7 = 0;
114         sp_globals.key8 = 0;
115         }
116 else
117         {
118         sp_globals.key32 = (KEY3 << 8) | KEY2;
119         sp_globals.key4 = KEY4;
120         sp_globals.key6 = KEY6;
121         sp_globals.key7 = KEY7;
122         sp_globals.key8 = KEY8;
123         }
124         
125
126 sp_globals.no_chars_avail = read_word_u(sp_globals.font_org + FH_NCHRF);
127
128 /* Read sp_globals.orus per em from font header */
129 sp_globals.orus_per_em = read_word_u(sp_globals.font_org + FH_ORUPM);
130
131 /* compute address of private header */
132 private_off = read_word_u(sp_globals.font_org + FH_HEDSZ);
133 sp_globals.hdr2_org = sp_globals.font_org + private_off;
134
135 /* set metric resolution if specified, default to outline res otherwise */
136 if (private_off > EXP_FH_METRES)
137         {
138         sp_globals.metric_resolution = read_word_u(sp_globals.font_org + EXP_FH_METRES);
139         }
140 else
141         {
142         sp_globals.metric_resolution = sp_globals.orus_per_em;
143         }
144
145 #if INCL_METRICS
146 sp_globals.kern.tkorg = sp_globals.font_org + read_long(sp_globals.hdr2_org + FH_OFFTK);
147 sp_globals.kern.pkorg = sp_globals.font_org + read_long(sp_globals.hdr2_org + FH_OFFPK); 
148 sp_globals.kern.no_tracks = read_word_u(sp_globals.font_org + FH_NKTKS);
149 sp_globals.kern.no_pairs = read_word_u(sp_globals.font_org + FH_NKPRS);
150 #endif
151
152 offcd = read_long(sp_globals.hdr2_org + FH_OFFCD); /* Read offset to character directory */
153 ofcns = read_long(sp_globals.hdr2_org + FH_OFCNS); /* Read offset to constraint data */
154 cd_size = ofcns - offcd;
155 if ((((sp_globals.no_chars_avail << 1) + 3) != cd_size) &&
156     (((sp_globals.no_chars_avail * 3) + 4) != cd_size))
157     {
158     report_error(4);           /* Font format error */
159     return FALSE;
160     }
161
162 #if INCL_LCD                   /* Dynamic character data load suppoorted? */
163 #if INCL_METRICS
164 no_bytes_min = read_long(sp_globals.hdr2_org + FH_OCHRD); /* Offset to character data */
165 #else                          /* Dynamic character data load not supported? */
166 no_bytes_min = read_long(sp_globals.hdr2_org + FH_OFFTK); /* Offset to track kerning data */
167 #endif
168 #else                          /* Dynamic character data load not supported? */
169 no_bytes_min = read_long(sp_globals.hdr2_org + FH_NBYTE); /* Offset to EOF + 1 */
170 #endif
171
172 sp_globals.font_buff_size = sp_globals.pfont->no_bytes;
173 if (sp_globals.font_buff_size < no_bytes_min)  /* Minimum data not loaded? */
174     {
175     report_error(1);           /* Insufficient font data loaded */
176     return FALSE;
177     }
178
179 sp_globals.pchar_dir = sp_globals.font_org + offcd;
180 sp_globals.first_char_idx = read_word_u(sp_globals.font_org + FH_FCHRF);
181
182 /* Register font name with sp_globals.constraint mechanism */
183 #if INCL_RULES
184 font_id = read_word_u(sp_globals.font_org + FH_FNTID);
185 if (!(sp_globals.constr.font_id_valid) || (sp_globals.constr.font_id != font_id))
186     {
187     sp_globals.constr.font_id = font_id;
188     sp_globals.constr.font_id_valid = TRUE;
189     sp_globals.constr.data_valid = FALSE;
190     }
191 sp_globals.constr.org = sp_globals.font_org + ofcns;
192 sp_globals.constr.active = ((sp_globals.pspecs->flags & CONSTR_OFF) == 0);
193 #endif
194
195 /* Set up sliding point constants */
196 /* Set pixel shift to accomodate largest transformed pixel value */
197 xmin = read_word_u(sp_globals.font_org + FH_FXMIN);
198 xmax = read_word_u(sp_globals.font_org + FH_FXMAX);
199 ymin = read_word_u(sp_globals.font_org + FH_FYMIN);
200 ymax = read_word_u(sp_globals.font_org + FH_FYMAX);
201
202 if (!sp_setup_consts(xmin,xmax,ymin,ymax))
203     {
204     report_error(3);           /* Requested specs out of range */
205     return FALSE;
206     }
207 #if INCL_ISW
208 /* save the value of the max x oru that the fixed point constants are based on*/
209 sp_globals.isw_xmax = xmax; 
210 #endif
211
212 /* Setup transformation control block */
213 sp_setup_tcb(&sp_globals.tcb0);
214
215
216 /* Select output module */
217 sp_globals.output_mode = sp_globals.pspecs->flags & 0x0007;
218
219 #if INCL_USEROUT
220 if (!init_userout(sp_globals.pspecs))
221 #endif
222
223 switch (sp_globals.output_mode)
224     {
225 #if INCL_BLACK
226 case MODE_BLACK:                        /* Output mode 0 (Black writer) */
227         sp_globals.init_out = sp_init_black;
228     sp_globals.begin_char               = sp_begin_char_black;
229     sp_globals.begin_sub_char   = sp_begin_sub_char_out;
230         sp_globals.begin_contour        = sp_begin_contour_black;
231     sp_globals.curve                    = sp_curve_out;
232         sp_globals.line                 = sp_line_black;
233     sp_globals.end_contour              = sp_end_contour_out;
234         sp_globals.end_sub_char = sp_end_sub_char_out;
235     sp_globals.end_char         = sp_end_char_black;
236     break;
237 #endif
238
239 #if INCL_SCREEN
240 case MODE_SCREEN:                        /* Output mode 1 (Screen writer) */
241         sp_globals.init_out = sp_init_screen;
242     sp_globals.begin_char               = sp_begin_char_screen;
243     sp_globals.begin_sub_char   = sp_begin_sub_char_out;
244         sp_globals.begin_contour        = sp_begin_contour_screen;
245     sp_globals.curve                    = sp_curve_screen;
246         sp_globals.line                 = sp_line_screen;
247     sp_globals.end_contour              = sp_end_contour_screen;
248         sp_globals.end_sub_char = sp_end_sub_char_out;
249     sp_globals.end_char         = sp_end_char_screen;
250         break;
251 #endif
252
253 #if INCL_OUTLINE
254 case MODE_OUTLINE:                        /* Output mode 2 (Vector) */
255         sp_globals.init_out = sp_init_outline;
256     sp_globals.begin_char               = sp_begin_char_outline;
257     sp_globals.begin_sub_char   = sp_begin_sub_char_outline;
258         sp_globals.begin_contour        = sp_begin_contour_outline;
259     sp_globals.curve                    = sp_curve_outline;
260         sp_globals.line                 = sp_line_outline;
261     sp_globals.end_contour              = sp_end_contour_outline;
262         sp_globals.end_sub_char = sp_end_sub_char_outline;
263     sp_globals.end_char         = sp_end_char_outline;
264         break;
265 #endif
266
267 #if INCL_2D
268 case MODE_2D:                        /* Output mode 3 */
269         sp_globals.init_out = sp_init_2d;
270     sp_globals.begin_char               = sp_begin_char_2d;
271     sp_globals.begin_sub_char   = sp_begin_sub_char_out;
272         sp_globals.begin_contour        = sp_begin_contour_2d;
273     sp_globals.curve                    = sp_curve_out;
274         sp_globals.line                 = sp_line_2d;
275     sp_globals.end_contour              = sp_end_contour_out;
276         sp_globals.end_sub_char = sp_end_sub_char_out;
277     sp_globals.end_char         = sp_end_char_2d;
278     break;
279 #endif
280
281 default:
282     report_error(8);           /* Unsupported mode requested */
283     return FALSE;
284     }
285
286         if (!fn_init_out(sp_globals.pspecs))
287                 {
288                 report_error(5);
289                 return FALSE;
290                 }
291                 
292
293 sp_globals.curves_out = sp_globals.pspecs->flags & CURVES_OUT;
294
295 if (sp_globals.pspecs->flags & BOGUS_MODE) /* Linear transformation requested? */
296     {
297     sp_globals.tcb0.xtype = sp_globals.tcb0.ytype = 4;
298     }
299 else                           /* Intelligent transformation requested? */
300     {
301 #if INCL_RULES
302 #else
303     report_error(7);           /* Rules requested; not supported */
304     return FALSE;
305 #endif
306     }
307
308 if ((sp_globals.pspecs->flags & SQUEEZE_LEFT) ||
309     (sp_globals.pspecs->flags & SQUEEZE_RIGHT) ||
310     (sp_globals.pspecs->flags & SQUEEZE_TOP) ||
311     (sp_globals.pspecs->flags & SQUEEZE_BOTTOM) )
312     {
313 #if (INCL_SQUEEZING)
314 #else
315      report_error(11);
316      return FALSE;
317 #endif
318     }
319
320 if ((sp_globals.pspecs->flags & CLIP_LEFT) ||
321     (sp_globals.pspecs->flags & CLIP_RIGHT) ||
322     (sp_globals.pspecs->flags & CLIP_TOP) ||
323     (sp_globals.pspecs->flags & CLIP_BOTTOM) )
324     {
325 #if (INCL_CLIPPING)
326 #else
327      report_error(11);
328      return FALSE;
329 #endif
330     }
331
332 sp_globals.specs_valid = TRUE;
333 return TRUE;
334 }
335
336 \f
337
338 #if INCL_MULTIDEV
339 #if INCL_BLACK || INCL_SCREEN || INCL_2D
340 FUNCTION boolean set_bitmap_device(bfuncs,size)
341 GDECL
342 bitmap_t *bfuncs;
343 ufix16 size;
344 {
345
346 if (size != sizeof(sp_globals.bitmap_device))
347         return FALSE;
348
349 sp_globals.bitmap_device = *bfuncs;
350 sp_globals.bitmap_device_set = TRUE;
351 }
352 #endif
353
354 #if INCL_OUTLINE
355 FUNCTION boolean set_outline_device(ofuncs,size)
356 GDECL
357 outline_t *ofuncs;
358 ufix16 size;
359 {
360
361 if (size != sizeof(sp_globals.outline_device))
362         return FALSE;
363
364 sp_globals.outline_device = *ofuncs;
365 sp_globals.outline_device_set = TRUE;
366 }
367 #endif
368 #endif
369
370 \f
371 #ifdef old
372 FUNCTION boolean sp_setup_consts(xmin, xmax, ymin, ymax)
373 #else
374 static FUNCTION boolean sp_setup_consts(xmin, xmax, ymin, ymax)
375 #endif
376 GDECL
377 fix15   xmin;          /* Minimum X ORU value in font */
378 fix15   xmax;          /* Maximum X ORU value in font */
379 fix15   ymin;          /* Minimum Y ORU value in font */
380 fix15   ymax;          /* Maximum Y ORU value in font */
381 /*
382  * Sets the following constants used for fixed point arithmetic:
383  *      sp_globals.multshift    multipliers and products; range is 14 to 8
384  *      sp_globals.pixshift     pixels: range is 0 to 8
385  *      sp_globals.mpshift      shift from product to sub-pixels (sp_globals.multshift - sp_globals.pixshift)
386  *      sp_globals.multrnd      rounding for products
387  *      sp_globals.pixrnd       rounding for pixels
388  *      sp_globals.mprnd        rounding for sub-pixels
389  *      sp_globals.onepix       1 pixel in shifted pixel units
390  *      sp_globals.pixfix       mask to eliminate fractional bits of shifted pixels
391  *      sp_globals.depth_adj    curve splitting depth adjustment
392  * Returns FALSE if specs are out of range
393  */
394 {
395 fix31   mult;          /* Successive multiplier values */
396 ufix32  num;           /* Numerator of largest multiplier value */
397 ufix32  numcopy;       /* Copy of numerator */
398 ufix32  denom;         /* Denominator of largest multiplier value */
399 ufix32  denomcopy;     /* Copy of denominator */
400 ufix32  pix_max;       /* Maximum pixel rounding error */
401 fix31   xmult;         /* Coefficient of X oru value in transformation */
402 fix31   ymult;         /* Coefficient of Y oru value in transformation */
403 fix31   offset;        /* Constant in transformation */
404 fix15   i;             /* Loop counter */
405 fix15   x, y;          /* Successive corners of bounding box in ORUs */
406 fix31   pixval;        /* Successive pixel values multiplied by orus per em */
407 fix15   xx, yy;        /* Bounding box corner that produces max pixel value */
408
409 /* Determine numerator and denominator of largest multiplier value */
410 mult = sp_globals.pspecs->xxmult >> 16;
411 if (mult < 0)
412     mult = -mult;
413 num = mult;
414
415 mult = sp_globals.pspecs->xymult >> 16;
416 if (mult < 0)
417     mult = -mult;
418 if (mult > num)
419     num = mult;
420
421 mult = sp_globals.pspecs->yxmult >> 16;
422 if (mult < 0)
423     mult = -mult;
424 if (mult > num)
425     num = mult;
426
427 mult = sp_globals.pspecs->yymult >> 16;
428 if (mult < 0)
429     mult = -mult;
430 if (mult > num)
431     num = mult;
432 num++;                 /* Max absolute pixels per em (rounded up) */
433 denom = (ufix32)sp_globals.orus_per_em;
434
435 /* Set curve splitting depth adjustment to accomodate largest multiplier value */
436 sp_globals.depth_adj = 0;   /* 0 = 0.5 pel, 1 = 0.13 pel, 2 = 0.04 pel accuracy */
437 denomcopy = denom;
438 /*  The following two occurances of a strange method of shifting twice by 1 
439     are intentional and should not be changed to a single shift by 2.  
440     It prevents MicroSoft C 5.1 from generating functions calls to do the shift.  
441     Worse, using the REENTRANT_ALLOC option in conjunction with the /AC compiler 
442     option, the function appears to be called incorrectly, causing depth_adj to always
443         be set to -7, causing very angular characters. */
444
445 while ((num > denomcopy) && (sp_globals.depth_adj < 5)) /* > 1, 4, 16, ...  pixels per oru? */
446     {
447     denomcopy <<= 1;
448     denomcopy <<= 1;
449     sp_globals.depth_adj++; /* Add 1, 2, 3, ... to depth adjustment */
450     }
451 numcopy = num << 2;
452 while ((numcopy <= denom) && (sp_globals.depth_adj > -4))  /* <= 1/4, 1/16, 1/64 pix per oru? */
453     {
454     numcopy <<= 1;
455     numcopy <<= 1;
456     sp_globals.depth_adj--; /* Subtract 1, 2, 3, ... from depth adjustment */
457     }
458 SHOW(sp_globals.depth_adj);
459
460 /* Set multiplier shift to accomodate largest multiplier value */
461 sp_globals.multshift = 14;            
462 numcopy = num;
463 while (numcopy >= denom)     /* More than 1, 2, 4, ... pix per oru? */
464     {
465     numcopy >>= 1;
466     sp_globals.multshift--; /* sp_globals.multshift is 13, 12, 11, ... */
467     }
468
469 sp_globals.multrnd = ((fix31)1 << sp_globals.multshift) >> 1;
470 SHOW(sp_globals.multshift);
471
472
473 pix_max = (ufix32)( 0xffff & read_word_u(sp_globals.hdr2_org + FH_PIXMX));
474
475 num = 0;
476 xmult = ((sp_globals.pspecs->xxmult >> 16) + 1) >> 1;
477 ymult = ((sp_globals.pspecs->xymult >> 16) + 1) >> 1;
478 offset = ((sp_globals.pspecs->xoffset >> 16) + 1) >> 1;
479 for (i = 0; i < 8; i++)
480     {
481     if (i == 4)
482         {
483         xmult = ((sp_globals.pspecs->yxmult >> 16) + 1) >> 1;
484         ymult = ((sp_globals.pspecs->yymult >> 16) + 1) >> 1;
485         offset = ((sp_globals.pspecs->yoffset >> 16) + 1) >> 1;
486         }
487     x = (i & BIT1)? xmin: xmax;
488     y = (i & BIT0)? ymin: ymax;
489     pixval = (fix31)x * xmult + (fix31)y * ymult + offset * denom;
490     if (pixval < 0)
491         pixval = -pixval;
492     if (pixval > num)
493         {
494         num = pixval;
495         xx = x;
496         yy = y;
497         }
498     }
499 if (xx < 0)
500     xx = -xx;
501 if (yy < 0)
502     yy = -yy;
503 num += xx + yy + ((pix_max + 2) * denom); 
504                                   /* Allow (with 2:1 safety margin) for 1 pixel rounding errors in */
505                                   /* xmult, ymult and offset values, pix_max pixel expansion */
506                                   /* due to intelligent scaling, and */
507                                   /* 1 pixel rounding of overall character position */
508 denom = denom << 14;              /* Note num is in units of half pixels times orus per em */
509
510 sp_globals.pixshift = -1;
511 while ((num <= denom) && (sp_globals.pixshift < 8))  /* Max pixels <= 32768, 16384, 8192, ... pixels? */
512     {
513     num <<= 1;
514     sp_globals.pixshift++;        /* sp_globals.pixshift = 0, 1, 2, ... */
515     }
516 if (sp_globals.pixshift < 0)
517     return FALSE;
518
519 SHOW(sp_globals.pixshift);
520 sp_globals.poshift = 16 - sp_globals.pixshift;
521
522 sp_globals.onepix = (fix15)1 << sp_globals.pixshift;
523 sp_globals.pixrnd = sp_globals.onepix >> 1;
524 sp_globals.pixfix = ~0 << sp_globals.pixshift;
525
526 sp_globals.mpshift = sp_globals.multshift - sp_globals.pixshift;
527 if (sp_globals.mpshift < 0)
528     return FALSE;
529 sp_globals.mprnd = ((fix31)1 << sp_globals.mpshift) >> 1;
530
531 return TRUE;
532 }
533 \f
534 #ifdef old
535 FUNCTION void sp_setup_tcb(ptcb)
536 #else
537 static FUNCTION void sp_setup_tcb(ptcb)
538 #endif
539 GDECL
540 tcb_t GLOBALFAR *ptcb;           /* Pointer to transformation control bloxk */
541 /* 
542  * Convert transformation coeffs to internal form 
543  */
544 {
545
546 ptcb->xxmult = sp_setup_mult(sp_globals.pspecs->xxmult);
547 ptcb->xymult = sp_setup_mult(sp_globals.pspecs->xymult);
548 ptcb->xoffset = sp_setup_offset(sp_globals.pspecs->xoffset);
549 ptcb->yxmult = sp_setup_mult(sp_globals.pspecs->yxmult);
550 ptcb->yymult = sp_setup_mult(sp_globals.pspecs->yymult);
551 ptcb->yoffset = sp_setup_offset(sp_globals.pspecs->yoffset);
552
553 SHOW(ptcb->xxmult);
554 SHOW(ptcb->xymult);
555 SHOW(ptcb->xoffset);
556 SHOW(ptcb->yxmult);
557 SHOW(ptcb->yymult);
558 SHOW(ptcb->yoffset);
559
560 type_tcb(ptcb); /* Classify transformation type */
561 }
562 \f
563 FUNCTION static fix15 sp_setup_mult(input_mult)
564 GDECL
565 fix31   input_mult;    /* Multiplier in input format */
566 /*
567  * Called by sp_setup_tcb() to convert multiplier in transformation
568  * matrix from external to internal form.
569  */
570 {
571 fix15   imshift;       /* Right shift to internal format */
572 fix31   imdenom;       /* Divisor to internal format */
573 fix31   imrnd;         /* Rounding for division operation */
574
575 imshift = 15 - sp_globals.multshift;
576 imdenom = (fix31)sp_globals.orus_per_em << imshift;
577 imrnd = imdenom >> 1;
578
579 input_mult >>= 1;
580 if (input_mult >= 0)
581     return (fix15)((input_mult + imrnd) / imdenom);
582 else
583     return -(fix15)((-input_mult + imrnd) / imdenom);
584 }
585 \f
586 FUNCTION static fix31 sp_setup_offset(input_offset)
587 GDECL
588 fix31   input_offset;   /* Multiplier in input format */
589 /*
590  * Called by sp_setup_tcb() to convert offset in transformation
591  * matrix from external to internal form.
592  */
593 {
594 fix15   imshift;       /* Right shift to internal format */
595 fix31   imrnd;         /* Rounding for right shift operation */
596
597 imshift = 15 - sp_globals.multshift;
598 imrnd = ((fix31)1 << imshift) >> 1;
599
600 return (((input_offset >> 1) + imrnd) >> imshift) + sp_globals.mprnd;
601 }
602 \f
603 FUNCTION void type_tcb(ptcb)
604 GDECL
605 tcb_t GLOBALFAR *ptcb;           /* Pointer to transformation control bloxk */
606 {
607 fix15   x_trans_type;
608 fix15   y_trans_type;
609 fix15   xx_mult;
610 fix15   xy_mult;
611 fix15   yx_mult;
612 fix15   yy_mult;
613 fix15   h_pos;
614 fix15   v_pos;
615 fix15   x_ppo;
616 fix15   y_ppo;
617 fix15   x_pos;
618 fix15   y_pos;
619
620 /* check for mirror image transformations */
621 xx_mult = ptcb->xxmult;
622 xy_mult = ptcb->xymult;
623 yx_mult = ptcb->yxmult;
624 yy_mult = ptcb->yymult;
625
626 ptcb->mirror = ((((fix31)xx_mult*(fix31)yy_mult)-
627                      ((fix31)xy_mult*(fix31)yx_mult)) < 0) ? -1 : 1;
628
629 if (sp_globals.pspecs->flags & BOGUS_MODE) /* Linear transformation requested? */
630     {
631     ptcb->xtype = 4;
632     ptcb->ytype = 4;
633
634     ptcb->xppo = 0;
635     ptcb->yppo = 0;
636     ptcb->xpos = 0;
637     ptcb->ypos = 0;
638     }
639 else                            /* Intelligent tranformation requested? */
640     {
641     h_pos = ((ptcb->xoffset >> sp_globals.mpshift) + sp_globals.pixrnd) & sp_globals.pixfix;
642     v_pos = ((ptcb->yoffset >> sp_globals.mpshift) + sp_globals.pixrnd) & sp_globals.pixfix;
643
644     x_trans_type = 4;
645     x_ppo = 0;
646     x_pos = 0;
647
648     y_trans_type = 4;
649     y_ppo = 0;
650     y_pos = 0;
651
652     if (xy_mult == 0)
653         {
654         if (xx_mult >= 0)
655             {
656             x_trans_type = 0;   /* X pix is function of X orus only */
657             x_ppo = xx_mult;
658             x_pos = h_pos;
659             }
660         else 
661             {
662             x_trans_type = 1;   /* X pix is function of -X orus only */
663             x_ppo = -xx_mult;
664             x_pos = -h_pos;
665             }
666         }
667
668     else if (xx_mult == 0)
669         {
670         if (xy_mult >= 0)
671             {
672             x_trans_type = 2;   /* X pix is function of Y orus only */
673             y_ppo = xy_mult;
674             y_pos = h_pos;
675             }
676         else 
677             {
678             x_trans_type = 3;   /* X pix is function of -Y orus only */
679             y_ppo = -xy_mult;
680             y_pos = -h_pos;
681             }
682         }
683
684     if (yx_mult == 0)
685         {
686         if (yy_mult >= 0)
687             {
688             y_trans_type = 0;   /* Y pix is function of Y orus only */
689             y_ppo = yy_mult;
690             y_pos = v_pos;
691             }
692         else 
693             {
694             y_trans_type = 1;   /* Y pix is function of -Y orus only */
695             y_ppo = -yy_mult;
696             y_pos = -v_pos;
697             }
698         }
699     else if (yy_mult == 0)
700         {
701         if (yx_mult >= 0)
702             {
703             y_trans_type = 2;   /* Y pix is function of X orus only */
704             x_ppo = yx_mult;
705             x_pos = v_pos;
706             }
707         else 
708             {
709             y_trans_type = 3;   /* Y pix is function of -X orus only */
710             x_ppo = -yx_mult;
711             x_pos = -v_pos;
712             }
713         }
714
715     ptcb->xtype = x_trans_type;
716     ptcb->ytype = y_trans_type;
717
718     ptcb->xppo = x_ppo;
719     ptcb->yppo = y_ppo;
720     ptcb->xpos = x_pos;
721     ptcb->ypos = y_pos;
722     }
723
724 sp_globals.normal = (ptcb->xtype != 4) && (ptcb->ytype != 4);
725
726 ptcb->xmode = 4;
727 ptcb->ymode = 4;   
728
729 SHOW(ptcb->xtype);
730 SHOW(ptcb->ytype);
731 SHOW(ptcb->xppo);
732 SHOW(ptcb->yppo);
733 SHOW(ptcb->xpos);
734 SHOW(ptcb->ypos);
735 }
736 \f
737 FUNCTION fix31 read_long(pointer)
738 GDECL
739 ufix8 FONTFAR *pointer;    /* Pointer to first byte of encrypted 3-byte integer */
740 /*
741  * Reads a 3-byte encrypted integer from the byte string starting at 
742  * the specified point.
743  * Returns the decrypted value read as a signed integer.
744  */
745 {
746 fix31 tmpfix31;
747
748 tmpfix31 = (fix31)((*pointer++) ^ sp_globals.key4) << 8;            /* Read middle byte */
749 tmpfix31 += (fix31)(*pointer++) << 16;                              /* Read most significant byte */
750 tmpfix31 += (fix31)((*pointer) ^ sp_globals.key6);                    /* Read least significant byte */
751 return tmpfix31;
752 }
753 \f
754 FUNCTION fix15 read_word_u(pointer)
755 GDECL
756 ufix8 FONTFAR *pointer;    /* Pointer to first byte of unencrypted 2-byte integer */
757 /*
758  * Reads a 2-byte unencrypted integer from the byte string starting at 
759  * the specified point.
760  * Returns the decrypted value read as a signed integer.
761  */
762 {
763 fix15 tmpfix15;
764
765 tmpfix15 = (fix15)(*pointer++) << 8;                                /* Read most significant byte */
766 tmpfix15 += (fix15)(*pointer);                                        /* Add least significant byte */
767 return tmpfix15;
768 }
769
770