4 * Copyright (C) 2011-2017 by Werner Lemberg.
6 * This file is part of the ttfautohint library, and may only be used,
7 * modified, and distributed under the terms given in `COPYING'. By
8 * continuing to use, modify, or distribute this file you indicate that you
9 * have read `COPYING' and understand and accept it fully.
11 * The file `COPYING' mentioned in the previous paragraph is distributed
12 * with the ttfautohint library.
19 /* we need the following macro */
20 /* so that `func_name' doesn't get replaced with its #defined value */
21 /* (as defined in `tabytecode.h') */
23 #define FPGM(func_name) fpgm_ ## func_name
27 * Due to a bug in FreeType up to and including version 2.4.7,
28 * it is not possible to use MD_orig with twilight points.
29 * We circumvent this by using GC_orig.
31 #define MD_orig_fixed \
38 #define MD_orig_ZP2_0 \
42 #define MD_orig_ZP2_1 \
54 * Older versions of Monotype's `iType' bytecode interpreter have a serious
55 * bug: The DIV instruction rounds the result, while the correct operation
56 * is truncation. (Note, however, that MUL always rounds the result.)
57 * Since many printers contain this rasterizer without any possibility to
58 * update to a non-buggy version, we have to work around the problem.
60 * DIV and MUL work on 26.6 numbers which means that the numerator gets
61 * multiplied by 64 before the division, and the product gets divided by 64
62 * after the multiplication, respectively. For example, to divide 2 by 3,
70 * The correct formula to divide two values in 26.6 format with truncation
75 * while older `iType' versions incorrectly apply rounding by using
79 * Doing our 2/3 division, we have a=2 and b=3*64, so we get
81 * (2*64 + (3*64)/2) / (3*64) = 1
83 * instead of the correct result 0.
85 * The solution to the rounding issue is to use a 26.6 value as an
86 * intermediate result so that we can truncate to the nearest integer (in
87 * 26.6 format) with the FLOOR operator before converting back to a plain
88 * integer (in 32.0 format).
90 * For the common divisions by 2 and 2^10 we define macros.
92 #define DIV_POS_BY_2 \
95 DIV, /* multiply by 64, then divide by 2 */ \
99 MUL /* multiply by 1, then divide by 64 */
112 ADD, /* add 1 if value is negative */ \
119 #define DIV_BY_1024 \
139 /* a convenience shorthand for scaling; see `bci_cvt_rescale' for details */
145 MUL, /* delta * 2^10 */ \
146 DIV_BY_1024, /* delta */ \
150 /* in the comments below, the top of the stack (`s:') */
151 /* is the rightmost element; the stack is shown */
152 /* after the instruction on the same line has been executed */
158 * Optimize the alignment of the top of small letters to the pixel grid.
160 * This function gets used in the `prep' table.
162 * in: blue_idx (CVT index for the style's top of small letters blue zone)
164 * sal: sal_i (CVT index of the style's scaling value;
165 * gets incremented by 1 after execution)
168 static const unsigned char FPGM(bci_align_x_height_a
) [] =
175 /* only get CVT value for non-zero index */
184 DUP
, /* s: blue blue blue */
188 /* if (font->increase_x_height) */
191 static const unsigned char FPGM(bci_align_x_height_b1a
) [] =
194 /* apply much `stronger' rounding up of x height for */
195 /* 6 <= PPEM <= increase_x_height */
201 /* %d, x height increase limit */
203 static const unsigned char FPGM(bci_align_x_height_b1b
) [] =
214 52, /* threshold = 52 */
218 40, /* threshold = 40 */
222 FLOOR
, /* fitted = FLOOR(blue + threshold) */
228 /* if (!font->increase_x_height) */
231 static const unsigned char FPGM(bci_align_x_height_b2
) [] =
237 FLOOR
, /* fitted = FLOOR(blue + 40) */
243 static const unsigned char FPGM(bci_align_x_height_c
) [] =
246 DUP
, /* s: blue blue fitted fitted */
249 IF
, /* s: blue fitted */
253 SUB
, /* s: blue (fitted-blue) */
260 MUL
, /* (fitted-blue) in 16.16 format */
262 DIV
, /* factor = ((fitted-blue) / blue) in 16.16 format */
274 RS
, /* s: factor idx */
283 ADD
, /* sal_i = sal_i + 1 */
294 * Round a 26.6 number. Contrary to the ROUND bytecode instruction, no
295 * engine specific corrections are applied.
302 static const unsigned char FPGM(bci_round
) [] =
320 * bci_quantize_stem_width
322 * Take a stem width and compare it against a set of already stored stem
323 * widths. If the difference to one of the values is less than 4, replace
324 * the argument with the stored one. Otherwise add the argument to the
325 * array of stem widths, without changing the argument.
327 * We do this to catch rounding errors.
331 * out: quantized(val)
333 * sal: sal_num_stem_widths
334 * sal_stem_width_offset
337 * sal_have_cached_width
338 * sal_cached_width_offset
341 static const unsigned char FPGM(bci_quantize_stem_width
) [] =
345 bci_quantize_stem_width
,
349 ABS
, /* s: val |val| */
353 sal_stem_width_offset
,
354 sal_have_cached_width
,
356 WS
, /* sal_have_cached_width = 0 */
363 ADD
, /* sal_limit = sal_stem_width_offset + 2 * sal_num_stem_widths */
368 sal_stem_width_offset
,
370 WS
, /* sal_k = sal_stem_width_offset */
374 37, /* not_in_array jump offset */
380 EQ
, /* sal_limit == sal_k ? */
381 JROT
,/* goto not_in_array */
385 12, /* found_stem jump offset */
390 RS
, /* cur_stem_width = sal[sal_k] */
395 LT
, /* |val - cur_stem_width| < 4 ? */
396 JROT
, /* goto found_stem */
403 ADD
, /* sal_k = sal_k + 2, skipping associated cache value */
407 33, /* start_loop jump offset */
409 JMPR
, /* goto start_loop */
412 POP
, /* discard val */
416 RS
, /* val = sal[sal_k] */
418 14, /* exit jump offset */
419 sal_have_cached_width
,
421 WS
, /* sal_have_cached_width = 1 */
422 JMPR
, /* goto exit */
430 WS
, /* sal[sal_k] = val */
438 WS
, /* sal_num_stem_widths = sal_num_stem_widths + 1 */
441 SWAP
, /* s: |new_val| val */
446 NEG
, /* new_val = -new_val */
449 /* for input width array index `n' we have (or soon will have) */
450 /* a cached output width at array index `n + 1' */
452 sal_cached_width_offset
,
457 WS
, /* sal_cached_width_offset = sal_k + 1 */
465 * bci_natural_stem_width
467 * This dummy function only pops arguments as necessary.
476 static const unsigned char FPGM(bci_natural_stem_width
) [] =
480 bci_natural_stem_width
,
494 * bci_smooth_stem_width
496 * This is the equivalent to the following code from function
497 * `ta_latin_compute_stem_width':
505 * else if base_is_round:
511 * delta = |dist - std_width|
522 * delta = delta - dist
525 * dist = dist + delta
526 * else if delta < 32:
528 * else if delta < 54:
531 * dist = dist + delta
535 * if width * base_delta > 0:
537 * bdelta = base_delta
539 * bdelta = (base_delta * (30 - ppem)) / 20
543 * dist = ROUND(dist - bdelta)
550 * If `cvtl_ignore_std_width' is set, we simply set `std_width'
553 * If `sal_have_cached_width' is set (by `bci_quantize_stem_width'), the
554 * cached value given by `sal_cached_width_offset' is directly taken, not
555 * computing the width again. Otherwise, the computed width gets stored
556 * at the given offset.
564 * sal: sal_vwidth_data_offset
566 * sal_have_cached_width
567 * sal_cached_width_offset
570 * cvtl_ignore_std_width
573 * bci_quantize_stem_width
576 static const unsigned char FPGM(bci_smooth_stem_width
) [] =
580 bci_smooth_stem_width
,
584 bci_quantize_stem_width
,
588 sal_have_cached_width
,
597 sal_cached_width_offset
,
599 RS
, /* cached_width = sal[sal_cached_width_offset] */
605 NEG
, /* cached_width = -cached_width */
610 ABS
, /* s: base_is_round stem_is_serif width dist */
615 LT
, /* dist < 3*64 */
619 MINDEX
, /* s: base_is_round width dist (dist<3*64) stem_is_serif */
620 AND
, /* stem_is_serif && dist < 3*64 */
625 sal_vwidth_data_offset
,
627 RCVT
, /* first indirection */
628 MUL
, /* divide by 64 */
629 RCVT
, /* second indirection */
632 cvtl_ignore_std_width
,
635 POP
, /* s: ... dist (stem_is_serif && dist < 3*64) 40 */
638 CINDEX
, /* standard_width = dist */
641 GT
, /* standard_width < 40 */
642 OR
, /* (stem_is_serif && dist < 3*64) || standard_width < 40 */
644 IF
, /* s: base_is_round width dist */
650 ROLL
, /* s: width dist base_is_round */
651 IF
, /* s: width dist */
656 IF
, /* s: width dist */
667 IF
, /* s: width dist */
674 DUP
, /* s: width dist dist */
677 sal_vwidth_data_offset
,
679 RCVT
, /* first indirection */
680 MUL
, /* divide by 64 */
681 RCVT
, /* second indirection */
683 ABS
, /* s: width dist delta */
688 IF
, /* s: width dist */
692 sal_vwidth_data_offset
,
694 RCVT
, /* first indirection */
695 MUL
, /* divide by 64 */
696 RCVT
, /* second indirection; dist = std_width */
708 DUP
, /* s: width dist dist */
711 LT
, /* dist < 3*64 */
713 DUP
, /* s: width delta dist */
714 FLOOR
, /* dist = FLOOR(dist) */
715 DUP
, /* s: width delta dist dist */
717 ROLL
, /* s: width dist delta dist */
718 SUB
, /* delta = delta - dist */
720 DUP
, /* s: width dist delta delta */
724 IF
, /* s: width dist delta */
725 ADD
, /* dist = dist + delta */
736 ADD
, /* dist = dist + 10 */
747 ADD
, /* dist = dist + 54 */
750 ADD
, /* dist = dist + delta */
759 CINDEX
, /* s: width dist width */
763 MUL
, /* s: width dist width*base_delta */
766 GT
, /* width * base_delta > 0 */
769 0, /* s: width dist bdelta */
779 RS
, /* bdelta = base_delta */
795 MUL
, /* (30 - ppem) in 26.6 format */
799 MUL
, /* base_delta * (30 - ppem) */
803 DIV
, /* bdelta = (base_delta * (30 - ppem)) / 20 */
807 ABS
, /* bdelta = |bdelta| */
808 SUB
, /* dist = dist - bdelta */
813 CALL
, /* dist = round(dist) */
818 SWAP
, /* s: dist width */
823 NEG
, /* dist = -dist */
830 sal_cached_width_offset
,
833 WS
, /* sal[sal_cached_width_offset] = |dist| */
844 * An auxiliary function for `bci_strong_stem_width'.
846 * in: n (initialized with CVT index for first vertical width)
858 static const unsigned char FPGM(bci_get_best_width
) [] =
866 RCVT
, /* s: dist n w */
870 CINDEX
, /* s: dist n w w dist */
872 ABS
, /* s: dist n w d */
876 RS
, /* s: dist n w d d best */
886 WS
, /* reference = w */
903 * bci_strong_stem_width
905 * This is the equivalent to the following code (function
906 * `ta_latin_snap_width' and some lines from
907 * `ta_latin_compute_stem_width'):
913 * for n in 0 .. num_widths:
921 * if dist >= reference:
922 * if dist < ROUND(reference) + 48:
925 * if dist > ROUND(reference) - 48:
937 * If `cvtl_ignore_std_width' is set, we leave `reference = width'.
940 * stem_is_serif (unused)
941 * base_is_round (unused)
947 * sal_vwidth_data_offset
950 * cvtl_ignore_std_width
952 * uses: bci_get_best_width
954 * bci_quantize_stem_width
957 static const unsigned char FPGM(bci_strong_stem_width_a
) [] =
961 bci_strong_stem_width
,
970 bci_quantize_stem_width
,
974 ABS
, /* s: width dist */
979 WS
, /* sal_best = 98 */
985 WS
, /* sal_ref = width */
988 cvtl_ignore_std_width
,
996 sal_vwidth_data_offset
,
999 MUL
, /* divide by 64; first index of vertical widths */
1001 /* s: width dist vw_idx */
1004 sal_vwidth_data_offset
,
1010 /* %c, number of used styles */
1012 static const unsigned char FPGM(bci_strong_stem_width_b
) [] =
1016 RCVT
, /* number of vertical widths */
1017 MUL
, /* divide by 64 */
1019 /* s: width dist vw_idx loop_count */
1023 /* clean up stack */
1024 POP
, /* s: width dist */
1029 RS
, /* s: width dist dist reference */
1036 CALL
, /* s: width dist reference dist dist ROUND(reference) */
1040 CINDEX
, /* s: width dist reference dist dist ROUND(reference) 48 reference */
1043 MINDEX
, /* s: width dist reference dist ROUND(reference) 48 reference dist */
1045 LTEQ
, /* reference <= dist */
1046 IF
, /* s: width dist reference dist ROUND(reference) 48 */
1048 LT
, /* dist < ROUND(reference) + 48 */
1052 GT
, /* dist > ROUND(reference) - 48 */
1056 SWAP
, /* s: width reference=new_dist dist */
1059 EIF
, /* !cvtl_ignore_std_width */
1061 DUP
, /* s: width dist dist */
1064 GTEQ
, /* dist >= 64 */
1068 CALL
, /* dist = ROUND(dist) */
1076 SWAP
, /* s: dist width */
1081 NEG
, /* dist = -dist */
1092 * An auxiliary function for `bci_loop'.
1094 * sal: sal_i (gets incremented by 2 after execution)
1097 * uses: func[sal_func]
1100 static const unsigned char FPGM(bci_loop_do
) [] =
1117 ADD
, /* sal_i = sal_i + 2 */
1128 * Take a range `start'..`end' and a function number and apply the
1129 * associated function to the range elements `start', `start+2',
1136 * sal: sal_i (counter initialized with `start')
1137 * sal_func (`func_num')
1142 static const unsigned char FPGM(bci_loop
) [] =
1152 WS
, /* sal_func = func_num */
1159 WS
, /* sal_i = start */
1165 ADD
, /* number of loops ((end - start) / 2 + 1) */
1179 * Rescale CVT value by `sal_scale' (in 16.16 format).
1181 * The scaling factor `sal_scale' isn't stored as `b/c' but as `(b-c)/c';
1182 * consequently, the calculation `a * b/c' is done as `a + delta' with
1183 * `delta = a * (b-c)/c'. This avoids overflow.
1192 static const unsigned char FPGM(bci_cvt_rescale
) [] =
1215 * bci_cvt_rescale_range
1217 * Rescale a range of CVT values with `bci_cvt_rescale', using a custom
1220 * This function gets used in the `prep' table.
1225 * sal: sal_i (CVT index of the style's scaling value;
1226 * gets incremented by 1 after execution)
1229 * uses: bci_cvt_rescale
1232 static const unsigned char FPGM(bci_cvt_rescale_range
) [] =
1236 bci_cvt_rescale_range
,
1239 /* store scaling value in `sal_scale' */
1246 WS
, /* s: cvt_start_idx num_cvt bci_cvt_rescale */
1249 /* clean up stack */
1257 ADD
, /* sal_i = sal_i + 1 */
1266 * bci_vwidth_data_store
1268 * Store a vertical width array value.
1270 * This function gets used in the `prep' table.
1274 * sal: sal_i (CVT index of the style's vwidth data;
1275 * gets incremented by 1 after execution)
1278 static const unsigned char FPGM(bci_vwidth_data_store
) [] =
1282 bci_vwidth_data_store
,
1296 ADD
, /* sal_i = sal_i + 1 */
1305 * bci_smooth_blue_round
1307 * Round a blue ref value and adjust its corresponding shoot value.
1309 * This is the equivalent to the following code (function
1310 * `ta_latin_metrics_scale_dim'):
1318 * else if delta < 48:
1328 * sal: sal_i (number of blue zones)
1335 static const unsigned char FPGM(bci_smooth_blue_round
) [] =
1339 bci_smooth_blue_round
,
1344 RCVT
, /* s: ref_idx ref_idx ref */
1350 SWAP
, /* s: ref_idx ref_idx round(ref) ref */
1358 ADD
, /* s: ref_idx ref_idx round(ref) ref shoot_idx */
1360 RCVT
, /* s: ref_idx ref_idx round(ref) ref shoot_idx shoot */
1362 ROLL
, /* s: ref_idx ref_idx round(ref) shoot_idx shoot ref */
1364 SUB
, /* s: ref_idx ref_idx round(ref) shoot_idx dist */
1366 ABS
, /* s: ref_idx ref_idx round(ref) shoot_idx dist delta */
1371 LT
, /* delta < 32 */
1380 LT
, /* delta < 48 */
1383 32, /* delta = 32 */
1387 64, /* delta = 64 */
1391 SWAP
, /* s: ref_idx ref_idx round(ref) shoot_idx delta dist */
1396 NEG
, /* delta = -delta */
1403 SUB
, /* s: ref_idx ref_idx round(ref) shoot_idx (round(ref) - delta) */
1410 ADD
, /* s: (ref_idx + 1) */
1418 * bci_strong_blue_round
1420 * Round a blue ref value and adjust its corresponding shoot value.
1422 * This is the equivalent to the following code:
1436 * It doesn't have corresponding code in talatin.c; however, some tests
1437 * have shown that the `smooth' code works just fine for this case also.
1441 * sal: sal_i (number of blue zones)
1448 static const unsigned char FPGM(bci_strong_blue_round
) [] =
1452 bci_strong_blue_round
,
1457 RCVT
, /* s: ref_idx ref_idx ref */
1463 SWAP
, /* s: ref_idx ref_idx round(ref) ref */
1471 ADD
, /* s: ref_idx ref_idx round(ref) ref shoot_idx */
1473 RCVT
, /* s: ref_idx ref_idx round(ref) ref shoot_idx shoot */
1475 ROLL
, /* s: ref_idx ref_idx round(ref) shoot_idx shoot ref */
1477 SUB
, /* s: ref_idx ref_idx round(ref) shoot_idx dist */
1479 ABS
, /* s: ref_idx ref_idx round(ref) shoot_idx dist delta */
1483 LT
, /* delta < 36 */
1486 0, /* delta = 0 (set overshoot to zero if < 0.56 pixel units) */
1490 64, /* delta = 64 (one pixel unit) */
1493 SWAP
, /* s: ref_idx ref_idx round(ref) shoot_idx delta dist */
1498 NEG
, /* delta = -delta */
1505 SUB
, /* s: ref_idx ref_idx round(ref) shoot_idx (round(ref) - delta) */
1512 ADD
, /* s: (ref_idx + 1) */
1520 * bci_blue_round_range
1522 * Round a range of blue zones (both reference and shoot values).
1524 * This function gets used in the `prep' table.
1526 * in: num_blue_zones
1529 * sal: sal_i (holds a copy of `num_blue_zones' for blue rounding function)
1531 * uses: bci_smooth_blue_round
1532 * bci_strong_blue_round
1535 static const unsigned char FPGM(bci_blue_round_range
) [] =
1539 bci_blue_round_range
,
1548 /* select blue rounding function based on flag in CVT; */
1549 /* for value >0 we use strong mode, else smooth mode */
1551 bci_strong_blue_round
,
1552 bci_smooth_blue_round
,
1554 cvtl_stem_width_mode
,
1566 /* clean up stack */
1575 * bci_decrement_component_counter
1577 * An auxiliary function for composite glyphs.
1579 * CVT: cvtl_is_subglyph
1582 static const unsigned char FPGM(bci_decrement_component_counter
) [] =
1586 bci_decrement_component_counter
,
1589 /* decrement `cvtl_is_subglyph' counter */
1605 * bci_get_point_extrema
1607 * An auxiliary function for `bci_create_segment'.
1613 * sal: sal_point_min
1617 static const unsigned char FPGM(bci_get_point_extrema
) [] =
1621 bci_get_point_extrema
,
1630 /* check whether `point' is a new minimum */
1633 RS
, /* s: point point point point_min */
1635 /* if distance is negative, we have a new minimum */
1639 IF
, /* s: point point */
1647 /* check whether `point' is a new maximum */
1650 RS
, /* s: point point point_max */
1652 /* if distance is positive, we have a new maximum */
1672 * Pop a byte with two delta arguments in its nibbles and push the
1673 * expanded arguments separately as two bytes.
1675 * in: 16 * (end - start) + (start - base)
1680 * sal: sal_base (set to `end' at return)
1684 static const unsigned char FPGM(bci_nibbles
) [] =
1691 PUSHB_1
, /* cf. DIV_POS_BY_2 macro */
1697 MUL
, /* s: in hnibble */
1702 MUL
, /* s: in hnibble (hnibble * 16) */
1705 SUB
, /* s: hnibble lnibble */
1710 ADD
, /* s: hnibble start */
1713 ADD
, /* s: start end */
1719 WS
, /* sal_base = end */
1729 * bci_number_set_is_element
1731 * Pop values from stack until it is empty. If one of them is equal to
1732 * the current PPEM value, set `cvtl_is_element' to 100 (and to 0
1739 * CVT: cvtl_is_element
1742 static const unsigned char FPGM(bci_number_set_is_element
) [] =
1746 bci_number_set_is_element
,
1764 JROT
, /* goto start_loop if stack depth != 0 */
1772 * bci_number_set_is_element2
1774 * Pop value ranges from stack until it is empty. If one of them contains
1775 * the current PPEM value, set `cvtl_is_element' to 100 (and to 0
1778 * in: ppem_range_1_start
1780 * ppem_range_2_start
1784 * CVT: cvtl_is_element
1787 static const unsigned char FPGM(bci_number_set_is_element2
) [] =
1791 bci_number_set_is_element2
,
1815 JROT
, /* goto start_loop if stack depth != 0 */
1823 * bci_create_segment
1825 * Store start and end point of a segment in the storage area,
1826 * then construct a point in the twilight zone to represent it.
1828 * This function is used by `bci_create_segments'.
1832 * [last (if wrap-around segment)]
1833 * [first (if wrap-around segment)]
1835 * sal: sal_i (start of current segment)
1836 * sal_j (current twilight point)
1840 * sal_num_packed_segments
1845 * uses: bci_get_point_extrema
1848 * If `sal_num_packed_segments' is > 0, the start/end pair is stored as
1849 * delta values in nibbles (without a wrap-around segment).
1852 static const unsigned char FPGM(bci_create_segment
) [] =
1861 sal_num_packed_segments
,
1866 sal_num_packed_segments
,
1867 sal_num_packed_segments
,
1872 WS
, /* sal_num_packed_segments = sal_num_packed_segments - 1 */
1885 WS
, /* sal[sal_i] = start */
1887 /* initialize inner loop(s) */
1892 WS
, /* sal_point_min = start */
1897 WS
, /* sal_point_max = start */
1901 SZPS
, /* set zp0, zp1, and zp2 to normal zone 1 */
1907 CINDEX
, /* s: start end end start */
1908 LT
, /* start > end */
1910 /* we have a wrap-around segment with two more arguments */
1911 /* to give the last and first point of the contour, respectively; */
1912 /* our job is to store a segment `start'-`last', */
1913 /* and to get extrema for the two segments */
1914 /* `start'-`last' and `first'-`end' */
1916 /* s: first last start end */
1925 WS
, /* sal[sal_i + 1] = last */
1928 ROLL
, /* s: first end last start */
1931 SWAP
, /* s: first end start last start */
1932 SUB
, /* s: first end start loop_count */
1935 bci_get_point_extrema
,
1937 /* clean up stack */
1940 SWAP
, /* s: end first */
1945 ROLL
, /* s: (first - 1) (first - 1) end */
1947 SUB
, /* s: (first - 1) loop_count */
1950 bci_get_point_extrema
,
1952 /* clean up stack */
1955 ELSE
, /* s: start end */
1964 WS
, /* sal[sal_i + 1] = end */
1969 SUB
, /* s: start loop_count */
1972 bci_get_point_extrema
,
1974 /* clean up stack */
1978 /* the twilight point representing a segment */
1979 /* is in the middle between the minimum and maximum */
1989 DIV_BY_2
, /* s: middle_pos */
1991 DO_SCALE
, /* middle_pos = middle_pos * scale */
1993 /* write it to temporary CVT location */
1997 SZP0
, /* set zp0 to twilight zone 0 */
2001 /* create twilight point with index `sal_j' */
2014 ADD
, /* twilight_point = twilight_point + 1 */
2023 * bci_create_segments
2025 * This is the top-level entry function.
2027 * It pops point ranges from the stack to define segments, computes
2028 * twilight points to represent segments, and finally calls
2029 * `bci_hint_glyph' to handle the rest.
2031 * The second argument (`data_offset') addresses three CVT arrays in
2035 * the current style's scaling value (stored in `sal_scale')
2037 * data_offset + num_used_styles:
2038 * offset to the current style's vwidth index array (this value gets
2039 * stored in `sal_vwidth_data_offset')
2041 * data_offset + 2*num_used_styles:
2042 * offset to the current style's vwidth size
2044 * This addressing scheme ensures that (a) we only need a single argument,
2045 * and (b) this argument supports up to (256-cvtl_max_runtime) styles,
2046 * which should be sufficient for a long time.
2048 * in: num_packed_segments
2053 * [contour_last 0 (if wrap-around segment)]
2054 * [contour_first 0 (if wrap-around segment)]
2057 * [contour_last 0 (if wrap-around segment)]
2058 * [contour_first 0 (if wrap-around segment)]
2060 * segment_start_(N-1)
2062 * [contour_last (N-1) (if wrap-around segment)]
2063 * [contour_first (N-1) (if wrap-around segment)]
2064 * ... stuff for bci_hint_glyph ...
2066 * sal: sal_i (start of current segment)
2067 * sal_j (current twilight point)
2068 * sal_num_packed_segments
2069 * sal_base (the base for delta values in nibbles)
2070 * sal_vwidth_data_offset
2073 * CVT: cvtl_is_subglyph
2075 * uses: bci_create_segment
2079 * If `num_packed_segments' is set to p, the first p start/end pairs are
2080 * stored as delta values in nibbles, with the `start' delta in the lower
2081 * nibble (and there are no wrap-around segments). For example, if the
2082 * first three pairs are 1/3, 5/8, and 12/13, the topmost three bytes on the
2083 * stack are 0x21, 0x32, and 0x14.
2087 static const unsigned char FPGM(bci_create_segments_a
) [] =
2091 bci_create_segments
,
2094 /* all our measurements are taken along the y axis */
2097 /* only do something if we are not a subglyph */
2105 sal_num_packed_segments
,
2112 sal_scale
, /* sal_scale = CVT(data_offset) */
2117 sal_vwidth_data_offset
,
2123 /* %c, number of used styles */
2125 static const unsigned char FPGM(bci_create_segments_b
) [] =
2129 WS
, /* sal_vwidth_data_offset = data_offset + num_used_styles */
2133 sal_stem_width_offset
,
2135 WS
, /* sal_stem_width_offset = num_segments (more to come) */
2141 SUB
, /* delta = (2*num_segments - 1) */
2151 sal_num_stem_widths
,
2153 WS
, /* sal_num_stem_widths = 0 */
2154 WS
, /* sal_base = 0 */
2155 WS
, /* sal_j = 0 (point offset) */
2158 ADD
, /* s: ... sal_segment_offset (sal_segment_offset + delta) */
2162 sal_stem_width_offset
,
2166 sal_stem_width_offset
,
2168 WS
, /* sal_stem_width_offset += sal_segment_offset + delta */
2181 /* used if we have delta exceptions */
2183 static const unsigned char FPGM(bci_create_segments_c
) [] =
2192 static const unsigned char FPGM(bci_create_segments_d
) [] =
2205 * bci_create_segments_X
2207 * Top-level routines for calling `bci_create_segments'.
2210 static const unsigned char FPGM(bci_create_segments_0
) [] =
2214 bci_create_segments_0
,
2219 bci_create_segments
,
2226 static const unsigned char FPGM(bci_create_segments_1
) [] =
2230 bci_create_segments_1
,
2235 bci_create_segments
,
2242 static const unsigned char FPGM(bci_create_segments_2
) [] =
2246 bci_create_segments_2
,
2251 bci_create_segments
,
2258 static const unsigned char FPGM(bci_create_segments_3
) [] =
2262 bci_create_segments_3
,
2267 bci_create_segments
,
2274 static const unsigned char FPGM(bci_create_segments_4
) [] =
2278 bci_create_segments_4
,
2283 bci_create_segments
,
2290 static const unsigned char FPGM(bci_create_segments_5
) [] =
2294 bci_create_segments_5
,
2299 bci_create_segments
,
2306 static const unsigned char FPGM(bci_create_segments_6
) [] =
2310 bci_create_segments_6
,
2315 bci_create_segments
,
2322 static const unsigned char FPGM(bci_create_segments_7
) [] =
2326 bci_create_segments_7
,
2331 bci_create_segments
,
2338 static const unsigned char FPGM(bci_create_segments_8
) [] =
2342 bci_create_segments_8
,
2347 bci_create_segments
,
2354 static const unsigned char FPGM(bci_create_segments_9
) [] =
2358 bci_create_segments_9
,
2363 bci_create_segments
,
2374 * Wrapper functions around DELTAP[123] that touch the affected points
2375 * before applying the delta. This is necessary for ClearType.
2377 * While DELTAP[123] implicitly do a loop, we have to process the
2378 * arguments sequentially by calling `bci_deltaX' with LOOPCALL.
2384 static const unsigned char FPGM(bci_deltap1
) [] =
2392 DUP
, /* s: point arg arg */
2393 PUSHB_1
, /* cf. DIV_POS_BY_2 macro */
2399 MUL
, /* s: point arg hnibble(arg) */
2401 CONTROL_DELTA_PPEM_MIN
,
2402 ADD
, /* s: point arg ppem(arg) */
2408 MDAP_noround
, /* touch `point' */
2412 DELTAP1
, /* process one `(point,arg)' pair */
2422 static const unsigned char FPGM(bci_deltap2
) [] =
2430 DUP
, /* s: point arg arg */
2431 PUSHB_1
, /* cf. DIV_POS_BY_2 macro */
2437 MUL
, /* s: point arg hnibble(arg) */
2439 CONTROL_DELTA_PPEM_MIN
+ 16,
2440 ADD
, /* s: point arg ppem(arg) */
2446 MDAP_noround
, /* touch `point' */
2450 DELTAP2
, /* process one `(point,arg)' pair */
2460 static const unsigned char FPGM(bci_deltap3
) [] =
2468 DUP
, /* s: point arg arg */
2469 PUSHB_1
, /* cf. DIV_POS_BY_2 macro */
2475 MUL
, /* s: point arg hnibble(arg) */
2477 CONTROL_DELTA_PPEM_MIN
+ 32,
2478 ADD
, /* s: point arg ppem(arg) */
2484 MDAP_noround
, /* touch `point' */
2488 DELTAP3
, /* process one `(point,arg)' pair */
2500 * bci_create_segments_composite
2502 * The same as `bci_create_segments'.
2503 * It also decrements the composite component counter.
2505 * sal: sal_num_packed_segments
2506 * sal_segment_offset
2507 * sal_vwidth_data_offset
2509 * CVT: cvtl_is_subglyph
2511 * uses: bci_decrement_component_counter
2512 * bci_create_segment
2517 static const unsigned char FPGM(bci_create_segments_composite_a
) [] =
2521 bci_create_segments_composite
,
2524 /* all our measurements are taken along the y axis */
2528 bci_decrement_component_counter
,
2531 /* only do something if we are not a subglyph */
2539 sal_num_packed_segments
,
2546 sal_scale
, /* sal_scale = CVT(data_offset) */
2551 sal_vwidth_data_offset
,
2557 /* %c, number of used styles */
2559 static const unsigned char FPGM(bci_create_segments_composite_b
) [] =
2563 WS
, /* sal_vwidth_data_offset = data_offset + num_used_styles */
2569 SUB
, /* delta = (2*num_segments - 1) */
2579 WS
, /* sal_base = 0 */
2580 WS
, /* sal_j = 0 (point offset) */
2583 ADD
, /* s: ... sal_segment_offset (sal_segment_offset + delta) */
2596 /* used if we have delta exceptions */
2598 static const unsigned char FPGM(bci_create_segments_composite_c
) [] =
2607 static const unsigned char FPGM(bci_create_segments_composite_d
) [] =
2620 * bci_create_segments_composite_X
2622 * Top-level routines for calling `bci_create_segments_composite'.
2625 static const unsigned char FPGM(bci_create_segments_composite_0
) [] =
2629 bci_create_segments_composite_0
,
2634 bci_create_segments_composite
,
2641 static const unsigned char FPGM(bci_create_segments_composite_1
) [] =
2645 bci_create_segments_composite_1
,
2650 bci_create_segments_composite
,
2657 static const unsigned char FPGM(bci_create_segments_composite_2
) [] =
2661 bci_create_segments_composite_2
,
2666 bci_create_segments_composite
,
2673 static const unsigned char FPGM(bci_create_segments_composite_3
) [] =
2677 bci_create_segments_composite_3
,
2682 bci_create_segments_composite
,
2689 static const unsigned char FPGM(bci_create_segments_composite_4
) [] =
2693 bci_create_segments_composite_4
,
2698 bci_create_segments_composite
,
2705 static const unsigned char FPGM(bci_create_segments_composite_5
) [] =
2709 bci_create_segments_composite_5
,
2714 bci_create_segments_composite
,
2721 static const unsigned char FPGM(bci_create_segments_composite_6
) [] =
2725 bci_create_segments_composite_6
,
2730 bci_create_segments_composite
,
2737 static const unsigned char FPGM(bci_create_segments_composite_7
) [] =
2741 bci_create_segments_composite_7
,
2746 bci_create_segments_composite
,
2753 static const unsigned char FPGM(bci_create_segments_composite_8
) [] =
2757 bci_create_segments_composite_8
,
2762 bci_create_segments_composite
,
2769 static const unsigned char FPGM(bci_create_segments_composite_9
) [] =
2773 bci_create_segments_composite_9
,
2778 bci_create_segments_composite
,
2789 * An auxiliary function for `bci_align_segment'.
2796 static const unsigned char FPGM(bci_align_point
) [] =
2804 ALIGNRP
, /* align point with rp0 */
2818 * Align all points in a segment to the twilight point in rp0.
2819 * zp0 and zp1 must be set to 0 (twilight) and 1 (normal), respectively.
2823 * sal: sal_segment_offset
2825 * uses: bci_align_point
2828 static const unsigned char FPGM(bci_align_segment
) [] =
2835 /* we need the values of `sal_segment_offset + 2*segment_index' */
2836 /* and `sal_segment_offset + 2*segment_index + 1' */
2848 RS
, /* s: first last */
2852 CINDEX
, /* s: first last first */
2856 ADD
, /* s: first loop_count */
2861 /* clean up stack */
2870 * bci_align_segments
2872 * Align segments to the twilight point in rp0.
2873 * zp0 and zp1 must be set to 0 (twilight) and 1 (normal), respectively.
2882 * uses: bci_align_segment
2885 static const unsigned char FPGM(bci_align_segments
) [] =
2908 * Scale a contour using two points giving the maximum and minimum
2911 * It expects that no point on the contour is touched.
2919 static const unsigned char FPGM(bci_scale_contour
) [] =
2930 DO_SCALE
, /* min_pos_new = min_pos * scale */
2935 /* don't scale a single-point contour twice */
2944 DO_SCALE
, /* max_pos_new = max_pos * scale */
2961 * Scale a glyph using a list of points (two points per contour, giving
2962 * the maximum and mininum coordinates).
2964 * It expects that no point in the glyph is touched.
2966 * Note that the point numbers are sorted in ascending order;
2967 * `min_point_X' and `max_point_X' thus refer to the two extrema of a
2968 * contour without specifying which one is the minimum and maximum.
2970 * in: num_contours (N)
2979 * CVT: cvtl_is_subglyph
2984 * uses: bci_scale_contour
2987 static const unsigned char FPGM(bci_scale_glyph_a
) [] =
2994 /* all our measurements are taken along the y axis */
2997 /* only do something if we are not a subglyph */
3004 /* use fallback scaling value */
3010 /* %c, fallback scaling index */
3012 static const unsigned char FPGM(bci_scale_glyph_b
) [] =
3020 SZPS
, /* set zp0, zp1, and zp2 to normal zone 1 */
3029 SZP2
, /* set zp2 to normal zone 1 */
3045 * bci_scale_composite_glyph
3047 * The same as `bci_scale_glyph'.
3048 * It also decrements the composite component counter.
3050 * CVT: cvtl_is_subglyph
3055 * uses: bci_decrement_component_counter
3059 static const unsigned char FPGM(bci_scale_composite_glyph_a
) [] =
3063 bci_scale_composite_glyph
,
3066 /* all our measurements are taken along the y axis */
3070 bci_decrement_component_counter
,
3073 /* only do something if we are not a subglyph */
3080 /* use fallback scaling value */
3086 /* %c, fallback scaling index */
3088 static const unsigned char FPGM(bci_scale_composite_glyph_b
) [] =
3096 SZPS
, /* set zp0, zp1, and zp2 to normal zone 1 */
3105 SZP2
, /* set zp2 to normal zone 1 */
3123 * Shift a contour by a given amount.
3125 * It expects that rp1 (pointed to by zp0) is set up properly; zp2 must
3126 * point to the normal zone 1.
3133 static const unsigned char FPGM(bci_shift_contour
) [] =
3141 SHC_rp1
, /* shift `contour' by (rp1_pos - rp1_orig_pos) */
3153 * bci_shift_subglyph
3155 * Shift a subglyph. To be more specific, it corrects the already applied
3156 * subglyph offset (if any) from the `glyf' table which needs to be scaled
3159 * If this function is called, a point `x' in the subglyph has been scaled
3160 * already (during the hinting of the subglyph itself), and `offset' has
3161 * been applied also:
3163 * x -> x * scale + offset (1)
3165 * However, the offset should be applied first, then the scaling:
3167 * x -> (x + offset) * scale (2)
3169 * Our job is now to transform (1) to (2); a simple calculation shows that
3170 * we have to shift all points of the subglyph by
3172 * offset * scale - offset = offset * (scale - 1)
3174 * Note that `sal_scale' is equal to the above `scale - 1'.
3176 * in: offset (in FUnits)
3180 * CVT: cvtl_funits_to_pixels
3188 static const unsigned char FPGM(bci_shift_subglyph_a
) [] =
3195 /* all our measurements are taken along the y axis */
3198 /* use fallback scaling value */
3204 /* %c, fallback scaling index */
3206 static const unsigned char FPGM(bci_shift_subglyph_b
) [] =
3213 cvtl_funits_to_pixels
,
3214 RCVT
, /* scaling factor FUnits -> pixels */
3218 /* the autohinter always rounds offsets */
3221 CALL
, /* offset = round(offset) */
3227 DIV_BY_1024
, /* delta = offset * (scale - 1) */
3229 /* and round again */
3232 CALL
, /* offset = round(offset) */
3236 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
3238 /* we create twilight point 0 as a reference point, */
3239 /* setting the original position to zero (using `cvtl_temp') */
3247 MIAP_noround
, /* rp0 and rp1 now point to twilight point 0 */
3249 SWAP
, /* s: first_contour num_contours 0 delta */
3250 SHPIX
, /* rp1_pos - rp1_orig_pos = delta */
3255 SZP2
, /* set zp2 to normal zone 1 */
3257 /* clean up stack */
3262 /* used if we have delta exceptions */
3264 static const unsigned char FPGM(bci_shift_subglyph_c
) [] =
3273 static const unsigned char FPGM(bci_shift_subglyph_d
) [] =
3282 * bci_ip_outer_align_point
3284 * Auxiliary function for `bci_action_ip_before' and
3285 * `bci_action_ip_after'.
3287 * It expects rp0 to contain the edge for alignment, zp0 set to twilight
3288 * zone, and both zp1 and zp2 set to normal zone.
3292 * sal: sal_i (edge_orig_pos)
3296 static const unsigned char FPGM(bci_ip_outer_align_point
) [] =
3300 bci_ip_outer_align_point
,
3304 ALIGNRP
, /* align `point' with `edge' */
3307 DO_SCALE
, /* point_orig_pos = point_orig_pos * scale */
3312 SUB
, /* s: point (point_orig_pos - edge_orig_pos) */
3321 * bci_ip_on_align_points
3323 * Auxiliary function for `bci_action_ip_on'.
3325 * in: edge (in twilight zone)
3333 static const unsigned char FPGM(bci_ip_on_align_points
) [] =
3337 bci_ip_on_align_points
,
3340 MDAP_noround
, /* set rp0 and rp1 to `edge' */
3351 * bci_ip_between_align_point
3353 * Auxiliary function for `bci_ip_between_align_points'.
3355 * It expects rp0 to contain the edge for alignment, zp0 set to twilight
3356 * zone, and both zp1 and zp2 set to normal zone.
3360 * sal: sal_i (edge_orig_pos)
3361 * sal_j (stretch_factor)
3365 static const unsigned char FPGM(bci_ip_between_align_point
) [] =
3369 bci_ip_between_align_point
,
3373 ALIGNRP
, /* align `point' with `edge' */
3376 DO_SCALE
, /* point_orig_pos = point_orig_pos * scale */
3381 SUB
, /* s: point (point_orig_pos - edge_orig_pos) */
3385 MUL
, /* s: point delta */
3394 * bci_ip_between_align_points
3396 * Auxiliary function for `bci_action_ip_between'.
3398 * in: after_edge (in twilight zone)
3399 * before_edge (in twilight zone)
3406 * sal: sal_i (before_orig_pos)
3407 * sal_j (stretch_factor)
3409 * uses: bci_ip_between_align_point
3412 static const unsigned char FPGM(bci_ip_between_align_points
) [] =
3416 bci_ip_between_align_points
,
3422 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
3424 DUP
, /* s: ... before after before before */
3425 MDAP_noround
, /* set rp0 and rp1 to `before' */
3427 GC_orig
, /* s: ... before after before before_orig_pos */
3431 WS
, /* sal_i = before_orig_pos */
3434 CINDEX
, /* s: ... before after before after */
3435 MD_cur
, /* a = after_pos - before_pos */
3438 MD_orig_ZP2_0
, /* b = after_orig_pos - before_orig_pos */
3444 POP
, /* avoid division by zero */
3450 WS
, /* sal_j = stretch_factor */
3453 bci_ip_between_align_point
,
3456 SZP2
, /* set zp2 to normal zone 1 */
3457 SZP1
, /* set zp1 to normal zone 1 */
3466 * bci_action_ip_before
3468 * Handle `ip_before' data to align points located before the first edge.
3470 * in: first_edge (in twilight zone)
3477 * sal: sal_i (first_edge_orig_pos)
3479 * uses: bci_ip_outer_align_point
3482 static const unsigned char FPGM(bci_action_ip_before
) [] =
3486 bci_action_ip_before
,
3491 SZP2
, /* set zp2 to twilight zone 0 */
3498 WS
, /* sal_i = first_edge_orig_pos */
3504 SZP2
, /* set zp2 to normal zone 1 */
3505 SZP1
, /* set zp1 to normal zone 1 */
3506 SZP0
, /* set zp0 to twilight zone 0 */
3508 MDAP_noround
, /* set rp0 and rp1 to `first_edge' */
3511 bci_ip_outer_align_point
,
3520 * bci_action_ip_after
3522 * Handle `ip_after' data to align points located after the last edge.
3524 * in: last_edge (in twilight zone)
3531 * sal: sal_i (last_edge_orig_pos)
3533 * uses: bci_ip_outer_align_point
3536 static const unsigned char FPGM(bci_action_ip_after
) [] =
3540 bci_action_ip_after
,
3545 SZP2
, /* set zp2 to twilight zone 0 */
3552 WS
, /* sal_i = last_edge_orig_pos */
3558 SZP2
, /* set zp2 to normal zone 1 */
3559 SZP1
, /* set zp1 to normal zone 1 */
3560 SZP0
, /* set zp0 to twilight zone 0 */
3562 MDAP_noround
, /* set rp0 and rp1 to `last_edge' */
3565 bci_ip_outer_align_point
,
3576 * Handle `ip_on' data to align points located on an edge coordinate (but
3577 * not part of an edge).
3579 * in: loop_counter (M)
3580 * edge_1 (in twilight zone)
3581 * loop_counter (N_1)
3586 * edge_2 (in twilight zone)
3587 * loop_counter (N_2)
3593 * edge_M (in twilight zone)
3594 * loop_counter (N_M)
3600 * uses: bci_ip_on_align_points
3603 static const unsigned char FPGM(bci_action_ip_on
) [] =
3613 SZP1
, /* set zp1 to normal zone 1 */
3614 SZP0
, /* set zp0 to twilight zone 0 */
3617 bci_ip_on_align_points
,
3626 * bci_action_ip_between
3628 * Handle `ip_between' data to align points located between two edges.
3630 * in: loop_counter (M)
3631 * before_edge_1 (in twilight zone)
3632 * after_edge_1 (in twilight zone)
3633 * loop_counter (N_1)
3638 * before_edge_2 (in twilight zone)
3639 * after_edge_2 (in twilight zone)
3640 * loop_counter (N_2)
3646 * before_edge_M (in twilight zone)
3647 * after_edge_M (in twilight zone)
3648 * loop_counter (N_M)
3654 * uses: bci_ip_between_align_points
3657 static const unsigned char FPGM(bci_action_ip_between
) [] =
3661 bci_action_ip_between
,
3665 bci_ip_between_align_points
,
3676 * Common code for bci_action_adjust routines.
3678 * in: top_to_bottom_hinting
3684 * out: edge (adjusted)
3686 * sal: sal_top_to_bottom_hinting
3689 * uses: func[sal_stem_width_function]
3692 static const unsigned char FPGM(bci_adjust_common
) [] =
3701 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
3703 sal_top_to_bottom_hinting
,
3709 CINDEX
, /* s: [...] edge2 edge is_round is_serif edge2 */
3712 CINDEX
, /* s: [...] edge2 edge is_round is_serif edge2 edge */
3713 MD_orig_ZP2_0
, /* s: [...] edge2 edge is_round is_serif org_len */
3716 sal_base_delta
, /* no base_delta needed here */
3721 sal_stem_width_function
,
3724 NEG
, /* s: [...] edge2 edge -cur_len */
3726 ROLL
, /* s: [...] edge -cur_len edge2 */
3727 MDAP_noround
, /* set rp0 and rp1 to `edge2' */
3730 DUP
, /* s: [...] -cur_len edge edge edge */
3731 ALIGNRP
, /* align `edge' with `edge2' */
3733 SHPIX
, /* shift `edge' by -cur_len */
3743 * Handle the ADJUST + BOUND actions to align an edge of a stem if the
3744 * other edge of the stem has already been moved, then moving it again if
3745 * necessary to stay bound.
3747 * in: top_to_bottom_hinting
3750 * edge_point (in twilight zone)
3751 * edge2_point (in twilight zone)
3752 * edge[-1] (in twilight zone)
3753 * ... stuff for bci_align_segments (edge) ...
3755 * sal: sal_top_to_bottom_hinting
3757 * uses: bci_adjust_common
3758 * bci_align_segments
3761 static const unsigned char FPGM(bci_adjust_bound
) [] =
3772 SWAP
, /* s: edge edge[-1] */
3774 MDAP_noround
, /* set rp0 and rp1 to `edge[-1]' */
3779 GC_cur
, /* s: edge edge[-1]_pos edge_pos */
3781 sal_top_to_bottom_hinting
,
3784 LT
, /* edge_pos > edge[-1]_pos */
3786 GT
, /* edge_pos < edge[-1]_pos */
3790 ALIGNRP
, /* align `edge' to `edge[-1]' */
3793 MDAP_noround
, /* set rp0 and rp1 to `edge' */
3798 SZP1
, /* set zp1 to normal zone 1 */
3807 * bci_action_adjust_bound
3808 * bci_action_adjust_bound_serif
3809 * bci_action_adjust_bound_round
3810 * bci_action_adjust_bound_round_serif
3811 * bci_action_adjust_down_bound
3812 * bci_action_adjust_down_bound_serif
3813 * bci_action_adjust_down_bound_round
3814 * bci_action_adjust_down_bound_round_serif
3816 * Higher-level routines for calling `bci_adjust_bound'.
3819 static const unsigned char FPGM(bci_action_adjust_bound
) [] =
3823 bci_action_adjust_bound
,
3837 static const unsigned char FPGM(bci_action_adjust_bound_serif
) [] =
3841 bci_action_adjust_bound_serif
,
3855 static const unsigned char FPGM(bci_action_adjust_bound_round
) [] =
3859 bci_action_adjust_bound_round
,
3873 static const unsigned char FPGM(bci_action_adjust_bound_round_serif
) [] =
3877 bci_action_adjust_bound_round_serif
,
3891 static const unsigned char FPGM(bci_action_adjust_down_bound
) [] =
3895 bci_action_adjust_down_bound
,
3909 static const unsigned char FPGM(bci_action_adjust_down_bound_serif
) [] =
3913 bci_action_adjust_down_bound_serif
,
3927 static const unsigned char FPGM(bci_action_adjust_down_bound_round
) [] =
3931 bci_action_adjust_down_bound_round
,
3945 static const unsigned char FPGM(bci_action_adjust_down_bound_round_serif
) [] =
3949 bci_action_adjust_down_bound_round_serif
,
3967 * Handle the ADJUST action to align an edge of a stem if the other edge
3968 * of the stem has already been moved.
3970 * in: edge2_is_serif
3972 * edge_point (in twilight zone)
3973 * edge2_point (in twilight zone)
3974 * ... stuff for bci_align_segments (edge) ...
3976 * uses: bci_adjust_common
3977 * bci_align_segments
3980 static const unsigned char FPGM(bci_adjust
) [] =
3992 MDAP_noround
, /* set rp0 and rp1 to `edge' */
3997 SZP1
, /* set zp1 to normal zone 1 */
4007 * bci_action_adjust_serif
4008 * bci_action_adjust_round
4009 * bci_action_adjust_round_serif
4011 * Higher-level routines for calling `bci_adjust'.
4014 static const unsigned char FPGM(bci_action_adjust
) [] =
4031 static const unsigned char FPGM(bci_action_adjust_serif
) [] =
4035 bci_action_adjust_serif
,
4048 static const unsigned char FPGM(bci_action_adjust_round
) [] =
4052 bci_action_adjust_round
,
4065 static const unsigned char FPGM(bci_action_adjust_round_serif
) [] =
4069 bci_action_adjust_round_serif
,
4086 * Common code for bci_action_stem routines.
4088 * in: top_to_bottom_hinting
4102 * sal_top_to_bottom_hinting
4105 * uses: func[sal_stem_width_function]
4110 #define sal_u_off sal_temp1
4112 #define sal_d_off sal_temp2
4114 #define sal_org_len sal_temp3
4116 #define sal_edge2 sal_temp3
4118 static const unsigned char FPGM(bci_stem_common
) [] =
4127 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
4130 sal_top_to_bottom_hinting
,
4140 DUP
, /* s: [...] edge2 edge is_round is_serif edge2 edge edge */
4141 MDAP_noround
, /* set rp0 and rp1 to `edge_point' (for ALIGNRP below) */
4143 MD_orig_ZP2_0
, /* s: [...] edge2 edge is_round is_serif org_len */
4151 sal_base_delta
, /* no base_delta needed here */
4156 sal_stem_width_function
,
4158 CALL
, /* s: [...] edge2 edge cur_len */
4163 LT
, /* cur_len < 96 */
4168 LTEQ
, /* cur_len <= 64 */
4186 SWAP
, /* s: [...] edge2 cur_len edge */
4191 DUP
, /* s: [...] edge2 cur_len edge edge anchor anchor */
4197 ADD
, /* s: [...] edge2 cur_len edge org_pos */
4202 ADD
, /* s: [...] edge2 cur_len edge org_center */
4207 CALL
, /* s: [...] edge2 cur_len edge org_center cur_pos1 */
4212 SUB
, /* s: ... cur_len edge cur_pos1 (org_center - cur_pos1) */
4219 ABS
, /* s: ... cur_len edge cur_pos1 (org_center - cur_pos1) delta1 */
4226 ABS
, /* s: [...] edge2 cur_len edge cur_pos1 delta1 delta2 */
4228 LT
, /* delta1 < delta2 */
4233 SUB
, /* cur_pos1 = cur_pos1 - u_off */
4239 ADD
, /* cur_pos1 = cur_pos1 + d_off */
4240 EIF
, /* s: [...] edge2 cur_len edge cur_pos1 */
4246 SUB
, /* arg = cur_pos1 - cur_len/2 */
4248 SWAP
, /* s: [...] edge2 cur_len arg edge */
4254 SWAP
, /* s: [...] edge2 cur_len edge edge arg edge */
4257 SHPIX
, /* edge = cur_pos1 - cur_len/2 */
4260 SWAP
, /* s: [...] edge2 cur_len edge */
4264 GC_cur
, /* s: [...] edge2 cur_len edge anchor_pos */
4272 ADD
, /* s: [...] edge2 cur_len edge org_pos */
4279 ADD
, /* s: [...] edge2 cur_len edge org_pos org_center */
4285 CALL
, /* cur_pos1 = ROUND(org_pos) */
4297 SUB
, /* s: [...] edge2 cur_len edge org_center cur_pos1 cur_pos2 */
4306 SUB
, /* s: ... cur_len edge cur_pos1 cur_pos2 (cur_len/2 - org_center) */
4313 ABS
, /* delta1 = |cur_pos1 + cur_len / 2 - org_center| */
4319 ABS
, /* s: ... edge2 cur_len edge cur_pos1 cur_pos2 delta1 delta2 */
4320 LT
, /* delta1 < delta2 */
4322 POP
, /* arg = cur_pos1 */
4326 POP
, /* arg = cur_pos2 */
4327 EIF
, /* s: [...] edge2 cur_len edge arg */
4334 SWAP
, /* s: [...] edge2 cur_len edge edge arg edge */
4337 SHPIX
, /* edge = arg */
4338 EIF
, /* s: [...] edge2 cur_len edge */
4348 * Handle the STEM action to align two edges of a stem, then moving one
4349 * edge again if necessary to stay bound.
4351 * The code after computing `cur_len' to shift `edge' and `edge2'
4352 * is equivalent to the snippet below (part of `ta_latin_hint_edges'):
4355 * if cur_len < = 64:
4362 * org_pos = anchor + (edge_orig - anchor_orig)
4363 * org_center = org_pos + org_len / 2
4365 * cur_pos1 = ROUND(org_center)
4366 * delta1 = |org_center - (cur_pos1 - u_off)|
4367 * delta2 = |org_center - (cur_pos1 + d_off)|
4368 * if (delta1 < delta2):
4369 * cur_pos1 = cur_pos1 - u_off
4371 * cur_pos1 = cur_pos1 + d_off
4373 * edge = cur_pos1 - cur_len / 2
4376 * org_pos = anchor + (edge_orig - anchor_orig)
4377 * org_center = org_pos + org_len / 2
4379 * cur_pos1 = ROUND(org_pos)
4380 * delta1 = |cur_pos1 + cur_len / 2 - org_center|
4381 * cur_pos2 = ROUND(org_pos + org_len) - cur_len
4382 * delta2 = |cur_pos2 + cur_len / 2 - org_center|
4384 * if (delta1 < delta2):
4389 * edge2 = edge + cur_len
4391 * in: top_to_bottom_hinting
4394 * edge_point (in twilight zone)
4395 * edge2_point (in twilight zone)
4396 * edge[-1] (in twilight zone)
4397 * ... stuff for bci_align_segments (edge) ...
4398 * ... stuff for bci_align_segments (edge2)...
4404 * sal_top_to_bottom_hinting
4406 * uses: bci_stem_common
4407 * bci_align_segments
4410 static const unsigned char FPGM(bci_stem_bound
) [] =
4421 ROLL
, /* s: edge[-1] cur_len edge edge2 */
4424 ALIGNRP
, /* align `edge2' with rp0 (still `edge') */
4428 WS
, /* s: edge[-1] cur_len edge edge2 */
4430 SHPIX
, /* edge2 = edge + cur_len */
4432 SWAP
, /* s: edge edge[-1] */
4434 MDAP_noround
, /* set rp0 and rp1 to `edge[-1]' */
4439 GC_cur
, /* s: edge edge[-1]_pos edge_pos */
4441 sal_top_to_bottom_hinting
,
4444 LT
, /* edge_pos > edge[-1]_pos */
4446 GT
, /* edge_pos < edge[-1]_pos */
4450 ALIGNRP
, /* align `edge' to `edge[-1]' */
4453 MDAP_noround
, /* set rp0 and rp1 to `edge' */
4458 SZP1
, /* set zp1 to normal zone 1 */
4464 MDAP_noround
, /* set rp0 and rp1 to `edge2' */
4476 * bci_action_stem_bound
4477 * bci_action_stem_bound_serif
4478 * bci_action_stem_bound_round
4479 * bci_action_stem_bound_round_serif
4480 * bci_action_stem_down_bound
4481 * bci_action_stem_down_bound_serif
4482 * bci_action_stem_down_bound_round
4483 * bci_action_stem_down_bound_round_serif
4485 * Higher-level routines for calling `bci_stem_bound'.
4488 static const unsigned char FPGM(bci_action_stem_bound
) [] =
4492 bci_action_stem_bound
,
4506 static const unsigned char FPGM(bci_action_stem_bound_serif
) [] =
4510 bci_action_stem_bound_serif
,
4524 static const unsigned char FPGM(bci_action_stem_bound_round
) [] =
4528 bci_action_stem_bound_round
,
4542 static const unsigned char FPGM(bci_action_stem_bound_round_serif
) [] =
4546 bci_action_stem_bound_round_serif
,
4560 static const unsigned char FPGM(bci_action_stem_down_bound
) [] =
4564 bci_action_stem_down_bound
,
4578 static const unsigned char FPGM(bci_action_stem_down_bound_serif
) [] =
4582 bci_action_stem_down_bound_serif
,
4596 static const unsigned char FPGM(bci_action_stem_down_bound_round
) [] =
4600 bci_action_stem_down_bound_round
,
4614 static const unsigned char FPGM(bci_action_stem_down_bound_round_serif
) [] =
4618 bci_action_stem_down_bound_round_serif
,
4636 * Handle the STEM action to align two edges of a stem.
4638 * See `bci_stem_bound' for more details.
4640 * in: edge2_is_serif
4642 * edge_point (in twilight zone)
4643 * edge2_point (in twilight zone)
4644 * ... stuff for bci_align_segments (edge) ...
4645 * ... stuff for bci_align_segments (edge2)...
4652 * uses: bci_stem_common
4653 * bci_align_segments
4656 static const unsigned char FPGM(bci_stem
) [] =
4669 SWAP
, /* s: cur_len edge2 */
4672 ALIGNRP
, /* align `edge2' with rp0 (still `edge') */
4676 WS
, /* s: cur_len edge2 */
4678 SHPIX
, /* edge2 = edge + cur_len */
4683 SZP1
, /* set zp1 to normal zone 1 */
4689 MDAP_noround
, /* set rp0 and rp1 to `edge2' */
4701 * bci_action_stem_serif
4702 * bci_action_stem_round
4703 * bci_action_stem_round_serif
4705 * Higher-level routines for calling `bci_stem'.
4708 static const unsigned char FPGM(bci_action_stem
) [] =
4725 static const unsigned char FPGM(bci_action_stem_serif
) [] =
4729 bci_action_stem_serif
,
4742 static const unsigned char FPGM(bci_action_stem_round
) [] =
4746 bci_action_stem_round
,
4759 static const unsigned char FPGM(bci_action_stem_round_serif
) [] =
4763 bci_action_stem_round_serif
,
4780 * Handle the LINK action to link an edge to another one.
4784 * base_point (in twilight zone)
4785 * stem_point (in twilight zone)
4786 * ... stuff for bci_align_segments (base) ...
4788 * sal: sal_base_delta
4790 * uses: func[sal_stem_width_function]
4791 * bci_align_segments
4794 static const unsigned char FPGM(bci_link
) [] =
4803 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
4811 DUP
, /* s: stem is_round is_serif stem base base */
4818 SUB
, /* base_delta = base_point_pos - base_point_orig_pos */
4822 WS
, /* sal_base_delta = base_delta */
4824 MDAP_noround
, /* set rp0 and rp1 to `base_point' (for ALIGNRP below) */
4826 MD_orig_ZP2_0
, /* s: stem is_round is_serif dist_orig */
4829 sal_stem_width_function
,
4831 CALL
, /* s: stem new_dist */
4835 ALIGNRP
, /* align `stem_point' with `base_point' */
4837 MDAP_noround
, /* set rp0 and rp1 to `stem_point' */
4839 SHPIX
, /* stem_point = base_point + new_dist */
4844 SZP1
, /* set zp1 to normal zone 1 */
4854 * bci_action_link_serif
4855 * bci_action_link_round
4856 * bci_action_link_round_serif
4858 * Higher-level routines for calling `bci_link'.
4861 static const unsigned char FPGM(bci_action_link
) [] =
4878 static const unsigned char FPGM(bci_action_link_serif
) [] =
4882 bci_action_link_serif
,
4895 static const unsigned char FPGM(bci_action_link_round
) [] =
4899 bci_action_link_round
,
4912 static const unsigned char FPGM(bci_action_link_round_serif
) [] =
4916 bci_action_link_round_serif
,
4933 * Handle the ANCHOR action to align two edges
4934 * and to set the edge anchor.
4936 * The code after computing `cur_len' to shift `edge' and `edge2'
4937 * is equivalent to the snippet below (part of `ta_latin_hint_edges'):
4940 * if cur_len < = 64:
4947 * org_center = edge_orig + org_len / 2
4948 * cur_pos1 = ROUND(org_center)
4950 * error1 = |org_center - (cur_pos1 - u_off)|
4951 * error2 = |org_center - (cur_pos1 + d_off)|
4952 * if (error1 < error2):
4953 * cur_pos1 = cur_pos1 - u_off
4955 * cur_pos1 = cur_pos1 + d_off
4957 * edge = cur_pos1 - cur_len / 2
4958 * edge2 = edge + cur_len
4961 * edge = ROUND(edge_orig)
4963 * in: edge2_is_serif
4965 * edge_point (in twilight zone)
4966 * edge2_point (in twilight zone)
4967 * ... stuff for bci_align_segments (edge) ...
4975 * uses: func[sal_stem_width_function]
4977 * bci_align_segments
4981 #define sal_u_off sal_temp1
4983 #define sal_d_off sal_temp2
4985 #define sal_org_len sal_temp3
4987 static const unsigned char FPGM(bci_anchor
) [] =
4994 /* store anchor point number in `sal_anchor' */
4999 WS
, /* sal_anchor = edge_point */
5003 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
5011 DUP
, /* s: edge2 edge is_round is_serif edge2 edge edge */
5012 MDAP_noround
, /* set rp0 and rp1 to `edge_point' (for ALIGNRP below) */
5014 MD_orig_ZP2_0
, /* s: edge2 edge is_round is_serif org_len */
5022 sal_base_delta
, /* no base_delta needed here */
5027 sal_stem_width_function
,
5029 CALL
, /* s: edge2 edge cur_len */
5034 LT
, /* cur_len < 96 */
5039 LTEQ
, /* cur_len <= 64 */
5057 SWAP
, /* s: edge2 cur_len edge */
5058 DUP
, /* s: edge2 cur_len edge edge */
5065 ADD
, /* s: edge2 cur_len edge org_center */
5070 CALL
, /* s: edge2 cur_len edge org_center cur_pos1 */
5075 SUB
, /* s: edge2 cur_len edge cur_pos1 (org_center - cur_pos1) */
5082 ABS
, /* s: edge2 cur_len edge cur_pos1 (org_center - cur_pos1) error1 */
5089 ABS
, /* s: edge2 cur_len edge cur_pos1 error1 error2 */
5091 LT
, /* error1 < error2 */
5096 SUB
, /* cur_pos1 = cur_pos1 - u_off */
5102 ADD
, /* cur_pos1 = cur_pos1 + d_off */
5103 EIF
, /* s: edge2 cur_len edge cur_pos1 */
5109 SUB
, /* s: edge2 cur_len edge (cur_pos1 - cur_len/2) */
5113 CINDEX
, /* s: edge2 cur_len edge (cur_pos1 - cur_len/2) edge */
5116 SHPIX
, /* edge = cur_pos1 - cur_len/2 */
5118 SWAP
, /* s: cur_len edge2 */
5120 ALIGNRP
, /* align `edge2' with rp0 (still `edge') */
5122 SHPIX
, /* edge2 = edge1 + cur_len */
5125 POP
, /* s: edge2 edge */
5133 CALL
, /* s: edge2 edge edge_pos round(edge_orig_pos) */
5136 SHPIX
, /* edge = round(edge_orig) */
5138 /* clean up stack */
5145 SZP1
, /* set zp1 to normal zone 1 */
5155 * bci_action_anchor_serif
5156 * bci_action_anchor_round
5157 * bci_action_anchor_round_serif
5159 * Higher-level routines for calling `bci_anchor'.
5162 static const unsigned char FPGM(bci_action_anchor
) [] =
5179 static const unsigned char FPGM(bci_action_anchor_serif
) [] =
5183 bci_action_anchor_serif
,
5196 static const unsigned char FPGM(bci_action_anchor_round
) [] =
5200 bci_action_anchor_round
,
5213 static const unsigned char FPGM(bci_action_anchor_round_serif
) [] =
5217 bci_action_anchor_round_serif
,
5232 * bci_action_blue_anchor
5234 * Handle the BLUE_ANCHOR action to align an edge with a blue zone
5235 * and to set the edge anchor.
5237 * in: anchor_point (in twilight zone)
5239 * edge_point (in twilight zone)
5240 * ... stuff for bci_align_segments (edge) ...
5244 * uses: bci_action_blue
5247 static const unsigned char FPGM(bci_action_blue_anchor
) [] =
5251 bci_action_blue_anchor
,
5254 /* store anchor point number in `sal_anchor' */
5272 * Handle the BLUE action to align an edge with a blue zone.
5275 * edge_point (in twilight zone)
5276 * ... stuff for bci_align_segments (edge) ...
5278 * uses: bci_align_segments
5281 static const unsigned char FPGM(bci_action_blue
) [] =
5290 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
5292 /* move `edge_point' to `blue_cvt_idx' position; */
5293 /* note that we can't use MIAP since this would modify */
5294 /* the twilight point's original coordinates also */
5298 MDAP_noround
, /* set rp0 and rp1 to `edge' */
5300 GC_cur
, /* s: new_pos edge edge_pos */
5303 SUB
, /* s: edge (new_pos - edge_pos) */
5309 SZP1
, /* set zp1 to normal zone 1 */
5320 * Common code for bci_action_serif routines.
5322 * in: top_to_bottom_hinting
5326 * sal: sal_top_to_bottom_hinting
5330 static const unsigned char FPGM(bci_serif_common
) [] =
5339 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
5342 sal_top_to_bottom_hinting
,
5351 MINDEX
, /* s: [...] serif serif serif serif base */
5353 MDAP_noround
, /* set rp0 and rp1 to `base_point' */
5356 ALIGNRP
, /* align `serif_point' with `base_point' */
5357 SHPIX
, /* serif = base + (serif_orig_pos - base_orig_pos) */
5367 * Move an edge if necessary to stay within a lower bound.
5372 * sal: sal_top_to_bottom_hinting
5374 * uses: bci_align_segments
5377 static const unsigned char FPGM(bci_lower_bound
) [] =
5384 SWAP
, /* s: edge bound */
5386 MDAP_noround
, /* set rp0 and rp1 to `bound' */
5391 GC_cur
, /* s: edge bound_pos edge_pos */
5393 sal_top_to_bottom_hinting
,
5396 LT
, /* edge_pos > bound_pos */
5398 GT
, /* edge_pos < bound_pos */
5402 ALIGNRP
, /* align `edge' to `bound' */
5405 MDAP_noround
, /* set rp0 and rp1 to `edge_point' */
5410 SZP1
, /* set zp1 to normal zone 1 */
5421 * Move an edge if necessary to stay within an upper bound.
5426 * sal: sal_top_to_bottom_hinting
5428 * uses: bci_align_segments
5431 static const unsigned char FPGM(bci_upper_bound
) [] =
5438 SWAP
, /* s: edge bound */
5440 MDAP_noround
, /* set rp0 and rp1 to `bound' */
5445 GC_cur
, /* s: edge bound_pos edge_pos */
5447 sal_top_to_bottom_hinting
,
5450 GT
, /* edge_pos < bound_pos */
5452 LT
, /* edge_pos > bound_pos */
5456 ALIGNRP
, /* align `edge' to `bound' */
5459 MDAP_noround
, /* set rp0 and rp1 to `edge_point' */
5464 SZP1
, /* set zp1 to normal zone 1 */
5473 * bci_upper_lower_bound
5475 * Move an edge if necessary to stay within a lower and lower bound.
5481 * sal: sal_top_to_bottom_hinting
5483 * uses: bci_align_segments
5486 static const unsigned char FPGM(bci_upper_lower_bound
) [] =
5490 bci_upper_lower_bound
,
5493 SWAP
, /* s: upper serif lower */
5495 MDAP_noround
, /* set rp0 and rp1 to `lower' */
5500 GC_cur
, /* s: upper serif lower_pos serif_pos */
5502 sal_top_to_bottom_hinting
,
5505 LT
, /* serif_pos > lower_pos */
5507 GT
, /* serif_pos < lower_pos */
5511 ALIGNRP
, /* align `serif' to `lower' */
5514 SWAP
, /* s: serif upper */
5516 MDAP_noround
, /* set rp0 and rp1 to `upper' */
5521 GC_cur
, /* s: serif upper_pos serif_pos */
5523 sal_top_to_bottom_hinting
,
5526 GT
, /* serif_pos < upper_pos */
5528 LT
, /* serif_pos > upper_pos */
5532 ALIGNRP
, /* align `serif' to `upper' */
5535 MDAP_noround
, /* set rp0 and rp1 to `serif_point' */
5540 SZP1
, /* set zp1 to normal zone 1 */
5551 * Handle the SERIF action to align a serif with its base.
5553 * in: serif_point (in twilight zone)
5554 * base_point (in twilight zone)
5555 * ... stuff for bci_align_segments (serif) ...
5557 * uses: bci_serif_common
5558 * bci_align_segments
5561 static const unsigned char FPGM(bci_action_serif
) [] =
5573 MDAP_noround
, /* set rp0 and rp1 to `serif_point' */
5578 SZP1
, /* set zp1 to normal zone 1 */
5587 * bci_action_serif_lower_bound
5589 * Handle the SERIF action to align a serif with its base, then moving it
5590 * again if necessary to stay within a lower bound.
5592 * in: serif_point (in twilight zone)
5593 * base_point (in twilight zone)
5594 * edge[-1] (in twilight zone)
5595 * ... stuff for bci_align_segments (serif) ...
5597 * uses: bci_serif_common
5601 static const unsigned char FPGM(bci_action_serif_lower_bound
) [] =
5605 bci_action_serif_lower_bound
,
5623 * bci_action_serif_upper_bound
5625 * Handle the SERIF action to align a serif with its base, then moving it
5626 * again if necessary to stay within an upper bound.
5628 * in: serif_point (in twilight zone)
5629 * base_point (in twilight zone)
5630 * edge[1] (in twilight zone)
5631 * ... stuff for bci_align_segments (serif) ...
5633 * uses: bci_serif_common
5637 static const unsigned char FPGM(bci_action_serif_upper_bound
) [] =
5641 bci_action_serif_upper_bound
,
5659 * bci_action_serif_upper_lower_bound
5661 * Handle the SERIF action to align a serif with its base, then moving it
5662 * again if necessary to stay within a lower and upper bound.
5664 * in: serif_point (in twilight zone)
5665 * base_point (in twilight zone)
5666 * edge[-1] (in twilight zone)
5667 * edge[1] (in twilight zone)
5668 * ... stuff for bci_align_segments (serif) ...
5670 * uses: bci_serif_common
5671 * bci_upper_lower_bound
5674 static const unsigned char FPGM(bci_action_serif_upper_lower_bound
) [] =
5678 bci_action_serif_upper_lower_bound
,
5683 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
5691 bci_upper_lower_bound
,
5700 * bci_action_serif_down_lower_bound
5702 * Handle the SERIF action to align a serif with its base, then moving it
5703 * again if necessary to stay within a lower bound. We hint top to
5706 * in: serif_point (in twilight zone)
5707 * base_point (in twilight zone)
5708 * edge[-1] (in twilight zone)
5709 * ... stuff for bci_align_segments (serif) ...
5711 * uses: bci_serif_common
5715 static const unsigned char FPGM(bci_action_serif_down_lower_bound
) [] =
5719 bci_action_serif_down_lower_bound
,
5737 * bci_action_serif_down_upper_bound
5739 * Handle the SERIF action to align a serif with its base, then moving it
5740 * again if necessary to stay within an upper bound. We hint top to
5743 * in: serif_point (in twilight zone)
5744 * base_point (in twilight zone)
5745 * edge[1] (in twilight zone)
5746 * ... stuff for bci_align_segments (serif) ...
5748 * uses: bci_serif_common
5752 static const unsigned char FPGM(bci_action_serif_down_upper_bound
) [] =
5756 bci_action_serif_down_upper_bound
,
5774 * bci_action_serif_down_upper_lower_bound
5776 * Handle the SERIF action to align a serif with its base, then moving it
5777 * again if necessary to stay within a lower and upper bound. We hint top
5780 * in: serif_point (in twilight zone)
5781 * base_point (in twilight zone)
5782 * edge[-1] (in twilight zone)
5783 * edge[1] (in twilight zone)
5784 * ... stuff for bci_align_segments (serif) ...
5786 * uses: bci_serif_common
5787 * bci_upper_lower_bound
5790 static const unsigned char FPGM(bci_action_serif_down_upper_lower_bound
) [] =
5794 bci_action_serif_down_upper_lower_bound
,
5799 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
5807 bci_upper_lower_bound
,
5816 * bci_serif_anchor_common
5818 * Common code for bci_action_serif_anchor routines.
5820 * in: top_to_bottom_hinting
5823 * out: edge (adjusted)
5826 * sal_top_to_bottom_hinting
5831 static const unsigned char FPGM(bci_serif_anchor_common
) [] =
5835 bci_serif_anchor_common
,
5840 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
5843 sal_top_to_bottom_hinting
,
5851 WS
, /* sal_anchor = edge_point */
5861 CALL
, /* s: [...] edge edge edge_pos round(edge_orig_pos) */
5864 SHPIX
, /* edge = round(edge_orig) */
5872 * bci_action_serif_anchor
5874 * Handle the SERIF_ANCHOR action to align a serif and to set the edge
5877 * in: edge_point (in twilight zone)
5878 * ... stuff for bci_align_segments (edge) ...
5880 * uses: bci_serif_anchor_common
5881 * bci_align_segments
5884 static const unsigned char FPGM(bci_action_serif_anchor
) [] =
5888 bci_action_serif_anchor
,
5893 bci_serif_anchor_common
,
5896 MDAP_noround
, /* set rp0 and rp1 to `edge' */
5901 SZP1
, /* set zp1 to normal zone 1 */
5910 * bci_action_serif_anchor_lower_bound
5912 * Handle the SERIF_ANCHOR action to align a serif and to set the edge
5913 * anchor, then moving it again if necessary to stay within a lower
5916 * in: edge_point (in twilight zone)
5917 * edge[-1] (in twilight zone)
5918 * ... stuff for bci_align_segments (edge) ...
5920 * uses: bci_serif_anchor_common
5924 static const unsigned char FPGM(bci_action_serif_anchor_lower_bound
) [] =
5928 bci_action_serif_anchor_lower_bound
,
5933 bci_serif_anchor_common
,
5946 * bci_action_serif_anchor_upper_bound
5948 * Handle the SERIF_ANCHOR action to align a serif and to set the edge
5949 * anchor, then moving it again if necessary to stay within an upper
5952 * in: edge_point (in twilight zone)
5953 * edge[1] (in twilight zone)
5954 * ... stuff for bci_align_segments (edge) ...
5956 * uses: bci_serif_anchor_common
5960 static const unsigned char FPGM(bci_action_serif_anchor_upper_bound
) [] =
5964 bci_action_serif_anchor_upper_bound
,
5969 bci_serif_anchor_common
,
5982 * bci_action_serif_anchor_upper_lower_bound
5984 * Handle the SERIF_ANCHOR action to align a serif and to set the edge
5985 * anchor, then moving it again if necessary to stay within a lower and
5988 * in: edge_point (in twilight zone)
5989 * edge[-1] (in twilight zone)
5990 * edge[1] (in twilight zone)
5991 * ... stuff for bci_align_segments (edge) ...
5993 * uses: bci_serif_anchor_common
5994 * bci_upper_lower_bound
5997 static const unsigned char FPGM(bci_action_serif_anchor_upper_lower_bound
) [] =
6001 bci_action_serif_anchor_upper_lower_bound
,
6006 bci_serif_anchor_common
,
6010 bci_upper_lower_bound
,
6019 * bci_action_serif_anchor_down_lower_bound
6021 * Handle the SERIF_ANCHOR action to align a serif and to set the edge
6022 * anchor, then moving it again if necessary to stay within a lower
6023 * bound. We hint top to bottom.
6025 * in: edge_point (in twilight zone)
6026 * edge[-1] (in twilight zone)
6027 * ... stuff for bci_align_segments (edge) ...
6029 * uses: bci_serif_anchor_common
6033 static const unsigned char FPGM(bci_action_serif_anchor_down_lower_bound
) [] =
6037 bci_action_serif_anchor_down_lower_bound
,
6042 bci_serif_anchor_common
,
6055 * bci_action_serif_anchor_down_upper_bound
6057 * Handle the SERIF_ANCHOR action to align a serif and to set the edge
6058 * anchor, then moving it again if necessary to stay within an upper
6059 * bound. We hint top to bottom.
6061 * in: edge_point (in twilight zone)
6062 * edge[1] (in twilight zone)
6063 * ... stuff for bci_align_segments (edge) ...
6065 * uses: bci_serif_anchor_common
6069 static const unsigned char FPGM(bci_action_serif_anchor_down_upper_bound
) [] =
6073 bci_action_serif_anchor_down_upper_bound
,
6078 bci_serif_anchor_common
,
6091 * bci_action_serif_anchor_down_upper_lower_bound
6093 * Handle the SERIF_ANCHOR action to align a serif and to set the edge
6094 * anchor, then moving it again if necessary to stay within a lower and
6095 * upper bound. We hint top to bottom.
6097 * in: edge_point (in twilight zone)
6098 * edge[-1] (in twilight zone)
6099 * edge[1] (in twilight zone)
6100 * ... stuff for bci_align_segments (edge) ...
6102 * uses: bci_serif_anchor_common
6103 * bci_upper_lower_bound
6106 static const unsigned char FPGM(bci_action_serif_anchor_down_upper_lower_bound
) [] =
6110 bci_action_serif_anchor_down_upper_lower_bound
,
6115 bci_serif_anchor_common
,
6119 bci_upper_lower_bound
,
6128 * bci_serif_link1_common
6130 * Common code for bci_action_serif_link1 routines.
6132 * in: top_to_bottom_hinting
6137 * out: edge (adjusted)
6139 * sal: sal_top_to_bottom_hinting
6143 static const unsigned char FPGM(bci_serif_link1_common
) [] =
6147 bci_serif_link1_common
,
6152 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
6155 sal_top_to_bottom_hinting
,
6161 CINDEX
, /* s: [...] after edge before after */
6164 CINDEX
, /* s: [...] after edge before after before */
6168 EQ
, /* after_orig_pos == before_orig_pos */
6169 IF
, /* s: [...] after edge before */
6170 MDAP_noround
, /* set rp0 and rp1 to `before' */
6172 ALIGNRP
, /* align `edge' with `before' */
6177 /* we have to execute `a*b/c', with b/c very near to 1: */
6178 /* to avoid overflow while retaining precision, */
6179 /* we transform this to `a + a * (b-c)/c' */
6183 CINDEX
, /* s: [...] after edge before edge */
6186 CINDEX
, /* s: [...] after edge before edge before */
6187 MD_orig_ZP2_0
, /* a = edge_orig_pos - before_orig_pos */
6192 CINDEX
, /* s: [...] after edge before a a after */
6195 CINDEX
, /* s: [...] after edge before a a after before */
6196 MD_orig_ZP2_0
, /* c = after_orig_pos - before_orig_pos */
6200 CINDEX
, /* s: [...] after edge before a a c after */
6203 CINDEX
, /* s: [...] after edge before a a c after before */
6204 MD_cur
, /* b = after_pos - before_pos */
6208 CINDEX
, /* s: [...] after edge before a a c b c */
6217 MUL
, /* (b-c) in 16.16 format */
6222 DIV
, /* s: [...] after edge before a a (b-c)/c */
6224 POP
, /* avoid division by zero */
6227 MUL
, /* a * (b-c)/c * 2^10 */
6228 DIV_BY_1024
, /* a * (b-c)/c */
6232 MDAP_noround
, /* set rp0 and rp1 to `before' */
6233 SWAP
, /* s: [...] after a*b/c edge */
6236 ALIGNRP
, /* align `edge' with `before' */
6238 SHPIX
, /* shift `edge' by `a*b/c' */
6240 SWAP
, /* s: [...] edge after */
6250 * bci_action_serif_link1
6252 * Handle the SERIF_LINK1 action to align a serif, depending on edges
6255 * in: before_point (in twilight zone)
6256 * edge_point (in twilight zone)
6257 * after_point (in twilight zone)
6258 * ... stuff for bci_align_segments (edge) ...
6260 * uses: bci_serif_link1_common
6261 * bci_align_segments
6264 static const unsigned char FPGM(bci_action_serif_link1
) [] =
6268 bci_action_serif_link1
,
6273 bci_serif_link1_common
,
6276 MDAP_noround
, /* set rp0 and rp1 to `edge' */
6281 SZP1
, /* set zp1 to normal zone 1 */
6290 * bci_action_serif_link1_lower_bound
6292 * Handle the SERIF_LINK1 action to align a serif, depending on edges
6293 * before and after. Additionally, move the serif again if necessary to
6294 * stay within a lower bound.
6296 * in: before_point (in twilight zone)
6297 * edge_point (in twilight zone)
6298 * after_point (in twilight zone)
6299 * edge[-1] (in twilight zone)
6300 * ... stuff for bci_align_segments (edge) ...
6302 * uses: bci_serif_link1_common
6306 static const unsigned char FPGM(bci_action_serif_link1_lower_bound
) [] =
6310 bci_action_serif_link1_lower_bound
,
6315 bci_serif_link1_common
,
6328 * bci_action_serif_link1_upper_bound
6330 * Handle the SERIF_LINK1 action to align a serif, depending on edges
6331 * before and after. Additionally, move the serif again if necessary to
6332 * stay within an upper bound.
6334 * in: before_point (in twilight zone)
6335 * edge_point (in twilight zone)
6336 * after_point (in twilight zone)
6337 * edge[1] (in twilight zone)
6338 * ... stuff for bci_align_segments (edge) ...
6340 * uses: bci_serif_link1_common
6344 static const unsigned char FPGM(bci_action_serif_link1_upper_bound
) [] =
6348 bci_action_serif_link1_upper_bound
,
6353 bci_serif_link1_common
,
6366 * bci_action_serif_link1_upper_lower_bound
6368 * Handle the SERIF_LINK1 action to align a serif, depending on edges
6369 * before and after. Additionally, move the serif again if necessary to
6370 * stay within a lower and upper bound.
6372 * in: before_point (in twilight zone)
6373 * edge_point (in twilight zone)
6374 * after_point (in twilight zone)
6375 * edge[-1] (in twilight zone)
6376 * edge[1] (in twilight zone)
6377 * ... stuff for bci_align_segments (edge) ...
6379 * uses: bci_serif_link1_common
6380 * bci_upper_lower_bound
6383 static const unsigned char FPGM(bci_action_serif_link1_upper_lower_bound
) [] =
6387 bci_action_serif_link1_upper_lower_bound
,
6392 bci_serif_link1_common
,
6396 bci_upper_lower_bound
,
6405 * bci_action_serif_link1_down_lower_bound
6407 * Handle the SERIF_LINK1 action to align a serif, depending on edges
6408 * before and after. Additionally, move the serif again if necessary to
6409 * stay within a lower bound. We hint top to bottom.
6411 * in: before_point (in twilight zone)
6412 * edge_point (in twilight zone)
6413 * after_point (in twilight zone)
6414 * edge[-1] (in twilight zone)
6415 * ... stuff for bci_align_segments (edge) ...
6417 * uses: bci_serif_link1_common
6421 static const unsigned char FPGM(bci_action_serif_link1_down_lower_bound
) [] =
6425 bci_action_serif_link1_down_lower_bound
,
6430 bci_serif_link1_common
,
6443 * bci_action_serif_link1_down_upper_bound
6445 * Handle the SERIF_LINK1 action to align a serif, depending on edges
6446 * before and after. Additionally, move the serif again if necessary to
6447 * stay within an upper bound. We hint top to bottom.
6449 * in: before_point (in twilight zone)
6450 * edge_point (in twilight zone)
6451 * after_point (in twilight zone)
6452 * edge[1] (in twilight zone)
6453 * ... stuff for bci_align_segments (edge) ...
6455 * uses: bci_serif_link1_common
6459 static const unsigned char FPGM(bci_action_serif_link1_down_upper_bound
) [] =
6463 bci_action_serif_link1_down_upper_bound
,
6468 bci_serif_link1_common
,
6481 * bci_action_serif_link1_down_upper_lower_bound
6483 * Handle the SERIF_LINK1 action to align a serif, depending on edges
6484 * before and after. Additionally, move the serif again if necessary to
6485 * stay within a lower and upper bound. We hint top to bottom.
6487 * in: before_point (in twilight zone)
6488 * edge_point (in twilight zone)
6489 * after_point (in twilight zone)
6490 * edge[-1] (in twilight zone)
6491 * edge[1] (in twilight zone)
6492 * ... stuff for bci_align_segments (edge) ...
6494 * uses: bci_serif_link1_common
6495 * bci_upper_lower_bound
6498 static const unsigned char FPGM(bci_action_serif_link1_down_upper_lower_bound
) [] =
6502 bci_action_serif_link1_down_upper_lower_bound
,
6507 bci_serif_link1_common
,
6511 bci_upper_lower_bound
,
6520 * bci_serif_link2_common
6522 * Common code for bci_action_serif_link2 routines.
6524 * in: top_to_bottom_hinting
6527 * out: edge (adjusted)
6530 * sal_top_to_bottom_hinting
6534 static const unsigned char FPGM(bci_serif_link2_common
) [] =
6538 bci_serif_link2_common
,
6543 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
6546 sal_top_to_bottom_hinting
,
6550 DUP
, /* s: [...] edge edge */
6554 DUP
, /* s: [...] edge edge anchor anchor */
6555 MDAP_noround
, /* set rp0 and rp1 to `sal_anchor' */
6564 DIV_BY_2
, /* delta = (edge_orig_pos - anchor_orig_pos + 16) & ~31 */
6569 ALIGNRP
, /* align `edge' with `sal_anchor' */
6571 SHPIX
, /* shift `edge' by `delta' */
6579 * bci_action_serif_link2
6581 * Handle the SERIF_LINK2 action to align a serif relative to the anchor.
6583 * in: edge_point (in twilight zone)
6584 * ... stuff for bci_align_segments (edge) ...
6586 * uses: bci_serif_link2_common
6587 * bci_align_segments
6590 static const unsigned char FPGM(bci_action_serif_link2
) [] =
6594 bci_action_serif_link2
,
6599 bci_serif_link2_common
,
6602 MDAP_noround
, /* set rp0 and rp1 to `edge' */
6607 SZP1
, /* set zp1 to normal zone 1 */
6616 * bci_action_serif_link2_lower_bound
6618 * Handle the SERIF_LINK2 action to align a serif relative to the anchor.
6619 * Additionally, move the serif again if necessary to stay within a lower
6622 * in: edge_point (in twilight zone)
6623 * edge[-1] (in twilight zone)
6624 * ... stuff for bci_align_segments (edge) ...
6626 * uses: bci_serif_link2_common
6630 static const unsigned char FPGM(bci_action_serif_link2_lower_bound
) [] =
6634 bci_action_serif_link2_lower_bound
,
6639 bci_serif_link2_common
,
6652 * bci_action_serif_link2_upper_bound
6654 * Handle the SERIF_LINK2 action to align a serif relative to the anchor.
6655 * Additionally, move the serif again if necessary to stay within an upper
6658 * in: edge_point (in twilight zone)
6659 * edge[1] (in twilight zone)
6660 * ... stuff for bci_align_segments (edge) ...
6662 * uses: bci_serif_link2_common
6666 static const unsigned char FPGM(bci_action_serif_link2_upper_bound
) [] =
6670 bci_action_serif_link2_upper_bound
,
6675 bci_serif_link2_common
,
6688 * bci_action_serif_link2_upper_lower_bound
6690 * Handle the SERIF_LINK2 action to align a serif relative to the anchor.
6691 * Additionally, move the serif again if necessary to stay within a lower
6694 * in: edge_point (in twilight zone)
6695 * edge[-1] (in twilight zone)
6696 * edge[1] (in twilight zone)
6697 * ... stuff for bci_align_segments (edge) ...
6699 * uses: bci_serif_link2_common
6700 * bci_upper_lower_bound
6703 static const unsigned char FPGM(bci_action_serif_link2_upper_lower_bound
) [] =
6707 bci_action_serif_link2_upper_lower_bound
,
6712 bci_serif_link2_common
,
6716 bci_upper_lower_bound
,
6725 * bci_action_serif_link2_down_lower_bound
6727 * Handle the SERIF_LINK2 action to align a serif relative to the anchor.
6728 * Additionally, move the serif again if necessary to stay within a lower
6729 * bound. We hint top to bottom.
6731 * in: edge_point (in twilight zone)
6732 * edge[-1] (in twilight zone)
6733 * ... stuff for bci_align_segments (edge) ...
6735 * uses: bci_serif_link2_common
6739 static const unsigned char FPGM(bci_action_serif_link2_down_lower_bound
) [] =
6743 bci_action_serif_link2_down_lower_bound
,
6748 bci_serif_link2_common
,
6761 * bci_action_serif_link2_down_upper_bound
6763 * Handle the SERIF_LINK2 action to align a serif relative to the anchor.
6764 * Additionally, move the serif again if necessary to stay within an upper
6765 * bound. We hint top to bottom.
6767 * in: edge_point (in twilight zone)
6768 * edge[1] (in twilight zone)
6769 * ... stuff for bci_align_segments (edge) ...
6771 * uses: bci_serif_link2_common
6775 static const unsigned char FPGM(bci_action_serif_link2_down_upper_bound
) [] =
6779 bci_action_serif_link2_down_upper_bound
,
6784 bci_serif_link2_common
,
6797 * bci_action_serif_link2_down_upper_lower_bound
6799 * Handle the SERIF_LINK2 action to align a serif relative to the anchor.
6800 * Additionally, move the serif again if necessary to stay within a lower
6801 * and upper bound. We hint top to bottom.
6803 * in: edge_point (in twilight zone)
6804 * edge[-1] (in twilight zone)
6805 * edge[1] (in twilight zone)
6806 * ... stuff for bci_align_segments (edge) ...
6808 * uses: bci_serif_link2_common
6809 * bci_upper_lower_bound
6812 static const unsigned char FPGM(bci_action_serif_link2_down_upper_lower_bound
) [] =
6816 bci_action_serif_link2_down_upper_lower_bound
,
6821 bci_serif_link2_common
,
6825 bci_upper_lower_bound
,
6836 * This is the top-level glyph hinting function which parses the arguments
6837 * on the stack and calls subroutines.
6839 * in: action_0_func_idx
6845 * CVT: cvtl_is_subglyph
6846 * cvtl_stem_width_mode
6849 * sal: sal_stem_width_function
6851 * uses: bci_action_ip_before
6852 * bci_action_ip_after
6854 * bci_action_ip_between
6856 * bci_action_adjust_bound
6857 * bci_action_adjust_bound_serif
6858 * bci_action_adjust_bound_round
6859 * bci_action_adjust_bound_round_serif
6861 * bci_action_stem_bound
6862 * bci_action_stem_bound_serif
6863 * bci_action_stem_bound_round
6864 * bci_action_stem_bound_round_serif
6867 * bci_action_link_serif
6868 * bci_action_link_round
6869 * bci_action_link_round_serif
6872 * bci_action_anchor_serif
6873 * bci_action_anchor_round
6874 * bci_action_anchor_round_serif
6876 * bci_action_blue_anchor
6879 * bci_action_adjust_serif
6880 * bci_action_adjust_round
6881 * bci_action_adjust_round_serif
6884 * bci_action_stem_serif
6885 * bci_action_stem_round
6886 * bci_action_stem_round_serif
6891 * bci_action_serif_lower_bound
6892 * bci_action_serif_upper_bound
6893 * bci_action_serif_upper_lower_bound
6895 * bci_action_serif_anchor
6896 * bci_action_serif_anchor_lower_bound
6897 * bci_action_serif_anchor_upper_bound
6898 * bci_action_serif_anchor_upper_lower_bound
6900 * bci_action_serif_link1
6901 * bci_action_serif_link1_lower_bound
6902 * bci_action_serif_link1_upper_bound
6903 * bci_action_serif_link1_upper_lower_bound
6905 * bci_action_serif_link2
6906 * bci_action_serif_link2_lower_bound
6907 * bci_action_serif_link2_upper_bound
6908 * bci_action_serif_link2_upper_lower_bound
6911 static const unsigned char FPGM(bci_hint_glyph
) [] =
6919 * set up stem width function based on flag in CVT:
6921 * < 0: bci_natural_stem_width
6922 * == 0: bci_smooth_stem_width
6923 * > 0: bci_strong_stem_width
6926 sal_stem_width_function
,
6928 cvtl_stem_width_mode
,
6933 bci_strong_stem_width
,
6937 bci_smooth_stem_width
,
6938 bci_natural_stem_width
,
6939 cvtl_stem_width_mode
,
6952 /* loop until all data on stack is used */
6961 JROT
, /* goto start_loop */
6966 SZP2
, /* set zp2 to normal zone 1 */
6977 #define COPY_FPGM(func_name) \
6980 memcpy(bufp, fpgm_ ## func_name, \
6981 sizeof (fpgm_ ## func_name)); \
6982 bufp += sizeof (fpgm_ ## func_name); \
6986 TA_table_build_fpgm(FT_Byte
** fpgm
,
6991 SFNT_Table
* glyf_table
= &font
->tables
[sfnt
->glyf_idx
];
6992 glyf_Data
* data
= (glyf_Data
*)glyf_table
->data
;
6994 unsigned char num_used_styles
= (unsigned char)data
->num_used_styles
;
6995 unsigned char fallback_style
=
6996 CVT_SCALING_VALUE_OFFSET(0)
6997 + (unsigned char)data
->style_ids
[font
->fallback_style
];
7005 /* for compatibility with dumb bytecode interpreters or analyzers, */
7006 /* FDEFs are stored in ascending index order, without holes -- */
7007 /* note that some FDEFs are not always needed */
7008 /* (depending on options of `TTFautohint'), */
7009 /* but implementing dynamic FDEF indices would be a lot of work */
7011 buf_len
= sizeof (FPGM(bci_align_x_height_a
))
7012 + (font
->increase_x_height
7013 ? (sizeof (FPGM(bci_align_x_height_b1a
))
7015 + sizeof (FPGM(bci_align_x_height_b1b
)))
7016 : sizeof (FPGM(bci_align_x_height_b2
)))
7017 + sizeof (FPGM(bci_align_x_height_c
))
7018 + sizeof (FPGM(bci_round
))
7019 + sizeof (FPGM(bci_natural_stem_width
))
7020 + sizeof (FPGM(bci_quantize_stem_width
))
7021 + sizeof (FPGM(bci_smooth_stem_width
))
7022 + sizeof (FPGM(bci_get_best_width
))
7023 + sizeof (FPGM(bci_strong_stem_width_a
))
7025 + sizeof (FPGM(bci_strong_stem_width_b
))
7026 + sizeof (FPGM(bci_loop_do
))
7027 + sizeof (FPGM(bci_loop
))
7028 + sizeof (FPGM(bci_cvt_rescale
))
7029 + sizeof (FPGM(bci_cvt_rescale_range
))
7030 + sizeof (FPGM(bci_vwidth_data_store
))
7031 + sizeof (FPGM(bci_smooth_blue_round
))
7032 + sizeof (FPGM(bci_strong_blue_round
))
7033 + sizeof (FPGM(bci_blue_round_range
))
7034 + sizeof (FPGM(bci_decrement_component_counter
))
7035 + sizeof (FPGM(bci_get_point_extrema
))
7036 + sizeof (FPGM(bci_nibbles
))
7037 + sizeof (FPGM(bci_number_set_is_element
))
7038 + sizeof (FPGM(bci_number_set_is_element2
))
7040 + sizeof (FPGM(bci_create_segment
))
7041 + sizeof (FPGM(bci_create_segments_a
))
7043 + sizeof (FPGM(bci_create_segments_b
))
7044 + (font
->control_data_head
!= 0
7045 ? sizeof (FPGM(bci_create_segments_c
))
7047 + sizeof (FPGM(bci_create_segments_d
))
7049 + sizeof (FPGM(bci_create_segments_0
))
7050 + sizeof (FPGM(bci_create_segments_1
))
7051 + sizeof (FPGM(bci_create_segments_2
))
7052 + sizeof (FPGM(bci_create_segments_3
))
7053 + sizeof (FPGM(bci_create_segments_4
))
7054 + sizeof (FPGM(bci_create_segments_5
))
7055 + sizeof (FPGM(bci_create_segments_6
))
7056 + sizeof (FPGM(bci_create_segments_7
))
7057 + sizeof (FPGM(bci_create_segments_8
))
7058 + sizeof (FPGM(bci_create_segments_9
))
7060 + sizeof (FPGM(bci_deltap1
))
7061 + sizeof (FPGM(bci_deltap2
))
7062 + sizeof (FPGM(bci_deltap3
))
7064 + sizeof (FPGM(bci_create_segments_composite_a
))
7066 + sizeof (FPGM(bci_create_segments_composite_b
))
7067 + (font
->control_data_head
!= 0
7068 ? sizeof (FPGM(bci_create_segments_composite_c
))
7070 + sizeof (FPGM(bci_create_segments_composite_d
))
7072 + sizeof (FPGM(bci_create_segments_composite_0
))
7073 + sizeof (FPGM(bci_create_segments_composite_1
))
7074 + sizeof (FPGM(bci_create_segments_composite_2
))
7075 + sizeof (FPGM(bci_create_segments_composite_3
))
7076 + sizeof (FPGM(bci_create_segments_composite_4
))
7077 + sizeof (FPGM(bci_create_segments_composite_5
))
7078 + sizeof (FPGM(bci_create_segments_composite_6
))
7079 + sizeof (FPGM(bci_create_segments_composite_7
))
7080 + sizeof (FPGM(bci_create_segments_composite_8
))
7081 + sizeof (FPGM(bci_create_segments_composite_9
))
7083 + sizeof (FPGM(bci_align_point
))
7084 + sizeof (FPGM(bci_align_segment
))
7085 + sizeof (FPGM(bci_align_segments
))
7087 + sizeof (FPGM(bci_scale_contour
))
7088 + sizeof (FPGM(bci_scale_glyph_a
))
7090 + sizeof (FPGM(bci_scale_glyph_b
))
7091 + sizeof (FPGM(bci_scale_composite_glyph_a
))
7093 + sizeof (FPGM(bci_scale_composite_glyph_b
))
7094 + sizeof (FPGM(bci_shift_contour
))
7095 + sizeof (FPGM(bci_shift_subglyph_a
))
7097 + sizeof (FPGM(bci_shift_subglyph_b
))
7098 + (font
->control_data_head
!= 0
7099 ? sizeof (FPGM(bci_shift_subglyph_c
))
7101 + sizeof (FPGM(bci_shift_subglyph_d
))
7103 + sizeof (FPGM(bci_ip_outer_align_point
))
7104 + sizeof (FPGM(bci_ip_on_align_points
))
7105 + sizeof (FPGM(bci_ip_between_align_point
))
7106 + sizeof (FPGM(bci_ip_between_align_points
))
7108 + sizeof (FPGM(bci_adjust_common
))
7109 + sizeof (FPGM(bci_stem_common
))
7110 + sizeof (FPGM(bci_serif_common
))
7111 + sizeof (FPGM(bci_serif_anchor_common
))
7112 + sizeof (FPGM(bci_serif_link1_common
))
7113 + sizeof (FPGM(bci_serif_link2_common
))
7115 + sizeof (FPGM(bci_lower_bound
))
7116 + sizeof (FPGM(bci_upper_bound
))
7117 + sizeof (FPGM(bci_upper_lower_bound
))
7119 + sizeof (FPGM(bci_adjust_bound
))
7120 + sizeof (FPGM(bci_stem_bound
))
7121 + sizeof (FPGM(bci_link
))
7122 + sizeof (FPGM(bci_anchor
))
7123 + sizeof (FPGM(bci_adjust
))
7124 + sizeof (FPGM(bci_stem
))
7126 + sizeof (FPGM(bci_action_ip_before
))
7127 + sizeof (FPGM(bci_action_ip_after
))
7128 + sizeof (FPGM(bci_action_ip_on
))
7129 + sizeof (FPGM(bci_action_ip_between
))
7131 + sizeof (FPGM(bci_action_blue
))
7132 + sizeof (FPGM(bci_action_blue_anchor
))
7134 + sizeof (FPGM(bci_action_anchor
))
7135 + sizeof (FPGM(bci_action_anchor_serif
))
7136 + sizeof (FPGM(bci_action_anchor_round
))
7137 + sizeof (FPGM(bci_action_anchor_round_serif
))
7139 + sizeof (FPGM(bci_action_adjust
))
7140 + sizeof (FPGM(bci_action_adjust_serif
))
7141 + sizeof (FPGM(bci_action_adjust_round
))
7142 + sizeof (FPGM(bci_action_adjust_round_serif
))
7143 + sizeof (FPGM(bci_action_adjust_bound
))
7144 + sizeof (FPGM(bci_action_adjust_bound_serif
))
7145 + sizeof (FPGM(bci_action_adjust_bound_round
))
7146 + sizeof (FPGM(bci_action_adjust_bound_round_serif
))
7147 + sizeof (FPGM(bci_action_adjust_down_bound
))
7148 + sizeof (FPGM(bci_action_adjust_down_bound_serif
))
7149 + sizeof (FPGM(bci_action_adjust_down_bound_round
))
7150 + sizeof (FPGM(bci_action_adjust_down_bound_round_serif
))
7152 + sizeof (FPGM(bci_action_link
))
7153 + sizeof (FPGM(bci_action_link_serif
))
7154 + sizeof (FPGM(bci_action_link_round
))
7155 + sizeof (FPGM(bci_action_link_round_serif
))
7157 + sizeof (FPGM(bci_action_stem
))
7158 + sizeof (FPGM(bci_action_stem_serif
))
7159 + sizeof (FPGM(bci_action_stem_round
))
7160 + sizeof (FPGM(bci_action_stem_round_serif
))
7161 + sizeof (FPGM(bci_action_stem_bound
))
7162 + sizeof (FPGM(bci_action_stem_bound_serif
))
7163 + sizeof (FPGM(bci_action_stem_bound_round
))
7164 + sizeof (FPGM(bci_action_stem_bound_round_serif
))
7165 + sizeof (FPGM(bci_action_stem_down_bound
))
7166 + sizeof (FPGM(bci_action_stem_down_bound_serif
))
7167 + sizeof (FPGM(bci_action_stem_down_bound_round
))
7168 + sizeof (FPGM(bci_action_stem_down_bound_round_serif
))
7170 + sizeof (FPGM(bci_action_serif
))
7171 + sizeof (FPGM(bci_action_serif_lower_bound
))
7172 + sizeof (FPGM(bci_action_serif_upper_bound
))
7173 + sizeof (FPGM(bci_action_serif_upper_lower_bound
))
7174 + sizeof (FPGM(bci_action_serif_down_lower_bound
))
7175 + sizeof (FPGM(bci_action_serif_down_upper_bound
))
7176 + sizeof (FPGM(bci_action_serif_down_upper_lower_bound
))
7178 + sizeof (FPGM(bci_action_serif_anchor
))
7179 + sizeof (FPGM(bci_action_serif_anchor_lower_bound
))
7180 + sizeof (FPGM(bci_action_serif_anchor_upper_bound
))
7181 + sizeof (FPGM(bci_action_serif_anchor_upper_lower_bound
))
7182 + sizeof (FPGM(bci_action_serif_anchor_down_lower_bound
))
7183 + sizeof (FPGM(bci_action_serif_anchor_down_upper_bound
))
7184 + sizeof (FPGM(bci_action_serif_anchor_down_upper_lower_bound
))
7186 + sizeof (FPGM(bci_action_serif_link1
))
7187 + sizeof (FPGM(bci_action_serif_link1_lower_bound
))
7188 + sizeof (FPGM(bci_action_serif_link1_upper_bound
))
7189 + sizeof (FPGM(bci_action_serif_link1_upper_lower_bound
))
7190 + sizeof (FPGM(bci_action_serif_link1_down_lower_bound
))
7191 + sizeof (FPGM(bci_action_serif_link1_down_upper_bound
))
7192 + sizeof (FPGM(bci_action_serif_link1_down_upper_lower_bound
))
7194 + sizeof (FPGM(bci_action_serif_link2
))
7195 + sizeof (FPGM(bci_action_serif_link2_lower_bound
))
7196 + sizeof (FPGM(bci_action_serif_link2_upper_bound
))
7197 + sizeof (FPGM(bci_action_serif_link2_upper_lower_bound
))
7198 + sizeof (FPGM(bci_action_serif_link2_down_lower_bound
))
7199 + sizeof (FPGM(bci_action_serif_link2_down_upper_bound
))
7200 + sizeof (FPGM(bci_action_serif_link2_down_upper_lower_bound
))
7202 + sizeof (FPGM(bci_hint_glyph
));
7204 /* buffer length must be a multiple of four */
7205 len
= (buf_len
+ 3) & ~3U;
7206 buf
= (FT_Byte
*)malloc(len
);
7208 return FT_Err_Out_Of_Memory
;
7210 /* pad end of buffer with zeros */
7211 buf
[len
- 1] = 0x00;
7212 buf
[len
- 2] = 0x00;
7213 buf
[len
- 3] = 0x00;
7215 /* copy font program into buffer and fill in the missing variables */
7218 COPY_FPGM(bci_align_x_height_a
);
7219 if (font
->increase_x_height
)
7221 COPY_FPGM(bci_align_x_height_b1a
);
7222 *(bufp
++) = HIGH(font
->increase_x_height
);
7223 *(bufp
++) = LOW(font
->increase_x_height
);
7224 COPY_FPGM(bci_align_x_height_b1b
);
7227 COPY_FPGM(bci_align_x_height_b2
);
7228 COPY_FPGM(bci_align_x_height_c
);
7230 COPY_FPGM(bci_round
);
7231 COPY_FPGM(bci_natural_stem_width
);
7232 COPY_FPGM(bci_quantize_stem_width
);
7233 COPY_FPGM(bci_smooth_stem_width
);
7234 COPY_FPGM(bci_get_best_width
);
7235 COPY_FPGM(bci_strong_stem_width_a
);
7236 *(bufp
++) = num_used_styles
;
7237 COPY_FPGM(bci_strong_stem_width_b
);
7238 COPY_FPGM(bci_loop_do
);
7239 COPY_FPGM(bci_loop
);
7240 COPY_FPGM(bci_cvt_rescale
);
7241 COPY_FPGM(bci_cvt_rescale_range
);
7242 COPY_FPGM(bci_vwidth_data_store
);
7243 COPY_FPGM(bci_smooth_blue_round
);
7244 COPY_FPGM(bci_strong_blue_round
);
7245 COPY_FPGM(bci_blue_round_range
);
7246 COPY_FPGM(bci_decrement_component_counter
);
7247 COPY_FPGM(bci_get_point_extrema
);
7248 COPY_FPGM(bci_nibbles
);
7249 COPY_FPGM(bci_number_set_is_element
);
7250 COPY_FPGM(bci_number_set_is_element2
);
7252 COPY_FPGM(bci_create_segment
);
7253 COPY_FPGM(bci_create_segments_a
);
7254 *(bufp
++) = num_used_styles
;
7255 COPY_FPGM(bci_create_segments_b
);
7256 if (font
->control_data_head
)
7257 COPY_FPGM(bci_create_segments_c
);
7258 COPY_FPGM(bci_create_segments_d
);
7260 COPY_FPGM(bci_create_segments_0
);
7261 COPY_FPGM(bci_create_segments_1
);
7262 COPY_FPGM(bci_create_segments_2
);
7263 COPY_FPGM(bci_create_segments_3
);
7264 COPY_FPGM(bci_create_segments_4
);
7265 COPY_FPGM(bci_create_segments_5
);
7266 COPY_FPGM(bci_create_segments_6
);
7267 COPY_FPGM(bci_create_segments_7
);
7268 COPY_FPGM(bci_create_segments_8
);
7269 COPY_FPGM(bci_create_segments_9
);
7271 COPY_FPGM(bci_deltap1
);
7272 COPY_FPGM(bci_deltap2
);
7273 COPY_FPGM(bci_deltap3
);
7275 COPY_FPGM(bci_create_segments_composite_a
);
7276 *(bufp
++) = num_used_styles
;
7277 COPY_FPGM(bci_create_segments_composite_b
);
7278 if (font
->control_data_head
)
7279 COPY_FPGM(bci_create_segments_composite_c
);
7280 COPY_FPGM(bci_create_segments_composite_d
);
7282 COPY_FPGM(bci_create_segments_composite_0
);
7283 COPY_FPGM(bci_create_segments_composite_1
);
7284 COPY_FPGM(bci_create_segments_composite_2
);
7285 COPY_FPGM(bci_create_segments_composite_3
);
7286 COPY_FPGM(bci_create_segments_composite_4
);
7287 COPY_FPGM(bci_create_segments_composite_5
);
7288 COPY_FPGM(bci_create_segments_composite_6
);
7289 COPY_FPGM(bci_create_segments_composite_7
);
7290 COPY_FPGM(bci_create_segments_composite_8
);
7291 COPY_FPGM(bci_create_segments_composite_9
);
7293 COPY_FPGM(bci_align_point
);
7294 COPY_FPGM(bci_align_segment
);
7295 COPY_FPGM(bci_align_segments
);
7297 COPY_FPGM(bci_scale_contour
);
7298 COPY_FPGM(bci_scale_glyph_a
);
7299 *(bufp
++) = fallback_style
;
7300 COPY_FPGM(bci_scale_glyph_b
);
7301 COPY_FPGM(bci_scale_composite_glyph_a
);
7302 *(bufp
++) = fallback_style
;
7303 COPY_FPGM(bci_scale_composite_glyph_b
);
7304 COPY_FPGM(bci_shift_contour
);
7305 COPY_FPGM(bci_shift_subglyph_a
);
7306 *(bufp
++) = fallback_style
;
7307 COPY_FPGM(bci_shift_subglyph_b
);
7308 if (font
->control_data_head
)
7309 COPY_FPGM(bci_shift_subglyph_c
);
7310 COPY_FPGM(bci_shift_subglyph_d
);
7312 COPY_FPGM(bci_ip_outer_align_point
);
7313 COPY_FPGM(bci_ip_on_align_points
);
7314 COPY_FPGM(bci_ip_between_align_point
);
7315 COPY_FPGM(bci_ip_between_align_points
);
7317 COPY_FPGM(bci_adjust_common
);
7318 COPY_FPGM(bci_stem_common
);
7319 COPY_FPGM(bci_serif_common
);
7320 COPY_FPGM(bci_serif_anchor_common
);
7321 COPY_FPGM(bci_serif_link1_common
);
7322 COPY_FPGM(bci_serif_link2_common
);
7324 COPY_FPGM(bci_lower_bound
);
7325 COPY_FPGM(bci_upper_bound
);
7326 COPY_FPGM(bci_upper_lower_bound
);
7328 COPY_FPGM(bci_adjust_bound
);
7329 COPY_FPGM(bci_stem_bound
);
7330 COPY_FPGM(bci_link
);
7331 COPY_FPGM(bci_anchor
);
7332 COPY_FPGM(bci_adjust
);
7333 COPY_FPGM(bci_stem
);
7335 COPY_FPGM(bci_action_ip_before
);
7336 COPY_FPGM(bci_action_ip_after
);
7337 COPY_FPGM(bci_action_ip_on
);
7338 COPY_FPGM(bci_action_ip_between
);
7340 COPY_FPGM(bci_action_blue
);
7341 COPY_FPGM(bci_action_blue_anchor
);
7343 COPY_FPGM(bci_action_anchor
);
7344 COPY_FPGM(bci_action_anchor_serif
);
7345 COPY_FPGM(bci_action_anchor_round
);
7346 COPY_FPGM(bci_action_anchor_round_serif
);
7348 COPY_FPGM(bci_action_adjust
);
7349 COPY_FPGM(bci_action_adjust_serif
);
7350 COPY_FPGM(bci_action_adjust_round
);
7351 COPY_FPGM(bci_action_adjust_round_serif
);
7352 COPY_FPGM(bci_action_adjust_bound
);
7353 COPY_FPGM(bci_action_adjust_bound_serif
);
7354 COPY_FPGM(bci_action_adjust_bound_round
);
7355 COPY_FPGM(bci_action_adjust_bound_round_serif
);
7356 COPY_FPGM(bci_action_adjust_down_bound
);
7357 COPY_FPGM(bci_action_adjust_down_bound_serif
);
7358 COPY_FPGM(bci_action_adjust_down_bound_round
);
7359 COPY_FPGM(bci_action_adjust_down_bound_round_serif
);
7361 COPY_FPGM(bci_action_link
);
7362 COPY_FPGM(bci_action_link_serif
);
7363 COPY_FPGM(bci_action_link_round
);
7364 COPY_FPGM(bci_action_link_round_serif
);
7366 COPY_FPGM(bci_action_stem
);
7367 COPY_FPGM(bci_action_stem_serif
);
7368 COPY_FPGM(bci_action_stem_round
);
7369 COPY_FPGM(bci_action_stem_round_serif
);
7370 COPY_FPGM(bci_action_stem_bound
);
7371 COPY_FPGM(bci_action_stem_bound_serif
);
7372 COPY_FPGM(bci_action_stem_bound_round
);
7373 COPY_FPGM(bci_action_stem_bound_round_serif
);
7374 COPY_FPGM(bci_action_stem_down_bound
);
7375 COPY_FPGM(bci_action_stem_down_bound_serif
);
7376 COPY_FPGM(bci_action_stem_down_bound_round
);
7377 COPY_FPGM(bci_action_stem_down_bound_round_serif
);
7379 COPY_FPGM(bci_action_serif
);
7380 COPY_FPGM(bci_action_serif_lower_bound
);
7381 COPY_FPGM(bci_action_serif_upper_bound
);
7382 COPY_FPGM(bci_action_serif_upper_lower_bound
);
7383 COPY_FPGM(bci_action_serif_down_lower_bound
);
7384 COPY_FPGM(bci_action_serif_down_upper_bound
);
7385 COPY_FPGM(bci_action_serif_down_upper_lower_bound
);
7387 COPY_FPGM(bci_action_serif_anchor
);
7388 COPY_FPGM(bci_action_serif_anchor_lower_bound
);
7389 COPY_FPGM(bci_action_serif_anchor_upper_bound
);
7390 COPY_FPGM(bci_action_serif_anchor_upper_lower_bound
);
7391 COPY_FPGM(bci_action_serif_anchor_down_lower_bound
);
7392 COPY_FPGM(bci_action_serif_anchor_down_upper_bound
);
7393 COPY_FPGM(bci_action_serif_anchor_down_upper_lower_bound
);
7395 COPY_FPGM(bci_action_serif_link1
);
7396 COPY_FPGM(bci_action_serif_link1_lower_bound
);
7397 COPY_FPGM(bci_action_serif_link1_upper_bound
);
7398 COPY_FPGM(bci_action_serif_link1_upper_lower_bound
);
7399 COPY_FPGM(bci_action_serif_link1_down_lower_bound
);
7400 COPY_FPGM(bci_action_serif_link1_down_upper_bound
);
7401 COPY_FPGM(bci_action_serif_link1_down_upper_lower_bound
);
7403 COPY_FPGM(bci_action_serif_link2
);
7404 COPY_FPGM(bci_action_serif_link2_lower_bound
);
7405 COPY_FPGM(bci_action_serif_link2_upper_bound
);
7406 COPY_FPGM(bci_action_serif_link2_upper_lower_bound
);
7407 COPY_FPGM(bci_action_serif_link2_down_lower_bound
);
7408 COPY_FPGM(bci_action_serif_link2_down_upper_bound
);
7409 COPY_FPGM(bci_action_serif_link2_down_upper_lower_bound
);
7411 COPY_FPGM(bci_hint_glyph
);
7414 *fpgm_len
= buf_len
;
7421 TA_sfnt_build_fpgm_table(SFNT
* sfnt
,
7426 SFNT_Table
* glyf_table
= &font
->tables
[sfnt
->glyf_idx
];
7427 glyf_Data
* data
= (glyf_Data
*)glyf_table
->data
;
7433 error
= TA_sfnt_add_table_info(sfnt
);
7437 /* `glyf', `cvt', `fpgm', and `prep' are always used in parallel */
7438 if (glyf_table
->processed
)
7440 sfnt
->table_infos
[sfnt
->num_table_infos
- 1] = data
->fpgm_idx
;
7444 error
= TA_table_build_fpgm(&fpgm_buf
, &fpgm_len
, sfnt
, font
);
7448 if (fpgm_len
> sfnt
->max_instructions
)
7449 sfnt
->max_instructions
= (FT_UShort
)fpgm_len
;
7451 /* in case of success, `fpgm_buf' gets linked */
7452 /* and is eventually freed in `TA_font_unload' */
7453 error
= TA_font_add_table(font
,
7454 &sfnt
->table_infos
[sfnt
->num_table_infos
- 1],
7455 TTAG_fpgm
, fpgm_len
, fpgm_buf
);
7459 data
->fpgm_idx
= sfnt
->table_infos
[sfnt
->num_table_infos
- 1];
7465 /* end of tafpgm.c */