1 /* $XConsortium: do_char.c /main/5 1995/10/24 11:22:28 gildea $ */
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.
13 BITSTREAM CHARTER is a registered trademark of Bitstream Inc.
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.
25 /***************************** D O - C H A R . C *****************************
27 * This is the top level module for processing one simple or composite *
30 ****************************************************************************/
32 #include "spdo_prv.h" /* General definitions for Speedo */
38 #define SHOW(X) printf("X = %d\n", X)
43 /***** GLOBAL VARIABLES *****/
45 /***** GLOBAL FUNCTIONS *****/
47 /***** EXTERNAL VARIABLES *****/
49 /***** EXTERNAL FUNCTIONS *****/
51 /***** STATIC VARIABLES *****/
53 /***** STATIC FUNCTIONS *****/
56 static boolean sp_make_simp_char(PROTO_DECL2 ufix8 FONTFAR *pointer,ufix8 format);
57 static boolean sp_make_comp_char(PROTO_DECL2 ufix8 FONTFAR *pointer);
58 static ufix8 FONTFAR *sp_get_char_org(PROTO_DECL2 ufix16 char_index,boolean top_level);
59 static fix15 sp_get_posn_arg(PROTO_DECL2 ufix8 FONTFAR *STACKFAR *ppointer,ufix8 format);
60 static fix15 sp_get_scale_arg(PROTO_DECL2 ufix8 FONTFAR *STACKFAR *ppointer,ufix8 format);
62 static boolean sp_make_simp_char(); /* Process simple character data */
63 static boolean sp_make_comp_char(); /* Process compound character data */
64 static ufix8 FONTFAR *sp_get_char_org(); /* Look up char in character directory */
65 static fix15 sp_get_posn_arg(); /* Read Xpos Ypos args in DOCH instruction */
66 static fix15 sp_get_scale_arg(); /* read Xscale Yscale args in DOCH instruction */
70 FUNCTION ufix16 get_char_id(char_index)
72 ufix16 char_index; /* Index to character in char directory */
74 * Returns character id for specified character index in currently
76 * Reports Error 10 and returns 0 if no font selected.
77 * Reports Error 12 and returns 0 if character data not available.
80 ufix8 FONTFAR *pointer; /* Pointer to character data */
82 if (!sp_globals.specs_valid) /* Font specs not defined? */
84 report_error(10); /* Report font not specified */
85 return (ufix16)0; /* Return zero character id */
88 pointer = sp_get_char_org(char_index, TRUE); /* Get pointer to character data */
89 if (pointer == NULL) /* Character data not available? */
91 report_error(12); /* Report character data not avail */
92 return (ufix16)0; /* Return zero character id */
95 return 0xffff & NEXT_WORD(pointer); /* Return character id */
100 FUNCTION fix31 get_char_width(char_index)
102 ufix16 char_index; /* Index to character in char directory */
104 * Returns character set width for specified character index in currently
105 * selected font in units of 1/65536 em.
106 * Reports Error 10 and returns 0 if no font selected.
107 * Reports Error 12 and returns 0 if character data not available.
110 ufix8 FONTFAR *pointer; /* Pointer to character data */
111 fix31 set_width; /* Set width of character */
113 if (!sp_globals.specs_valid) /* Font specs not defined? */
115 report_error(10); /* Report font not specified */
116 return (fix31)0; /* Return zero character width */
119 pointer = sp_get_char_org(char_index, TRUE); /* Get pointer to character data */
120 if (pointer == NULL) /* Character data not available? */
122 report_error(12); /* Report character data not avail */
123 return (fix31)0; /* Return zero character width */
126 pointer += 2; /* Skip over character id */
127 set_width = (fix31)NEXT_WORD(pointer); /* Read set width and Convert units */
128 set_width = ((set_width << 16) + (sp_globals.metric_resolution >> 1)) / sp_globals.metric_resolution;
129 return set_width; /* Return in 1/65536 em units */
134 FUNCTION fix15 get_track_kern(track, point_size)
136 fix15 track; /* Track required (0 - 3) */
137 fix15 point_size; /* Point size (units of whole points) */
139 * Returns inter-character spacing adjustment in units of 1/256
140 * points for the specified kerning track and point size.
141 * If the specified point size is larger than the maximum point
142 * size for the specified track, the adjustment for the maximum
143 * point size is used.
144 * If the specified point size is smaller than the minimum point
145 * size for the specified track, the adjustment for the minimum
146 * point size is used.
147 * If the specified point size is between the minimum point size
148 * and the maximum point size for the specified track, the
149 * adjustment is interpolated linearly between the minimum and
150 * maximum adjustments.
151 * Reports Error 10 and returns 0 if no font selected.
152 * Reports Error 13 and returns 0 if track kerning data not in font.
155 ufix8 FONTFAR *pointer; /* Pointer to character data */
156 fix15 no_tracks; /* Number of kerning tracks in font */
157 ufix8 format; /* Track kerning format byte */
158 fix15 i; /* Track counter */
159 fix15 min_pt_size; /* Minimum point size for track */
160 fix15 max_pt_size; /* Maximum point size for track */
161 fix15 min_adj; /* Adjustment for min point size */
162 fix15 max_adj; /* Adjustment for max point size */
163 fix31 delta_pt_size;/* Max point size - min point size */
164 fix31 delta_adj; /* Min adjustment - max adjustment */
165 fix15 adj = 0; /* Interpolated adjustment */
167 if (track == 0) /* Track zero selected? */
169 return adj; /* Return zero track kerning adjustment */
172 if (!sp_globals.specs_valid) /* Font specs not defined? */
174 report_error(10); /* Report font not specified */
175 return adj; /* Return zero track kerning adjustment */
178 no_tracks = sp_globals.kern.no_tracks; /* Number of kerning tracks */
179 if (track > no_tracks) /* Required track not available? */
181 report_error(13); /* Report track kerning data not avail */
182 return adj; /* Return zero track kerning adjustment */
185 pointer = sp_globals.kern.tkorg; /* Point to start of track kern data */
186 for (i = 0; i < track; i++) /* Read until track required is read */
188 format = NEXT_BYTE(pointer); /* Read track kerning format byte */
189 min_pt_size = (format & BIT0)?
191 (fix15)NEXT_BYTE(pointer);
192 min_adj = (format & BIT1)?
194 (fix15)NEXT_BYTE(pointer);
195 max_pt_size = (format & BIT2)?
197 (fix15)NEXT_BYTE(pointer);
198 max_adj = (format & BIT3)?
200 (fix15)NEXT_BYTE(pointer);
203 if (point_size <= min_pt_size) /* Smaller than minimum point size? */
205 return min_adj; /* Return minimum adjustment (1/256 points) */
208 if (point_size >= max_pt_size) /* Larger than maximum point size? */
210 return max_adj; /* Return maximum adjustment (1/256 points) */
213 delta_pt_size = (fix31)(max_pt_size - min_pt_size);
214 delta_adj = (fix31)(min_adj - max_adj);
215 adj = (fix15)(min_adj -
216 (((fix31)(point_size - min_pt_size) * delta_adj +
217 (delta_pt_size >> 1)) / delta_pt_size));
218 return adj; /* Return interpolated adjustment (1/256 points) */
223 FUNCTION fix31 get_pair_kern(char_index1, char_index2)
225 ufix16 char_index1; /* Index to first character in char directory */
226 ufix16 char_index2; /* Index to second character in char directory */
228 * Returns inter-character spacing adjustment in units of 1/65536 em
229 * for the specified pair of characters.
230 * Reports Error 10 and returns 0 if no font selected.
231 * Reports Error 14 and returns 0 if pair kerning data not in font.
234 ufix8 FONTFAR *origin; /* Pointer to first kerning pair record */
235 ufix8 FONTFAR *pointer; /* Pointer to character data */
236 ufix16 tmpufix16; /* Temporary workspace */
237 fix15 no_pairs; /* Number of kerning pairs in font */
238 ufix8 format; /* Track kerning format byte */
239 boolean long_id; /* TRUE if 2-byte character ids */
240 fix15 rec_size; /* Number of bytes in kern pair record */
241 fix15 n; /* Number of remaining kern pairs */
242 fix15 nn; /* Number of kern pairs in first partition */
243 fix15 base; /* Index to first record in rem kern pairs */
244 fix15 i; /* Index to kern pair being tested */
245 fix31 adj = 0; /* Returned value of adjustment */
246 fix15 adj_base; /* Adjustment base for relative adjustments */
248 if (!sp_globals.specs_valid) /* Font specs not defined? */
250 report_error(10); /* Report font not specified */
251 return adj; /* Return zero pair kerning adjustment */
254 no_pairs = sp_globals.kern.no_pairs; /* Number of kerning pairs */
255 if (no_pairs == 0) /* Pair kerning data not available? */
257 report_error(14); /* Report pair kerning data not avail */
258 return adj; /* Return zero pair kerning adjustment */
261 pointer = sp_globals.kern.pkorg; /* Point to start of pair kern data */
262 format = NEXT_BYTE(pointer); /* Read pair kerning format byte */
263 if (!(format & BIT0)) /* One-byte adjustment values? */
264 adj_base = NEXT_WORD(pointer); /* Read base adjustment */
265 origin = pointer; /* First byte of kerning pair data */
266 rec_size = format + 3; /* Compute kerning pair record size */
267 long_id = format & BIT1; /* Set flag for 2-byte char index */
269 n = no_pairs; /* Consider all kerning pairs */
270 base = 0; /* Set base at first kern pair record */
271 while (n != 0) /* While 1 or more kern pairs remain ... */
273 nn = n >> 1; /* Size of first partition */
274 i = base + nn; /* Index to record to be tested */
275 pointer = origin + (i * rec_size);
276 tmpufix16 = NEXT_CHNDX(pointer, long_id);
277 if (char_index1 < tmpufix16)
279 n = nn; /* Number remaining in first partition */
282 if (char_index1 > tmpufix16)
284 n -= nn + 1; /* Number remaining in second partition */
285 base = i + 1; /* Base index for second partition */
288 tmpufix16 = NEXT_CHNDX(pointer, long_id);
289 if (char_index2 < tmpufix16)
291 n = nn; /* Number remaining in first partition */
294 if (char_index2 > tmpufix16)
296 n -= nn + 1; /* Number remaining in second partition */
297 base = i + 1; /* Base index for second partition */
300 adj = (format & BIT0)?
301 (fix31)NEXT_WORD(pointer):
302 (fix31)(adj_base + (fix15)NEXT_BYTE(pointer));
303 adj = ((adj << 16) + (sp_globals.orus_per_em >> 1)) / sp_globals.orus_per_em; /* Convert units */
304 n = 0; /* No more to consider */
306 return adj; /* Return pair kerning adjustment */
313 FUNCTION boolean get_char_bbox(char_index, bbox)
319 * returns true if character exists, false if it doesn't
320 * provides transformed character bounding box in 1/65536 pixels
321 * in the provided bbox_t structure. Bounding box may be
322 * conservative in the event that the transformation is not
323 * normal or the character is compound.
326 ufix8 FONTFAR *pointer;
332 sp_globals.plaid = &plaid;
335 if (!sp_globals.specs_valid) /* Font specs not defined? */
337 report_error(10); /* Report font not specified */
338 return FALSE; /* Error return */
341 init_tcb(); /* Initialize transformation control block */
343 pointer = sp_get_char_org(char_index, TRUE); /* Point to start of character data */
344 if (pointer == NULL) /* Character data not available? */
346 report_error(12); /* Report character data not avail */
347 return FALSE; /* Error return */
350 pointer += 2; /* Skip over character id */
351 tmp = NEXT_WORD(pointer); /* Read set width */
353 tmp = NEXT_BYTE(pointer);
354 if (tmp & BIT1) /* Optional data in header? */
356 tmp = (ufix8)NEXT_BYTE(pointer); /* Read size of optional data */
357 pointer += tmp; /* Skip optional data */
360 pointer = plaid_tcb(pointer, tmp); /* Process plaid data */
361 pointer = read_bbox(pointer, &Pmin, &Pmax,(boolean)FALSE); /* Read bounding box */
362 bbox->xmin = (fix31)Pmin.x << sp_globals.poshift;
363 bbox->xmax = (fix31)Pmax.x << sp_globals.poshift;
364 bbox->ymin = (fix31)Pmin.y << sp_globals.poshift;
365 bbox->ymax = (fix31)Pmax.y << sp_globals.poshift;
369 #else /* new code, 4/25/91 */
371 FUNCTION boolean get_char_bbox(char_index, bbox)
377 * returns true if character exists, false if it doesn't
378 * provides transformed character bounding box in 1/65536 pixels
379 * in the provided bbox_t structure. Bounding box may be
380 * conservative in the event that the transformation is not
381 * normal or the character is compound.
384 ufix8 FONTFAR *pointer;
392 sp_globals.plaid = &plaid;
395 if (!sp_globals.specs_valid) /* Font specs not defined? */
397 report_error(10); /* Report font not specified */
398 return FALSE; /* Error return */
401 init_tcb(); /* Initialize transformation control block */
403 pointer = sp_get_char_org(char_index, TRUE); /* Point to start of character data */
404 if (pointer == NULL) /* Character data not available? */
406 report_error(12); /* Report character data not avail */
407 return FALSE; /* Error return */
410 pointer += 2; /* Skip over character id */
411 tmp = NEXT_WORD(pointer); /* Read set width */
413 format = NEXT_BYTE(pointer);
414 if (format & BIT1) /* Optional data in header? */
416 tmp = (ufix8)NEXT_BYTE(pointer); /* Read size of optional data */
417 pointer += tmp; /* Skip optional data */
422 pix_adj = sp_globals.onepix << 1; /* Allow 2 pixel expansion ... */
429 pointer = plaid_tcb(pointer, format); /* Process plaid data */
430 pointer = read_bbox(pointer, &Pmin, &Pmax,(boolean)FALSE); /* Read bounding box */
432 Pmin.x -= pix_adj; /* ... of components of ... */
433 Pmin.y -= pix_adj; /* ... compound ... */
434 Pmax.x += pix_adj; /* ... character ... */
435 Pmax.y += pix_adj; /* ... bounding box. */
438 bbox->xmin = (fix31)Pmin.x << sp_globals.poshift;
439 bbox->xmax = (fix31)Pmax.x << sp_globals.poshift;
440 bbox->ymin = (fix31)Pmin.y << sp_globals.poshift;
441 bbox->ymax = (fix31)Pmax.y << sp_globals.poshift;
444 #endif /* new code */
450 FUNCTION boolean make_char_isw(char_index,imported_setwidth)
453 ufix32 imported_setwidth;
455 fix15 xmin; /* Minimum X ORU value in font */
456 fix15 xmax; /* Maximum X ORU value in font */
457 fix15 ymin; /* Minimum Y ORU value in font */
458 fix15 ymax; /* Maximum Y ORU value in font */
461 sp_globals.import_setwidth_act = TRUE;
462 /* convert imported width to orus */
463 sp_globals.imported_width = (sp_globals.metric_resolution *
464 imported_setwidth) >> 16;
465 return_value = do_make_char(char_index);
467 if (sp_globals.isw_modified_constants)
469 /* reset fixed point constants */
470 xmin = read_word_u(sp_globals.font_org + FH_FXMIN);
471 ymin = read_word_u(sp_globals.font_org + FH_FYMIN);
472 ymax = read_word_u(sp_globals.font_org + FH_FYMAX);
473 sp_globals.constr.data_valid = FALSE;
474 xmax = read_word_u(sp_globals.font_org + FH_FXMAX);
475 if (!setup_consts(xmin,xmax,ymin,ymax))
477 report_error(3); /* Requested specs out of range */
481 return (return_value);
484 FUNCTION boolean make_char(char_index)
486 ufix16 char_index; /* Index to character in char directory */
488 sp_globals.import_setwidth_act = FALSE;
489 return (do_make_char(char_index));
492 FUNCTION static boolean do_make_char(char_index)
494 FUNCTION boolean make_char(char_index)
497 * Outputs specified character using the currently selected font and
498 * scaling and output specifications.
499 * Reports Error 10 and returns FALSE if no font specifications
501 * Reports Error 12 and returns FALSE if character data not available.
506 ufix8 FONTFAR *pointer; /* Pointer to character data */
512 sp_globals.isw_modified_constants = FALSE;
519 #if INCL_BLACK || INCL_SCREEN || INCL_2D
520 intercepts_t intercepts;
521 sp_globals.intercepts = &intercepts;
524 sp_globals.plaid = &plaid;
527 if (!sp_globals.specs_valid) /* Font specs not defined? */
529 report_error(10); /* Report font not specified */
530 return FALSE; /* Error return */
535 if (sp_globals.output_mode == MODE_OUTLINE && !sp_globals.outline_device_set)
542 if (!sp_globals.bitmap_device_set)
550 init_tcb(); /* Initialize transformation control block */
552 pointer = sp_get_char_org(char_index, TRUE); /* Point to start of character data */
554 if (pointer == NULL) /* Character data not available? */
556 report_error(12); /* Report character data not avail */
557 return FALSE; /* Error return */
560 pointer += 2; /* Skip over character id */
561 x_orus = NEXT_WORD(pointer); /* Read set width */
562 #if INCL_SQUEEZING || INCL_ISW
563 sp_globals.setwidth_orus = x_orus;
567 if (sp_globals.import_setwidth_act)
568 x_orus = sp_globals.imported_width;
570 sp_globals.Psw.x = (fix15)((fix31)
571 (((fix31)x_orus * (sp_globals.specs.xxmult>>16) +
572 ( ((fix31)x_orus * (sp_globals.specs.xxmult&0xffffL) )>>16)
573 ) << sp_globals.pixshift) / sp_globals.metric_resolution);
575 sp_globals.Psw.y = (fix15)(
577 ((fix31)x_orus * (sp_globals.specs.yxmult>>16) +
578 ( ((fix31)x_orus * (sp_globals.specs.yxmult&0xffffL) )>>16)
579 ) << sp_globals.pixshift) / sp_globals.metric_resolution);
581 format = NEXT_BYTE(pointer);
582 if (format & BIT1) /* Optional data in header? */
584 tmpfix15 = (ufix8)NEXT_BYTE(pointer); /* Read size of optional data */
585 pointer += tmpfix15; /* Skip optional data */
589 return sp_make_comp_char(pointer); /* Output compound character */
593 return sp_make_simp_char(pointer, format); /* Output simple character */
597 FUNCTION static boolean sp_make_simp_char(pointer, format)
599 ufix8 FONTFAR *pointer; /* Pointer to first byte of position argument */
600 ufix8 format; /* Character format byte */
602 * Called by sp_make_char() to output a simple (non-compound) character.
603 * Returns TRUE on completion.
606 point_t Pmin, Pmax; /* Transformed corners of bounding box */
607 #if INCL_SQUEEZING || INCL_ISW
608 ufix8 FONTFAR *save_pointer;
616 sp_globals.squeezing_compound = FALSE;
617 if ((sp_globals.pspecs->flags & SQUEEZE_LEFT) ||
618 (sp_globals.pspecs->flags & SQUEEZE_RIGHT) ||
619 (sp_globals.pspecs->flags & SQUEEZE_TOP) ||
620 (sp_globals.pspecs->flags & SQUEEZE_BOTTOM) )
622 /* get the bounding box data before processing the character */
623 save_pointer = pointer;
624 preview_bounding_box (pointer, format);
625 pointer = save_pointer;
629 if (sp_globals.import_setwidth_act)
631 save_pointer = pointer;
632 preview_bounding_box (pointer, format);
633 pointer = save_pointer;
634 /* make sure I'm not going to get fixed point overflow */
635 isw_scale = compute_isw_scale();
636 if (sp_globals.bbox_xmin_orus < 0)
637 char_width = SQUEEZE_MULT((sp_globals.bbox_xmax_orus - sp_globals.bbox_xmin_orus), isw_scale);
639 char_width = SQUEEZE_MULT(sp_globals.bbox_xmax_orus, isw_scale);
640 if (char_width >= sp_globals.isw_xmax)
641 if (!reset_xmax(char_width))
645 pointer = plaid_tcb(pointer, format); /* Process plaid data */
646 pointer = read_bbox(pointer, &Pmin, &Pmax, FALSE); /* Read bounding box */
647 if (fn_begin_char(sp_globals.Psw, Pmin, Pmax)) /* Signal start of character output */
651 proc_outl_data(pointer); /* Process outline data */
653 while (!fn_end_char()); /* Repeat if not done */
658 FUNCTION static boolean sp_make_comp_char(pointer)
660 ufix8 FONTFAR *pointer; /* Pointer to first byte of position argument */
662 * Called by sp_make_char() to output a compound character.
663 * Returns FALSE if data for any sub-character is not available.
664 * Returns TRUE if output completed with no error.
667 point_t Pmin, Pmax; /* Transformed corners of bounding box */
668 point_t Pssw; /* Transformed escapement vector */
669 ufix8 FONTFAR *pointer_sav; /* Saved pointer to compound character data */
670 ufix8 FONTFAR *sub_pointer; /* Pointer to sub-character data */
671 ufix8 format; /* Format of DOCH instruction */
672 ufix16 sub_char_index; /* Index to sub-character in character directory */
673 fix15 x_posn; /* X position of sub-character (outline res units) */
674 fix15 y_posn; /* Y position of sub-character (outline res units) */
675 fix15 x_scale; /* X scale factor of sub-character (scale units) */
676 fix15 y_scale; /* Y scale factor of sub-character (scale units) */
677 fix15 tmpfix15; /* Temporary workspace */
678 fix15 x_orus; /* Set width in outline resolution units */
679 fix15 pix_adj; /* Pixel adjustment to compound char bounding box */
681 fix31 x_factor, x_offset, top_scale, bottom_scale;
682 boolean squeezed_x, squeezed_y;
684 #if INCL_SQUEEZING || INCL_ISW
694 sp_globals.squeezing_compound = TRUE;
696 pointer = read_bbox(pointer, &Pmin, &Pmax, TRUE); /* Read bounding box data */
697 pix_adj = sp_globals.onepix << 1; /* Allow 2 pixel expansion ... */
698 Pmin.x -= pix_adj; /* ... of components of ... */
699 Pmin.y -= pix_adj; /* ... compound ... */
700 Pmax.x += pix_adj; /* ... character ... */
701 Pmax.y += pix_adj; /* ... bounding box. */
704 /* scale the bounding box if necessary before calling begin_char */
705 squeezed_x = calculate_x_scale(&x_factor, &x_offset, 0);
706 squeezed_y = calculate_y_scale(&top_scale, &bottom_scale,0,0);
709 { /* scale the x coordinates of the bbox */
710 x_offset_pix = (fix15)(((x_offset >> 16) * sp_globals.tcb0.xppo)
711 >> sp_globals.mpshift);
712 if ((x_offset_pix >0) && (x_offset_pix < sp_globals.onepix))
713 x_offset_pix = sp_globals.onepix;
714 Pmin.x = SQUEEZE_MULT (x_factor, Pmin.x) + x_offset_pix - pix_adj;
715 Pmax.x = SQUEEZE_MULT (x_factor, Pmax.x) + x_offset_pix + pix_adj;
718 { /* scale the y coordinates of the bbox */
720 Pmin.y = SQUEEZE_MULT (bottom_scale, Pmin.y) - pix_adj;
722 Pmin.y = SQUEEZE_MULT (top_scale, Pmin.y) - pix_adj;
724 Pmax.y = SQUEEZE_MULT (bottom_scale, Pmax.y) + pix_adj;
726 Pmax.y = SQUEEZE_MULT (top_scale, Pmax.y) + pix_adj;
730 if (sp_globals.import_setwidth_act)
732 /* make sure I'm not going to get fixed point overflow */
733 isw_scale = ((fix31)sp_globals.imported_width << 16)/
734 (fix31)sp_globals.setwidth_orus;
735 char_width = SQUEEZE_MULT((sp_globals.bbox_xmax_orus -
736 sp_globals.bbox_xmin_orus),
738 if (char_width >= sp_globals.isw_xmax)
739 if (!reset_xmax(char_width))
744 if (fn_begin_char(sp_globals.Psw, Pmin, Pmax)) /* Signal start of character data */
746 pointer_sav = pointer;
749 pointer = pointer_sav; /* Point to next DOCH or END instruction */
750 while (format = NEXT_BYTE(pointer)) /* DOCH instruction? */
752 init_tcb(); /* Initialize transformation control block */
753 x_posn = sp_get_posn_arg(&pointer, format);
754 y_posn = sp_get_posn_arg(&pointer, (ufix8)(format >> 2));
755 x_scale = sp_get_scale_arg(&pointer, (ufix8)(format & BIT4));
756 y_scale = sp_get_scale_arg(&pointer, (ufix8)(format & BIT5));
757 scale_tcb(&sp_globals.tcb, x_posn, y_posn, x_scale, y_scale); /* Scale for sub-char */
758 sub_char_index = (format & BIT6)? /* Read sub-char index */
759 0xffff & NEXT_WORD(pointer):
760 0xffff & NEXT_BYTE(pointer);
761 sub_pointer = sp_get_char_org(sub_char_index, FALSE); /* Point to start of sub-char */
762 if (sub_pointer == NULL) /* Character data not available? */
764 return FALSE; /* Abort character output */
766 sub_pointer += 2; /* Skip over character id */
767 x_orus = NEXT_WORD(sub_pointer); /* Read set_width of sub-character */
771 ((fix31)x_orus * (sp_globals.specs.xxmult>>16) +
772 ( ((fix31)x_orus * (sp_globals.specs.xxmult&0xffffL) )>>16)
773 ) << sp_globals.pixshift) / sp_globals.metric_resolution);
776 ((fix31)x_orus * (sp_globals.specs.yxmult>>16) +
777 ( ((fix31)x_orus * (sp_globals.specs.yxmult&0xffffL) )>>16)
778 ) << sp_globals.pixshift) / sp_globals.metric_resolution);
780 format = NEXT_BYTE(sub_pointer); /* Read sub-character format */
781 if (format & BIT1) /* Optional data in header? */
783 tmpfix15 = (ufix8)NEXT_BYTE(sub_pointer); /* Read size of optional data */
784 sub_pointer += tmpfix15; /* Skip optional data */
786 sub_pointer = plaid_tcb(sub_pointer, format); /* Process sub-character plaid data */
787 sub_pointer = read_bbox(sub_pointer, &Pmin, &Pmax, FALSE); /* Read bounding box */
788 fn_begin_sub_char(Pssw, Pmin, Pmax); /* Signal start of sub-character data */
789 proc_outl_data(sub_pointer); /* Process sub-character data */
790 fn_end_sub_char(); /* Signal end of sub-character data */
793 while (!fn_end_char()); /* Signal end of character; repeat if required */
798 #if INCL_LCD /* Dynamic load character data supported? */
799 FUNCTION static ufix8 FONTFAR *sp_get_char_org(char_index, top_level)
801 ufix16 char_index; /* Index of character to be accessed */
802 boolean top_level; /* Not a compound character element */
804 * Called by sp_get_char_id(), sp_get_char_width(), sp_make_char() and
805 * sp_make_comp_char() to get a pointer to the start of the character data
806 * for the specified character index.
807 * Version for configuration supporting dynamic character data loading.
808 * Calls load_char_data() to load character data if not already loaded
809 * as part of the original font buffer.
810 * Returns NULL if character data not available
813 buff_t *pchar_data; /* Buffer descriptor requested */
814 ufix8 FONTFAR *pointer; /* Pointer into character directory */
815 ufix8 format; /* Character directory format byte */
816 fix31 char_offset; /* Offset of char data from start of font file */
817 fix31 next_char_offset; /* Offset of char data from start of font file */
818 fix15 no_bytes; /* Number of bytes required for char data */
820 if (top_level) /* Not element of compound char? */
822 if (char_index < sp_globals.first_char_idx) /* Before start of character set? */
824 char_index -= sp_globals.first_char_idx;
825 if (char_index >= sp_globals.no_chars_avail) /* Beyond end of character set? */
827 sp_globals.cb_offset = 0; /* Reset char buffer offset */
830 pointer = sp_globals.pchar_dir;
831 format = NEXT_BYTE(pointer); /* Read character directory format byte */
832 pointer += char_index << 1; /* Point to indexed character entry */
833 if (format) /* 3-byte entries in char directory? */
835 pointer += char_index; /* Adjust for 3-byte entries */
836 char_offset = read_long(pointer); /* Read file offset to char data */
837 next_char_offset = read_long(pointer + 3); /* Read offset to next char */
841 char_offset = (fix31)(0xffff & NEXT_WORD(pointer)); /* Read file offset to char data */
842 next_char_offset = (fix31)(0xffff & NEXT_WORD(pointer)); /* Read offset to next char */
845 no_bytes = next_char_offset - char_offset;
846 if (no_bytes == 0) /* Character not in directory? */
849 if (next_char_offset <= sp_globals.font_buff_size)/* Character data already in font buffer? */
850 return sp_globals.pfont->org + char_offset; /* Return pointer into font buffer */
852 pchar_data = load_char_data(char_offset, no_bytes, sp_globals.cb_offset); /* Request char data load */
853 if (pchar_data->no_bytes < no_bytes) /* Correct number of bytes loaded? */
856 if (top_level) /* Not element of compound char? */
858 sp_globals.cb_offset = no_bytes;
861 return pchar_data->org; /* Return pointer into character data buffer */
866 #else /* Dynamic load character data not supported? */
867 FUNCTION static ufix8 FONTFAR *sp_get_char_org(char_index, top_level)
869 ufix16 char_index; /* Index of character to be accessed */
870 boolean top_level; /* Not a compound character element */
872 * Called by sp_get_char_id(), sp_get_char_width(), sp_make_char() and
873 * sp_make_comp_char() to get a pointer to the start of the character data
874 * for the specified character index.
875 * Version for configuration not supporting dynamic character data loading.
876 * Returns NULL if character data not available
879 ufix8 FONTFAR *pointer; /* Pointer into character directory */
880 ufix8 format; /* Character directory format byte */
881 fix31 char_offset; /* Offset of char data from start of font file */
882 fix31 next_char_offset; /* Offset of char data from start of font file */
883 fix15 no_bytes; /* Number of bytes required for char data */
885 if (top_level) /* Not element of compound char? */
887 if (char_index < sp_globals.first_char_idx) /* Before start of character set? */
889 char_index -= sp_globals.first_char_idx;
890 if (char_index >= sp_globals.no_chars_avail) /* Beyond end of character set? */
894 pointer = sp_globals.pchar_dir;
895 format = NEXT_BYTE(pointer); /* Read character directory format byte */
896 pointer += char_index << 1; /* Point to indexed character entry */
897 if (format) /* 3-byte entries in char directory? */
899 pointer += char_index; /* Adjust for 3-byte entries */
900 char_offset = read_long(pointer); /* Read file offset to char data */
901 next_char_offset = read_long(pointer + 3); /* Read offset to next char */
905 char_offset = (fix31)(0xffff & NEXT_WORD(pointer)); /* Read file offset to char data */
906 next_char_offset = (fix31)(0xffff & NEXT_WORD(pointer)); /* Read offset to next char */
909 no_bytes = next_char_offset - char_offset;
910 if (no_bytes == 0) /* Character not in directory? */
913 return sp_globals.pfont->org + char_offset; /* Return pointer into font buffer */
918 FUNCTION static fix15 sp_get_posn_arg(ppointer, format)
920 ufix8 FONTFAR * STACKFAR *ppointer; /* Pointer to first byte of position argument */
921 ufix8 format; /* Format of DOCH arguments */
923 * Called by sp_make_comp_char() to read a position argument from the
924 * specified point in the font/char buffer.
925 * Updates pointer to byte following position argument.
926 * Returns value of position argument in outline resolution units
929 switch (format & 0x03)
932 return NEXT_WORD(*ppointer);
935 return (fix15)((fix7)NEXT_BYTE(*ppointer));
942 FUNCTION static fix15 sp_get_scale_arg(ppointer, format)
944 ufix8 FONTFAR *STACKFAR *ppointer; /* Pointer to first byte of position argument */
945 ufix8 format; /* Format of DOCH arguments */
947 * Called by sp_make_comp_char() to read a scale argument from the
948 * specified point in the font/char buffer.
949 * Updates pointer to byte following scale argument.
950 * Returns value of scale argument in scale units (normally 1/4096)
954 return NEXT_WORD(*ppointer);
956 return (fix15)ONE_SCALE;
958 #if INCL_ISW || INCL_SQUEEZING
959 FUNCTION static void preview_bounding_box(pointer,format)
961 ufix8 FONTFAR *pointer; /* Pointer to first byte of position argument */
962 ufix8 format; /* Character format byte */
964 point_t Pmin, Pmax; /* Transformed corners of bounding box */
966 sp_globals.no_X_orus = (format & BIT2)?
967 (fix15)NEXT_BYTE(pointer):
969 sp_globals.no_Y_orus = (format & BIT3)?
970 (fix15)NEXT_BYTE(pointer):
972 pointer = read_oru_table(pointer);
974 /* Skip over control zone table */
975 pointer = skip_control_zone(pointer,format);
977 /* Skip over interpolation table */
978 pointer = skip_interpolation_table(pointer,format);
979 /* get_args has a pathological need for this value to be set */
980 sp_globals.Y_edge_org = sp_globals.no_X_orus;
981 pointer = read_bbox(pointer, &Pmin, &Pmax, TRUE); /* Read bounding bo
987 FUNCTION static boolean reset_xmax(xmax)
992 fix15 xmin; /* Minimum X ORU value in font */
993 fix15 ymin; /* Minimum Y ORU value in font */
994 fix15 ymax; /* Maximum Y ORU value in font */
997 sp_globals.isw_modified_constants = TRUE;
998 xmin = read_word_u(sp_globals.font_org + FH_FXMIN);
999 ymin = read_word_u(sp_globals.font_org + FH_FYMIN);
1000 ymax = read_word_u(sp_globals.font_org + FH_FYMAX);
1002 if (!setup_consts(xmin,xmax,ymin,ymax))
1004 report_error(3); /* Requested specs out of range */
1007 sp_globals.constr.data_valid = FALSE;
1008 /* recompute setwidth */
1009 sp_globals.Psw.x = (fix15)((fix31)(
1010 ((fix31)sp_globals.imported_width * (sp_globals.specs.xxmult>>16) +
1011 ( ((fix31)sp_globals.imported_width *
1012 (sp_globals.specs.xxmult&0xffffL) )>>16)
1013 ) << sp_globals.pixshift) / sp_globals.metric_resolution);
1014 sp_globals.Psw.y = (fix15)(
1016 ((fix31)sp_globals.imported_width * (sp_globals.specs.yxmult>>16) +
1017 ( ((fix31)sp_globals.imported_width * (sp_globals.specs.yxmult&0xffffL) )>>16)
1018 ) << sp_globals.pixshift) / sp_globals.metric_resolution);