4 * Copyright (C) 2011-2021 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
2071 * sal_stem_width_offset
2074 * CVT: cvtl_is_subglyph
2076 * uses: bci_create_segment
2080 * If `num_packed_segments' is set to p, the first p start/end pairs are
2081 * stored as delta values in nibbles, with the `start' delta in the lower
2082 * nibble (and there are no wrap-around segments). For example, if the
2083 * first three pairs are 1/3, 5/8, and 12/13, the topmost three bytes on the
2084 * stack are 0x21, 0x32, and 0x14.
2088 static const unsigned char FPGM(bci_create_segments_a
) [] =
2092 bci_create_segments
,
2095 /* all our measurements are taken along the y axis */
2098 /* only do something if we are not a subglyph */
2106 sal_num_packed_segments
,
2113 sal_scale
, /* sal_scale = CVT(data_offset) */
2118 sal_vwidth_data_offset
,
2124 /* %c, number of used styles */
2126 static const unsigned char FPGM(bci_create_segments_b
) [] =
2130 WS
, /* sal_vwidth_data_offset = data_offset + num_used_styles */
2133 ADD
, /* delta = 2*num_segments */
2143 sal_num_stem_widths
,
2145 WS
, /* sal_num_stem_widths = 0 */
2146 WS
, /* sal_base = 0 */
2147 WS
, /* sal_j = 0 (point offset) */
2150 ADD
, /* s: ... sal_segment_offset (sal_segment_offset + delta) */
2154 sal_stem_width_offset
,
2156 WS
, /* sal_stem_width_offset = sal_segment_offset + delta */
2160 SUB
, /* s: ... sal_segment_offset (sal_segment_offset + delta - 1) */
2173 /* used if we have delta exceptions */
2175 static const unsigned char FPGM(bci_create_segments_c
) [] =
2184 static const unsigned char FPGM(bci_create_segments_d
) [] =
2197 * bci_create_segments_X
2199 * Top-level routines for calling `bci_create_segments'.
2202 static const unsigned char FPGM(bci_create_segments_0
) [] =
2206 bci_create_segments_0
,
2211 bci_create_segments
,
2218 static const unsigned char FPGM(bci_create_segments_1
) [] =
2222 bci_create_segments_1
,
2227 bci_create_segments
,
2234 static const unsigned char FPGM(bci_create_segments_2
) [] =
2238 bci_create_segments_2
,
2243 bci_create_segments
,
2250 static const unsigned char FPGM(bci_create_segments_3
) [] =
2254 bci_create_segments_3
,
2259 bci_create_segments
,
2266 static const unsigned char FPGM(bci_create_segments_4
) [] =
2270 bci_create_segments_4
,
2275 bci_create_segments
,
2282 static const unsigned char FPGM(bci_create_segments_5
) [] =
2286 bci_create_segments_5
,
2291 bci_create_segments
,
2298 static const unsigned char FPGM(bci_create_segments_6
) [] =
2302 bci_create_segments_6
,
2307 bci_create_segments
,
2314 static const unsigned char FPGM(bci_create_segments_7
) [] =
2318 bci_create_segments_7
,
2323 bci_create_segments
,
2330 static const unsigned char FPGM(bci_create_segments_8
) [] =
2334 bci_create_segments_8
,
2339 bci_create_segments
,
2346 static const unsigned char FPGM(bci_create_segments_9
) [] =
2350 bci_create_segments_9
,
2355 bci_create_segments
,
2366 * Wrapper functions around DELTAP[123] that touch the affected points
2367 * before applying the delta. This is necessary for ClearType.
2369 * While DELTAP[123] implicitly do a loop, we have to process the
2370 * arguments sequentially by calling `bci_deltaX' with LOOPCALL.
2376 static const unsigned char FPGM(bci_deltap1
) [] =
2384 DUP
, /* s: point arg arg */
2385 PUSHB_1
, /* cf. DIV_POS_BY_2 macro */
2391 MUL
, /* s: point arg hnibble(arg) */
2393 CONTROL_DELTA_PPEM_MIN
,
2394 ADD
, /* s: point arg ppem(arg) */
2400 MDAP_noround
, /* touch `point' */
2404 DELTAP1
, /* process one `(point,arg)' pair */
2414 static const unsigned char FPGM(bci_deltap2
) [] =
2422 DUP
, /* s: point arg arg */
2423 PUSHB_1
, /* cf. DIV_POS_BY_2 macro */
2429 MUL
, /* s: point arg hnibble(arg) */
2431 CONTROL_DELTA_PPEM_MIN
+ 16,
2432 ADD
, /* s: point arg ppem(arg) */
2438 MDAP_noround
, /* touch `point' */
2442 DELTAP2
, /* process one `(point,arg)' pair */
2452 static const unsigned char FPGM(bci_deltap3
) [] =
2460 DUP
, /* s: point arg arg */
2461 PUSHB_1
, /* cf. DIV_POS_BY_2 macro */
2467 MUL
, /* s: point arg hnibble(arg) */
2469 CONTROL_DELTA_PPEM_MIN
+ 32,
2470 ADD
, /* s: point arg ppem(arg) */
2476 MDAP_noround
, /* touch `point' */
2480 DELTAP3
, /* process one `(point,arg)' pair */
2492 * bci_create_segments_composite
2494 * The same as `bci_create_segments'.
2495 * It also decrements the composite component counter.
2497 * sal: sal_num_packed_segments
2498 * sal_segment_offset
2499 * sal_vwidth_data_offset
2501 * CVT: cvtl_is_subglyph
2503 * uses: bci_decrement_component_counter
2504 * bci_create_segment
2509 static const unsigned char FPGM(bci_create_segments_composite_a
) [] =
2513 bci_create_segments_composite
,
2516 /* all our measurements are taken along the y axis */
2520 bci_decrement_component_counter
,
2523 /* only do something if we are not a subglyph */
2531 sal_num_packed_segments
,
2538 sal_scale
, /* sal_scale = CVT(data_offset) */
2543 sal_vwidth_data_offset
,
2549 /* %c, number of used styles */
2551 static const unsigned char FPGM(bci_create_segments_composite_b
) [] =
2555 WS
, /* sal_vwidth_data_offset = data_offset + num_used_styles */
2561 SUB
, /* delta = (2*num_segments - 1) */
2571 WS
, /* sal_base = 0 */
2572 WS
, /* sal_j = 0 (point offset) */
2575 ADD
, /* s: ... sal_segment_offset (sal_segment_offset + delta) */
2588 /* used if we have delta exceptions */
2590 static const unsigned char FPGM(bci_create_segments_composite_c
) [] =
2599 static const unsigned char FPGM(bci_create_segments_composite_d
) [] =
2612 * bci_create_segments_composite_X
2614 * Top-level routines for calling `bci_create_segments_composite'.
2617 static const unsigned char FPGM(bci_create_segments_composite_0
) [] =
2621 bci_create_segments_composite_0
,
2626 bci_create_segments_composite
,
2633 static const unsigned char FPGM(bci_create_segments_composite_1
) [] =
2637 bci_create_segments_composite_1
,
2642 bci_create_segments_composite
,
2649 static const unsigned char FPGM(bci_create_segments_composite_2
) [] =
2653 bci_create_segments_composite_2
,
2658 bci_create_segments_composite
,
2665 static const unsigned char FPGM(bci_create_segments_composite_3
) [] =
2669 bci_create_segments_composite_3
,
2674 bci_create_segments_composite
,
2681 static const unsigned char FPGM(bci_create_segments_composite_4
) [] =
2685 bci_create_segments_composite_4
,
2690 bci_create_segments_composite
,
2697 static const unsigned char FPGM(bci_create_segments_composite_5
) [] =
2701 bci_create_segments_composite_5
,
2706 bci_create_segments_composite
,
2713 static const unsigned char FPGM(bci_create_segments_composite_6
) [] =
2717 bci_create_segments_composite_6
,
2722 bci_create_segments_composite
,
2729 static const unsigned char FPGM(bci_create_segments_composite_7
) [] =
2733 bci_create_segments_composite_7
,
2738 bci_create_segments_composite
,
2745 static const unsigned char FPGM(bci_create_segments_composite_8
) [] =
2749 bci_create_segments_composite_8
,
2754 bci_create_segments_composite
,
2761 static const unsigned char FPGM(bci_create_segments_composite_9
) [] =
2765 bci_create_segments_composite_9
,
2770 bci_create_segments_composite
,
2781 * An auxiliary function for `bci_align_segment'.
2788 static const unsigned char FPGM(bci_align_point
) [] =
2796 ALIGNRP
, /* align point with rp0 */
2810 * Align all points in a segment to the twilight point in rp0.
2811 * zp0 and zp1 must be set to 0 (twilight) and 1 (normal), respectively.
2815 * sal: sal_segment_offset
2817 * uses: bci_align_point
2820 static const unsigned char FPGM(bci_align_segment
) [] =
2827 /* we need the values of `sal_segment_offset + 2*segment_index' */
2828 /* and `sal_segment_offset + 2*segment_index + 1' */
2840 RS
, /* s: first last */
2844 CINDEX
, /* s: first last first */
2848 ADD
, /* s: first loop_count */
2853 /* clean up stack */
2862 * bci_align_segments
2864 * Align segments to the twilight point in rp0.
2865 * zp0 and zp1 must be set to 0 (twilight) and 1 (normal), respectively.
2874 * uses: bci_align_segment
2877 static const unsigned char FPGM(bci_align_segments
) [] =
2900 * Scale a contour using two points giving the maximum and minimum
2903 * It expects that no point on the contour is touched.
2911 static const unsigned char FPGM(bci_scale_contour
) [] =
2922 DO_SCALE
, /* min_pos_new = min_pos * scale */
2927 /* don't scale a single-point contour twice */
2936 DO_SCALE
, /* max_pos_new = max_pos * scale */
2953 * Scale a glyph using a list of points (two points per contour, giving
2954 * the maximum and mininum coordinates).
2956 * It expects that no point in the glyph is touched.
2958 * Note that the point numbers are sorted in ascending order;
2959 * `min_point_X' and `max_point_X' thus refer to the two extrema of a
2960 * contour without specifying which one is the minimum and maximum.
2962 * in: num_contours (N)
2971 * CVT: cvtl_is_subglyph
2976 * uses: bci_scale_contour
2979 static const unsigned char FPGM(bci_scale_glyph_a
) [] =
2986 /* all our measurements are taken along the y axis */
2989 /* only do something if we are not a subglyph */
2996 /* use fallback scaling value */
3002 /* %c, fallback scaling index */
3004 static const unsigned char FPGM(bci_scale_glyph_b
) [] =
3012 SZPS
, /* set zp0, zp1, and zp2 to normal zone 1 */
3021 SZP2
, /* set zp2 to normal zone 1 */
3037 * bci_scale_composite_glyph
3039 * The same as `bci_scale_glyph'.
3040 * It also decrements the composite component counter.
3042 * CVT: cvtl_is_subglyph
3047 * uses: bci_decrement_component_counter
3051 static const unsigned char FPGM(bci_scale_composite_glyph_a
) [] =
3055 bci_scale_composite_glyph
,
3058 /* all our measurements are taken along the y axis */
3062 bci_decrement_component_counter
,
3065 /* only do something if we are not a subglyph */
3072 /* use fallback scaling value */
3078 /* %c, fallback scaling index */
3080 static const unsigned char FPGM(bci_scale_composite_glyph_b
) [] =
3088 SZPS
, /* set zp0, zp1, and zp2 to normal zone 1 */
3097 SZP2
, /* set zp2 to normal zone 1 */
3115 * Shift a contour by a given amount.
3117 * It expects that rp1 (pointed to by zp0) is set up properly; zp2 must
3118 * point to the normal zone 1.
3125 static const unsigned char FPGM(bci_shift_contour
) [] =
3133 SHC_rp1
, /* shift `contour' by (rp1_pos - rp1_orig_pos) */
3145 * bci_shift_subglyph
3147 * Shift a subglyph. To be more specific, it corrects the already applied
3148 * subglyph offset (if any) from the `glyf' table which needs to be scaled
3151 * If this function is called, a point `x' in the subglyph has been scaled
3152 * already (during the hinting of the subglyph itself), and `offset' has
3153 * been applied also:
3155 * x -> x * scale + offset (1)
3157 * However, the offset should be applied first, then the scaling:
3159 * x -> (x + offset) * scale (2)
3161 * Our job is now to transform (1) to (2); a simple calculation shows that
3162 * we have to shift all points of the subglyph by
3164 * offset * scale - offset = offset * (scale - 1)
3166 * Note that `sal_scale' is equal to the above `scale - 1'.
3168 * in: offset (in FUnits)
3172 * CVT: cvtl_funits_to_pixels
3180 static const unsigned char FPGM(bci_shift_subglyph_a
) [] =
3187 /* all our measurements are taken along the y axis */
3190 /* use fallback scaling value */
3196 /* %c, fallback scaling index */
3198 static const unsigned char FPGM(bci_shift_subglyph_b
) [] =
3205 cvtl_funits_to_pixels
,
3206 RCVT
, /* scaling factor FUnits -> pixels */
3210 /* the autohinter always rounds offsets */
3213 CALL
, /* offset = round(offset) */
3219 DIV_BY_1024
, /* delta = offset * (scale - 1) */
3221 /* and round again */
3224 CALL
, /* offset = round(offset) */
3228 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
3230 /* we create twilight point 0 as a reference point, */
3231 /* setting the original position to zero (using `cvtl_temp') */
3239 MIAP_noround
, /* rp0 and rp1 now point to twilight point 0 */
3241 SWAP
, /* s: first_contour num_contours 0 delta */
3242 SHPIX
, /* rp1_pos - rp1_orig_pos = delta */
3247 SZP2
, /* set zp2 to normal zone 1 */
3249 /* clean up stack */
3254 /* used if we have delta exceptions */
3256 static const unsigned char FPGM(bci_shift_subglyph_c
) [] =
3265 static const unsigned char FPGM(bci_shift_subglyph_d
) [] =
3274 * bci_ip_outer_align_point
3276 * Auxiliary function for `bci_action_ip_before' and
3277 * `bci_action_ip_after'.
3279 * It expects rp0 to contain the edge for alignment, zp0 set to twilight
3280 * zone, and both zp1 and zp2 set to normal zone.
3284 * sal: sal_i (edge_orig_pos)
3288 static const unsigned char FPGM(bci_ip_outer_align_point
) [] =
3292 bci_ip_outer_align_point
,
3296 ALIGNRP
, /* align `point' with `edge' */
3299 DO_SCALE
, /* point_orig_pos = point_orig_pos * scale */
3304 SUB
, /* s: point (point_orig_pos - edge_orig_pos) */
3313 * bci_ip_on_align_points
3315 * Auxiliary function for `bci_action_ip_on'.
3317 * in: edge (in twilight zone)
3325 static const unsigned char FPGM(bci_ip_on_align_points
) [] =
3329 bci_ip_on_align_points
,
3332 MDAP_noround
, /* set rp0 and rp1 to `edge' */
3343 * bci_ip_between_align_point
3345 * Auxiliary function for `bci_ip_between_align_points'.
3347 * It expects rp0 to contain the edge for alignment, zp0 set to twilight
3348 * zone, and both zp1 and zp2 set to normal zone.
3352 * sal: sal_i (edge_orig_pos)
3353 * sal_j (stretch_factor)
3357 static const unsigned char FPGM(bci_ip_between_align_point
) [] =
3361 bci_ip_between_align_point
,
3365 ALIGNRP
, /* align `point' with `edge' */
3368 DO_SCALE
, /* point_orig_pos = point_orig_pos * scale */
3373 SUB
, /* s: point (point_orig_pos - edge_orig_pos) */
3377 MUL
, /* s: point delta */
3386 * bci_ip_between_align_points
3388 * Auxiliary function for `bci_action_ip_between'.
3390 * in: after_edge (in twilight zone)
3391 * before_edge (in twilight zone)
3398 * sal: sal_i (before_orig_pos)
3399 * sal_j (stretch_factor)
3401 * uses: bci_ip_between_align_point
3404 static const unsigned char FPGM(bci_ip_between_align_points
) [] =
3408 bci_ip_between_align_points
,
3414 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
3416 DUP
, /* s: ... before after before before */
3417 MDAP_noround
, /* set rp0 and rp1 to `before' */
3419 GC_orig
, /* s: ... before after before before_orig_pos */
3423 WS
, /* sal_i = before_orig_pos */
3426 CINDEX
, /* s: ... before after before after */
3427 MD_cur
, /* a = after_pos - before_pos */
3430 MD_orig_ZP2_0
, /* b = after_orig_pos - before_orig_pos */
3436 POP
, /* avoid division by zero */
3442 WS
, /* sal_j = stretch_factor */
3445 bci_ip_between_align_point
,
3448 SZP2
, /* set zp2 to normal zone 1 */
3449 SZP1
, /* set zp1 to normal zone 1 */
3458 * bci_action_ip_before
3460 * Handle `ip_before' data to align points located before the first edge.
3462 * in: first_edge (in twilight zone)
3469 * sal: sal_i (first_edge_orig_pos)
3471 * uses: bci_ip_outer_align_point
3474 static const unsigned char FPGM(bci_action_ip_before
) [] =
3478 bci_action_ip_before
,
3483 SZP2
, /* set zp2 to twilight zone 0 */
3490 WS
, /* sal_i = first_edge_orig_pos */
3496 SZP2
, /* set zp2 to normal zone 1 */
3497 SZP1
, /* set zp1 to normal zone 1 */
3498 SZP0
, /* set zp0 to twilight zone 0 */
3500 MDAP_noround
, /* set rp0 and rp1 to `first_edge' */
3503 bci_ip_outer_align_point
,
3512 * bci_action_ip_after
3514 * Handle `ip_after' data to align points located after the last edge.
3516 * in: last_edge (in twilight zone)
3523 * sal: sal_i (last_edge_orig_pos)
3525 * uses: bci_ip_outer_align_point
3528 static const unsigned char FPGM(bci_action_ip_after
) [] =
3532 bci_action_ip_after
,
3537 SZP2
, /* set zp2 to twilight zone 0 */
3544 WS
, /* sal_i = last_edge_orig_pos */
3550 SZP2
, /* set zp2 to normal zone 1 */
3551 SZP1
, /* set zp1 to normal zone 1 */
3552 SZP0
, /* set zp0 to twilight zone 0 */
3554 MDAP_noround
, /* set rp0 and rp1 to `last_edge' */
3557 bci_ip_outer_align_point
,
3568 * Handle `ip_on' data to align points located on an edge coordinate (but
3569 * not part of an edge).
3571 * in: loop_counter (M)
3572 * edge_1 (in twilight zone)
3573 * loop_counter (N_1)
3578 * edge_2 (in twilight zone)
3579 * loop_counter (N_2)
3585 * edge_M (in twilight zone)
3586 * loop_counter (N_M)
3592 * uses: bci_ip_on_align_points
3595 static const unsigned char FPGM(bci_action_ip_on
) [] =
3605 SZP1
, /* set zp1 to normal zone 1 */
3606 SZP0
, /* set zp0 to twilight zone 0 */
3609 bci_ip_on_align_points
,
3618 * bci_action_ip_between
3620 * Handle `ip_between' data to align points located between two edges.
3622 * in: loop_counter (M)
3623 * before_edge_1 (in twilight zone)
3624 * after_edge_1 (in twilight zone)
3625 * loop_counter (N_1)
3630 * before_edge_2 (in twilight zone)
3631 * after_edge_2 (in twilight zone)
3632 * loop_counter (N_2)
3638 * before_edge_M (in twilight zone)
3639 * after_edge_M (in twilight zone)
3640 * loop_counter (N_M)
3646 * uses: bci_ip_between_align_points
3649 static const unsigned char FPGM(bci_action_ip_between
) [] =
3653 bci_action_ip_between
,
3657 bci_ip_between_align_points
,
3668 * Common code for bci_action_adjust routines.
3670 * in: top_to_bottom_hinting
3676 * out: edge (adjusted)
3678 * sal: sal_top_to_bottom_hinting
3681 * uses: func[sal_stem_width_function]
3684 static const unsigned char FPGM(bci_adjust_common
) [] =
3693 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
3695 sal_top_to_bottom_hinting
,
3701 CINDEX
, /* s: [...] edge2 edge is_round is_serif edge2 */
3704 CINDEX
, /* s: [...] edge2 edge is_round is_serif edge2 edge */
3705 MD_orig_ZP2_0
, /* s: [...] edge2 edge is_round is_serif org_len */
3708 sal_base_delta
, /* no base_delta needed here */
3713 sal_stem_width_function
,
3716 NEG
, /* s: [...] edge2 edge -cur_len */
3718 ROLL
, /* s: [...] edge -cur_len edge2 */
3719 MDAP_noround
, /* set rp0 and rp1 to `edge2' */
3722 DUP
, /* s: [...] -cur_len edge edge edge */
3723 ALIGNRP
, /* align `edge' with `edge2' */
3725 SHPIX
, /* shift `edge' by -cur_len */
3735 * Handle the ADJUST + BOUND actions to align an edge of a stem if the
3736 * other edge of the stem has already been moved, then moving it again if
3737 * necessary to stay bound.
3739 * in: top_to_bottom_hinting
3742 * edge_point (in twilight zone)
3743 * edge2_point (in twilight zone)
3744 * edge[-1] (in twilight zone)
3745 * ... stuff for bci_align_segments (edge) ...
3747 * sal: sal_top_to_bottom_hinting
3749 * uses: bci_adjust_common
3750 * bci_align_segments
3753 static const unsigned char FPGM(bci_adjust_bound
) [] =
3764 SWAP
, /* s: edge edge[-1] */
3766 MDAP_noround
, /* set rp0 and rp1 to `edge[-1]' */
3771 GC_cur
, /* s: edge edge[-1]_pos edge_pos */
3773 sal_top_to_bottom_hinting
,
3776 LT
, /* edge_pos > edge[-1]_pos */
3778 GT
, /* edge_pos < edge[-1]_pos */
3782 ALIGNRP
, /* align `edge' to `edge[-1]' */
3785 MDAP_noround
, /* set rp0 and rp1 to `edge' */
3790 SZP1
, /* set zp1 to normal zone 1 */
3799 * bci_action_adjust_bound
3800 * bci_action_adjust_bound_serif
3801 * bci_action_adjust_bound_round
3802 * bci_action_adjust_bound_round_serif
3803 * bci_action_adjust_down_bound
3804 * bci_action_adjust_down_bound_serif
3805 * bci_action_adjust_down_bound_round
3806 * bci_action_adjust_down_bound_round_serif
3808 * Higher-level routines for calling `bci_adjust_bound'.
3811 static const unsigned char FPGM(bci_action_adjust_bound
) [] =
3815 bci_action_adjust_bound
,
3829 static const unsigned char FPGM(bci_action_adjust_bound_serif
) [] =
3833 bci_action_adjust_bound_serif
,
3847 static const unsigned char FPGM(bci_action_adjust_bound_round
) [] =
3851 bci_action_adjust_bound_round
,
3865 static const unsigned char FPGM(bci_action_adjust_bound_round_serif
) [] =
3869 bci_action_adjust_bound_round_serif
,
3883 static const unsigned char FPGM(bci_action_adjust_down_bound
) [] =
3887 bci_action_adjust_down_bound
,
3901 static const unsigned char FPGM(bci_action_adjust_down_bound_serif
) [] =
3905 bci_action_adjust_down_bound_serif
,
3919 static const unsigned char FPGM(bci_action_adjust_down_bound_round
) [] =
3923 bci_action_adjust_down_bound_round
,
3937 static const unsigned char FPGM(bci_action_adjust_down_bound_round_serif
) [] =
3941 bci_action_adjust_down_bound_round_serif
,
3959 * Handle the ADJUST action to align an edge of a stem if the other edge
3960 * of the stem has already been moved.
3962 * in: edge2_is_serif
3964 * edge_point (in twilight zone)
3965 * edge2_point (in twilight zone)
3966 * ... stuff for bci_align_segments (edge) ...
3968 * uses: bci_adjust_common
3969 * bci_align_segments
3972 static const unsigned char FPGM(bci_adjust
) [] =
3984 MDAP_noround
, /* set rp0 and rp1 to `edge' */
3989 SZP1
, /* set zp1 to normal zone 1 */
3999 * bci_action_adjust_serif
4000 * bci_action_adjust_round
4001 * bci_action_adjust_round_serif
4003 * Higher-level routines for calling `bci_adjust'.
4006 static const unsigned char FPGM(bci_action_adjust
) [] =
4023 static const unsigned char FPGM(bci_action_adjust_serif
) [] =
4027 bci_action_adjust_serif
,
4040 static const unsigned char FPGM(bci_action_adjust_round
) [] =
4044 bci_action_adjust_round
,
4057 static const unsigned char FPGM(bci_action_adjust_round_serif
) [] =
4061 bci_action_adjust_round_serif
,
4078 * Common code for bci_action_stem routines.
4080 * in: top_to_bottom_hinting
4094 * sal_top_to_bottom_hinting
4097 * uses: func[sal_stem_width_function]
4102 #define sal_u_off sal_temp1
4104 #define sal_d_off sal_temp2
4106 #define sal_org_len sal_temp3
4108 #define sal_edge2 sal_temp3
4110 static const unsigned char FPGM(bci_stem_common
) [] =
4119 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
4122 sal_top_to_bottom_hinting
,
4132 DUP
, /* s: [...] edge2 edge is_round is_serif edge2 edge edge */
4133 MDAP_noround
, /* set rp0 and rp1 to `edge_point' (for ALIGNRP below) */
4135 MD_orig_ZP2_0
, /* s: [...] edge2 edge is_round is_serif org_len */
4143 sal_base_delta
, /* no base_delta needed here */
4148 sal_stem_width_function
,
4150 CALL
, /* s: [...] edge2 edge cur_len */
4155 LT
, /* cur_len < 96 */
4160 LTEQ
, /* cur_len <= 64 */
4178 SWAP
, /* s: [...] edge2 cur_len edge */
4183 DUP
, /* s: [...] edge2 cur_len edge edge anchor anchor */
4189 ADD
, /* s: [...] edge2 cur_len edge org_pos */
4194 ADD
, /* s: [...] edge2 cur_len edge org_center */
4199 CALL
, /* s: [...] edge2 cur_len edge org_center cur_pos1 */
4204 SUB
, /* s: ... cur_len edge cur_pos1 (org_center - cur_pos1) */
4211 ABS
, /* s: ... cur_len edge cur_pos1 (org_center - cur_pos1) delta1 */
4218 ABS
, /* s: [...] edge2 cur_len edge cur_pos1 delta1 delta2 */
4220 LT
, /* delta1 < delta2 */
4225 SUB
, /* cur_pos1 = cur_pos1 - u_off */
4231 ADD
, /* cur_pos1 = cur_pos1 + d_off */
4232 EIF
, /* s: [...] edge2 cur_len edge cur_pos1 */
4238 SUB
, /* arg = cur_pos1 - cur_len/2 */
4240 SWAP
, /* s: [...] edge2 cur_len arg edge */
4246 SWAP
, /* s: [...] edge2 cur_len edge edge arg edge */
4249 SHPIX
, /* edge = cur_pos1 - cur_len/2 */
4252 SWAP
, /* s: [...] edge2 cur_len edge */
4256 GC_cur
, /* s: [...] edge2 cur_len edge anchor_pos */
4264 ADD
, /* s: [...] edge2 cur_len edge org_pos */
4271 ADD
, /* s: [...] edge2 cur_len edge org_pos org_center */
4277 CALL
, /* cur_pos1 = ROUND(org_pos) */
4289 SUB
, /* s: [...] edge2 cur_len edge org_center cur_pos1 cur_pos2 */
4298 SUB
, /* s: ... cur_len edge cur_pos1 cur_pos2 (cur_len/2 - org_center) */
4305 ABS
, /* delta1 = |cur_pos1 + cur_len / 2 - org_center| */
4311 ABS
, /* s: ... edge2 cur_len edge cur_pos1 cur_pos2 delta1 delta2 */
4312 LT
, /* delta1 < delta2 */
4314 POP
, /* arg = cur_pos1 */
4318 POP
, /* arg = cur_pos2 */
4319 EIF
, /* s: [...] edge2 cur_len edge arg */
4326 SWAP
, /* s: [...] edge2 cur_len edge edge arg edge */
4329 SHPIX
, /* edge = arg */
4330 EIF
, /* s: [...] edge2 cur_len edge */
4340 * Handle the STEM action to align two edges of a stem, then moving one
4341 * edge again if necessary to stay bound.
4343 * The code after computing `cur_len' to shift `edge' and `edge2'
4344 * is equivalent to the snippet below (part of `ta_latin_hint_edges'):
4347 * if cur_len < = 64:
4354 * org_pos = anchor + (edge_orig - anchor_orig)
4355 * org_center = org_pos + org_len / 2
4357 * cur_pos1 = ROUND(org_center)
4358 * delta1 = |org_center - (cur_pos1 - u_off)|
4359 * delta2 = |org_center - (cur_pos1 + d_off)|
4360 * if (delta1 < delta2):
4361 * cur_pos1 = cur_pos1 - u_off
4363 * cur_pos1 = cur_pos1 + d_off
4365 * edge = cur_pos1 - cur_len / 2
4368 * org_pos = anchor + (edge_orig - anchor_orig)
4369 * org_center = org_pos + org_len / 2
4371 * cur_pos1 = ROUND(org_pos)
4372 * delta1 = |cur_pos1 + cur_len / 2 - org_center|
4373 * cur_pos2 = ROUND(org_pos + org_len) - cur_len
4374 * delta2 = |cur_pos2 + cur_len / 2 - org_center|
4376 * if (delta1 < delta2):
4381 * edge2 = edge + cur_len
4383 * in: top_to_bottom_hinting
4386 * edge_point (in twilight zone)
4387 * edge2_point (in twilight zone)
4388 * edge[-1] (in twilight zone)
4389 * ... stuff for bci_align_segments (edge) ...
4390 * ... stuff for bci_align_segments (edge2)...
4396 * sal_top_to_bottom_hinting
4398 * uses: bci_stem_common
4399 * bci_align_segments
4402 static const unsigned char FPGM(bci_stem_bound
) [] =
4413 ROLL
, /* s: edge[-1] cur_len edge edge2 */
4416 ALIGNRP
, /* align `edge2' with rp0 (still `edge') */
4420 WS
, /* s: edge[-1] cur_len edge edge2 */
4422 SHPIX
, /* edge2 = edge + cur_len */
4424 SWAP
, /* s: edge edge[-1] */
4426 MDAP_noround
, /* set rp0 and rp1 to `edge[-1]' */
4431 GC_cur
, /* s: edge edge[-1]_pos edge_pos */
4433 sal_top_to_bottom_hinting
,
4436 LT
, /* edge_pos > edge[-1]_pos */
4438 GT
, /* edge_pos < edge[-1]_pos */
4442 ALIGNRP
, /* align `edge' to `edge[-1]' */
4445 MDAP_noround
, /* set rp0 and rp1 to `edge' */
4450 SZP1
, /* set zp1 to normal zone 1 */
4456 MDAP_noround
, /* set rp0 and rp1 to `edge2' */
4468 * bci_action_stem_bound
4469 * bci_action_stem_bound_serif
4470 * bci_action_stem_bound_round
4471 * bci_action_stem_bound_round_serif
4472 * bci_action_stem_down_bound
4473 * bci_action_stem_down_bound_serif
4474 * bci_action_stem_down_bound_round
4475 * bci_action_stem_down_bound_round_serif
4477 * Higher-level routines for calling `bci_stem_bound'.
4480 static const unsigned char FPGM(bci_action_stem_bound
) [] =
4484 bci_action_stem_bound
,
4498 static const unsigned char FPGM(bci_action_stem_bound_serif
) [] =
4502 bci_action_stem_bound_serif
,
4516 static const unsigned char FPGM(bci_action_stem_bound_round
) [] =
4520 bci_action_stem_bound_round
,
4534 static const unsigned char FPGM(bci_action_stem_bound_round_serif
) [] =
4538 bci_action_stem_bound_round_serif
,
4552 static const unsigned char FPGM(bci_action_stem_down_bound
) [] =
4556 bci_action_stem_down_bound
,
4570 static const unsigned char FPGM(bci_action_stem_down_bound_serif
) [] =
4574 bci_action_stem_down_bound_serif
,
4588 static const unsigned char FPGM(bci_action_stem_down_bound_round
) [] =
4592 bci_action_stem_down_bound_round
,
4606 static const unsigned char FPGM(bci_action_stem_down_bound_round_serif
) [] =
4610 bci_action_stem_down_bound_round_serif
,
4628 * Handle the STEM action to align two edges of a stem.
4630 * See `bci_stem_bound' for more details.
4632 * in: edge2_is_serif
4634 * edge_point (in twilight zone)
4635 * edge2_point (in twilight zone)
4636 * ... stuff for bci_align_segments (edge) ...
4637 * ... stuff for bci_align_segments (edge2)...
4644 * uses: bci_stem_common
4645 * bci_align_segments
4648 static const unsigned char FPGM(bci_stem
) [] =
4661 SWAP
, /* s: cur_len edge2 */
4664 ALIGNRP
, /* align `edge2' with rp0 (still `edge') */
4668 WS
, /* s: cur_len edge2 */
4670 SHPIX
, /* edge2 = edge + cur_len */
4675 SZP1
, /* set zp1 to normal zone 1 */
4681 MDAP_noround
, /* set rp0 and rp1 to `edge2' */
4693 * bci_action_stem_serif
4694 * bci_action_stem_round
4695 * bci_action_stem_round_serif
4697 * Higher-level routines for calling `bci_stem'.
4700 static const unsigned char FPGM(bci_action_stem
) [] =
4717 static const unsigned char FPGM(bci_action_stem_serif
) [] =
4721 bci_action_stem_serif
,
4734 static const unsigned char FPGM(bci_action_stem_round
) [] =
4738 bci_action_stem_round
,
4751 static const unsigned char FPGM(bci_action_stem_round_serif
) [] =
4755 bci_action_stem_round_serif
,
4772 * Handle the LINK action to link an edge to another one.
4776 * base_point (in twilight zone)
4777 * stem_point (in twilight zone)
4778 * ... stuff for bci_align_segments (base) ...
4780 * sal: sal_base_delta
4782 * uses: func[sal_stem_width_function]
4783 * bci_align_segments
4786 static const unsigned char FPGM(bci_link
) [] =
4795 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
4803 DUP
, /* s: stem is_round is_serif stem base base */
4810 SUB
, /* base_delta = base_point_pos - base_point_orig_pos */
4814 WS
, /* sal_base_delta = base_delta */
4816 MDAP_noround
, /* set rp0 and rp1 to `base_point' (for ALIGNRP below) */
4818 MD_orig_ZP2_0
, /* s: stem is_round is_serif dist_orig */
4821 sal_stem_width_function
,
4823 CALL
, /* s: stem new_dist */
4827 ALIGNRP
, /* align `stem_point' with `base_point' */
4829 MDAP_noround
, /* set rp0 and rp1 to `stem_point' */
4831 SHPIX
, /* stem_point = base_point + new_dist */
4836 SZP1
, /* set zp1 to normal zone 1 */
4846 * bci_action_link_serif
4847 * bci_action_link_round
4848 * bci_action_link_round_serif
4850 * Higher-level routines for calling `bci_link'.
4853 static const unsigned char FPGM(bci_action_link
) [] =
4870 static const unsigned char FPGM(bci_action_link_serif
) [] =
4874 bci_action_link_serif
,
4887 static const unsigned char FPGM(bci_action_link_round
) [] =
4891 bci_action_link_round
,
4904 static const unsigned char FPGM(bci_action_link_round_serif
) [] =
4908 bci_action_link_round_serif
,
4925 * Handle the ANCHOR action to align two edges
4926 * and to set the edge anchor.
4928 * The code after computing `cur_len' to shift `edge' and `edge2'
4929 * is equivalent to the snippet below (part of `ta_latin_hint_edges'):
4932 * if cur_len < = 64:
4939 * org_center = edge_orig + org_len / 2
4940 * cur_pos1 = ROUND(org_center)
4942 * error1 = |org_center - (cur_pos1 - u_off)|
4943 * error2 = |org_center - (cur_pos1 + d_off)|
4944 * if (error1 < error2):
4945 * cur_pos1 = cur_pos1 - u_off
4947 * cur_pos1 = cur_pos1 + d_off
4949 * edge = cur_pos1 - cur_len / 2
4950 * edge2 = edge + cur_len
4953 * edge = ROUND(edge_orig)
4955 * in: edge2_is_serif
4957 * edge_point (in twilight zone)
4958 * edge2_point (in twilight zone)
4959 * ... stuff for bci_align_segments (edge) ...
4967 * uses: func[sal_stem_width_function]
4969 * bci_align_segments
4973 #define sal_u_off sal_temp1
4975 #define sal_d_off sal_temp2
4977 #define sal_org_len sal_temp3
4979 static const unsigned char FPGM(bci_anchor
) [] =
4986 /* store anchor point number in `sal_anchor' */
4991 WS
, /* sal_anchor = edge_point */
4995 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
5003 DUP
, /* s: edge2 edge is_round is_serif edge2 edge edge */
5004 MDAP_noround
, /* set rp0 and rp1 to `edge_point' (for ALIGNRP below) */
5006 MD_orig_ZP2_0
, /* s: edge2 edge is_round is_serif org_len */
5014 sal_base_delta
, /* no base_delta needed here */
5019 sal_stem_width_function
,
5021 CALL
, /* s: edge2 edge cur_len */
5026 LT
, /* cur_len < 96 */
5031 LTEQ
, /* cur_len <= 64 */
5049 SWAP
, /* s: edge2 cur_len edge */
5050 DUP
, /* s: edge2 cur_len edge edge */
5057 ADD
, /* s: edge2 cur_len edge org_center */
5062 CALL
, /* s: edge2 cur_len edge org_center cur_pos1 */
5067 SUB
, /* s: edge2 cur_len edge cur_pos1 (org_center - cur_pos1) */
5074 ABS
, /* s: edge2 cur_len edge cur_pos1 (org_center - cur_pos1) error1 */
5081 ABS
, /* s: edge2 cur_len edge cur_pos1 error1 error2 */
5083 LT
, /* error1 < error2 */
5088 SUB
, /* cur_pos1 = cur_pos1 - u_off */
5094 ADD
, /* cur_pos1 = cur_pos1 + d_off */
5095 EIF
, /* s: edge2 cur_len edge cur_pos1 */
5101 SUB
, /* s: edge2 cur_len edge (cur_pos1 - cur_len/2) */
5105 CINDEX
, /* s: edge2 cur_len edge (cur_pos1 - cur_len/2) edge */
5108 SHPIX
, /* edge = cur_pos1 - cur_len/2 */
5110 SWAP
, /* s: cur_len edge2 */
5112 ALIGNRP
, /* align `edge2' with rp0 (still `edge') */
5114 SHPIX
, /* edge2 = edge1 + cur_len */
5117 POP
, /* s: edge2 edge */
5125 CALL
, /* s: edge2 edge edge_pos round(edge_orig_pos) */
5128 SHPIX
, /* edge = round(edge_orig) */
5130 /* clean up stack */
5137 SZP1
, /* set zp1 to normal zone 1 */
5147 * bci_action_anchor_serif
5148 * bci_action_anchor_round
5149 * bci_action_anchor_round_serif
5151 * Higher-level routines for calling `bci_anchor'.
5154 static const unsigned char FPGM(bci_action_anchor
) [] =
5171 static const unsigned char FPGM(bci_action_anchor_serif
) [] =
5175 bci_action_anchor_serif
,
5188 static const unsigned char FPGM(bci_action_anchor_round
) [] =
5192 bci_action_anchor_round
,
5205 static const unsigned char FPGM(bci_action_anchor_round_serif
) [] =
5209 bci_action_anchor_round_serif
,
5224 * bci_action_blue_anchor
5226 * Handle the BLUE_ANCHOR action to align an edge with a blue zone
5227 * and to set the edge anchor.
5229 * in: anchor_point (in twilight zone)
5231 * edge_point (in twilight zone)
5232 * ... stuff for bci_align_segments (edge) ...
5236 * uses: bci_action_blue
5239 static const unsigned char FPGM(bci_action_blue_anchor
) [] =
5243 bci_action_blue_anchor
,
5246 /* store anchor point number in `sal_anchor' */
5264 * Handle the BLUE action to align an edge with a blue zone.
5267 * edge_point (in twilight zone)
5268 * ... stuff for bci_align_segments (edge) ...
5270 * uses: bci_align_segments
5273 static const unsigned char FPGM(bci_action_blue
) [] =
5282 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
5284 /* move `edge_point' to `blue_cvt_idx' position; */
5285 /* note that we can't use MIAP since this would modify */
5286 /* the twilight point's original coordinates also */
5290 MDAP_noround
, /* set rp0 and rp1 to `edge' */
5292 GC_cur
, /* s: new_pos edge edge_pos */
5295 SUB
, /* s: edge (new_pos - edge_pos) */
5301 SZP1
, /* set zp1 to normal zone 1 */
5312 * Common code for bci_action_serif routines.
5314 * in: top_to_bottom_hinting
5318 * sal: sal_top_to_bottom_hinting
5322 static const unsigned char FPGM(bci_serif_common
) [] =
5331 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
5334 sal_top_to_bottom_hinting
,
5343 MINDEX
, /* s: [...] serif serif serif serif base */
5345 MDAP_noround
, /* set rp0 and rp1 to `base_point' */
5348 ALIGNRP
, /* align `serif_point' with `base_point' */
5349 SHPIX
, /* serif = base + (serif_orig_pos - base_orig_pos) */
5359 * Move an edge if necessary to stay within a lower bound.
5364 * sal: sal_top_to_bottom_hinting
5366 * uses: bci_align_segments
5369 static const unsigned char FPGM(bci_lower_bound
) [] =
5376 SWAP
, /* s: edge bound */
5378 MDAP_noround
, /* set rp0 and rp1 to `bound' */
5383 GC_cur
, /* s: edge bound_pos edge_pos */
5385 sal_top_to_bottom_hinting
,
5388 LT
, /* edge_pos > bound_pos */
5390 GT
, /* edge_pos < bound_pos */
5394 ALIGNRP
, /* align `edge' to `bound' */
5397 MDAP_noround
, /* set rp0 and rp1 to `edge_point' */
5402 SZP1
, /* set zp1 to normal zone 1 */
5413 * Move an edge if necessary to stay within an upper bound.
5418 * sal: sal_top_to_bottom_hinting
5420 * uses: bci_align_segments
5423 static const unsigned char FPGM(bci_upper_bound
) [] =
5430 SWAP
, /* s: edge bound */
5432 MDAP_noround
, /* set rp0 and rp1 to `bound' */
5437 GC_cur
, /* s: edge bound_pos edge_pos */
5439 sal_top_to_bottom_hinting
,
5442 GT
, /* edge_pos < bound_pos */
5444 LT
, /* edge_pos > bound_pos */
5448 ALIGNRP
, /* align `edge' to `bound' */
5451 MDAP_noround
, /* set rp0 and rp1 to `edge_point' */
5456 SZP1
, /* set zp1 to normal zone 1 */
5465 * bci_upper_lower_bound
5467 * Move an edge if necessary to stay within a lower and lower bound.
5473 * sal: sal_top_to_bottom_hinting
5475 * uses: bci_align_segments
5478 static const unsigned char FPGM(bci_upper_lower_bound
) [] =
5482 bci_upper_lower_bound
,
5485 SWAP
, /* s: upper serif lower */
5487 MDAP_noround
, /* set rp0 and rp1 to `lower' */
5492 GC_cur
, /* s: upper serif lower_pos serif_pos */
5494 sal_top_to_bottom_hinting
,
5497 LT
, /* serif_pos > lower_pos */
5499 GT
, /* serif_pos < lower_pos */
5503 ALIGNRP
, /* align `serif' to `lower' */
5506 SWAP
, /* s: serif upper */
5508 MDAP_noround
, /* set rp0 and rp1 to `upper' */
5513 GC_cur
, /* s: serif upper_pos serif_pos */
5515 sal_top_to_bottom_hinting
,
5518 GT
, /* serif_pos < upper_pos */
5520 LT
, /* serif_pos > upper_pos */
5524 ALIGNRP
, /* align `serif' to `upper' */
5527 MDAP_noround
, /* set rp0 and rp1 to `serif_point' */
5532 SZP1
, /* set zp1 to normal zone 1 */
5543 * Handle the SERIF action to align a serif with its base.
5545 * in: serif_point (in twilight zone)
5546 * base_point (in twilight zone)
5547 * ... stuff for bci_align_segments (serif) ...
5549 * uses: bci_serif_common
5550 * bci_align_segments
5553 static const unsigned char FPGM(bci_action_serif
) [] =
5565 MDAP_noround
, /* set rp0 and rp1 to `serif_point' */
5570 SZP1
, /* set zp1 to normal zone 1 */
5579 * bci_action_serif_lower_bound
5581 * Handle the SERIF action to align a serif with its base, then moving it
5582 * again if necessary to stay within a lower bound.
5584 * in: serif_point (in twilight zone)
5585 * base_point (in twilight zone)
5586 * edge[-1] (in twilight zone)
5587 * ... stuff for bci_align_segments (serif) ...
5589 * uses: bci_serif_common
5593 static const unsigned char FPGM(bci_action_serif_lower_bound
) [] =
5597 bci_action_serif_lower_bound
,
5615 * bci_action_serif_upper_bound
5617 * Handle the SERIF action to align a serif with its base, then moving it
5618 * again if necessary to stay within an upper bound.
5620 * in: serif_point (in twilight zone)
5621 * base_point (in twilight zone)
5622 * edge[1] (in twilight zone)
5623 * ... stuff for bci_align_segments (serif) ...
5625 * uses: bci_serif_common
5629 static const unsigned char FPGM(bci_action_serif_upper_bound
) [] =
5633 bci_action_serif_upper_bound
,
5651 * bci_action_serif_upper_lower_bound
5653 * Handle the SERIF action to align a serif with its base, then moving it
5654 * again if necessary to stay within a lower and upper bound.
5656 * in: serif_point (in twilight zone)
5657 * base_point (in twilight zone)
5658 * edge[-1] (in twilight zone)
5659 * edge[1] (in twilight zone)
5660 * ... stuff for bci_align_segments (serif) ...
5662 * uses: bci_serif_common
5663 * bci_upper_lower_bound
5666 static const unsigned char FPGM(bci_action_serif_upper_lower_bound
) [] =
5670 bci_action_serif_upper_lower_bound
,
5675 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
5683 bci_upper_lower_bound
,
5692 * bci_action_serif_down_lower_bound
5694 * Handle the SERIF action to align a serif with its base, then moving it
5695 * again if necessary to stay within a lower bound. We hint top to
5698 * in: serif_point (in twilight zone)
5699 * base_point (in twilight zone)
5700 * edge[-1] (in twilight zone)
5701 * ... stuff for bci_align_segments (serif) ...
5703 * uses: bci_serif_common
5707 static const unsigned char FPGM(bci_action_serif_down_lower_bound
) [] =
5711 bci_action_serif_down_lower_bound
,
5729 * bci_action_serif_down_upper_bound
5731 * Handle the SERIF action to align a serif with its base, then moving it
5732 * again if necessary to stay within an upper bound. We hint top to
5735 * in: serif_point (in twilight zone)
5736 * base_point (in twilight zone)
5737 * edge[1] (in twilight zone)
5738 * ... stuff for bci_align_segments (serif) ...
5740 * uses: bci_serif_common
5744 static const unsigned char FPGM(bci_action_serif_down_upper_bound
) [] =
5748 bci_action_serif_down_upper_bound
,
5766 * bci_action_serif_down_upper_lower_bound
5768 * Handle the SERIF action to align a serif with its base, then moving it
5769 * again if necessary to stay within a lower and upper bound. We hint top
5772 * in: serif_point (in twilight zone)
5773 * base_point (in twilight zone)
5774 * edge[-1] (in twilight zone)
5775 * edge[1] (in twilight zone)
5776 * ... stuff for bci_align_segments (serif) ...
5778 * uses: bci_serif_common
5779 * bci_upper_lower_bound
5782 static const unsigned char FPGM(bci_action_serif_down_upper_lower_bound
) [] =
5786 bci_action_serif_down_upper_lower_bound
,
5791 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
5799 bci_upper_lower_bound
,
5808 * bci_serif_anchor_common
5810 * Common code for bci_action_serif_anchor routines.
5812 * in: top_to_bottom_hinting
5815 * out: edge (adjusted)
5818 * sal_top_to_bottom_hinting
5823 static const unsigned char FPGM(bci_serif_anchor_common
) [] =
5827 bci_serif_anchor_common
,
5832 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
5835 sal_top_to_bottom_hinting
,
5843 WS
, /* sal_anchor = edge_point */
5853 CALL
, /* s: [...] edge edge edge_pos round(edge_orig_pos) */
5856 SHPIX
, /* edge = round(edge_orig) */
5864 * bci_action_serif_anchor
5866 * Handle the SERIF_ANCHOR action to align a serif and to set the edge
5869 * in: edge_point (in twilight zone)
5870 * ... stuff for bci_align_segments (edge) ...
5872 * uses: bci_serif_anchor_common
5873 * bci_align_segments
5876 static const unsigned char FPGM(bci_action_serif_anchor
) [] =
5880 bci_action_serif_anchor
,
5885 bci_serif_anchor_common
,
5888 MDAP_noround
, /* set rp0 and rp1 to `edge' */
5893 SZP1
, /* set zp1 to normal zone 1 */
5902 * bci_action_serif_anchor_lower_bound
5904 * Handle the SERIF_ANCHOR action to align a serif and to set the edge
5905 * anchor, then moving it again if necessary to stay within a lower
5908 * in: edge_point (in twilight zone)
5909 * edge[-1] (in twilight zone)
5910 * ... stuff for bci_align_segments (edge) ...
5912 * uses: bci_serif_anchor_common
5916 static const unsigned char FPGM(bci_action_serif_anchor_lower_bound
) [] =
5920 bci_action_serif_anchor_lower_bound
,
5925 bci_serif_anchor_common
,
5938 * bci_action_serif_anchor_upper_bound
5940 * Handle the SERIF_ANCHOR action to align a serif and to set the edge
5941 * anchor, then moving it again if necessary to stay within an upper
5944 * in: edge_point (in twilight zone)
5945 * edge[1] (in twilight zone)
5946 * ... stuff for bci_align_segments (edge) ...
5948 * uses: bci_serif_anchor_common
5952 static const unsigned char FPGM(bci_action_serif_anchor_upper_bound
) [] =
5956 bci_action_serif_anchor_upper_bound
,
5961 bci_serif_anchor_common
,
5974 * bci_action_serif_anchor_upper_lower_bound
5976 * Handle the SERIF_ANCHOR action to align a serif and to set the edge
5977 * anchor, then moving it again if necessary to stay within a lower and
5980 * in: edge_point (in twilight zone)
5981 * edge[-1] (in twilight zone)
5982 * edge[1] (in twilight zone)
5983 * ... stuff for bci_align_segments (edge) ...
5985 * uses: bci_serif_anchor_common
5986 * bci_upper_lower_bound
5989 static const unsigned char FPGM(bci_action_serif_anchor_upper_lower_bound
) [] =
5993 bci_action_serif_anchor_upper_lower_bound
,
5998 bci_serif_anchor_common
,
6002 bci_upper_lower_bound
,
6011 * bci_action_serif_anchor_down_lower_bound
6013 * Handle the SERIF_ANCHOR action to align a serif and to set the edge
6014 * anchor, then moving it again if necessary to stay within a lower
6015 * bound. We hint top to bottom.
6017 * in: edge_point (in twilight zone)
6018 * edge[-1] (in twilight zone)
6019 * ... stuff for bci_align_segments (edge) ...
6021 * uses: bci_serif_anchor_common
6025 static const unsigned char FPGM(bci_action_serif_anchor_down_lower_bound
) [] =
6029 bci_action_serif_anchor_down_lower_bound
,
6034 bci_serif_anchor_common
,
6047 * bci_action_serif_anchor_down_upper_bound
6049 * Handle the SERIF_ANCHOR action to align a serif and to set the edge
6050 * anchor, then moving it again if necessary to stay within an upper
6051 * bound. We hint top to bottom.
6053 * in: edge_point (in twilight zone)
6054 * edge[1] (in twilight zone)
6055 * ... stuff for bci_align_segments (edge) ...
6057 * uses: bci_serif_anchor_common
6061 static const unsigned char FPGM(bci_action_serif_anchor_down_upper_bound
) [] =
6065 bci_action_serif_anchor_down_upper_bound
,
6070 bci_serif_anchor_common
,
6083 * bci_action_serif_anchor_down_upper_lower_bound
6085 * Handle the SERIF_ANCHOR action to align a serif and to set the edge
6086 * anchor, then moving it again if necessary to stay within a lower and
6087 * upper bound. We hint top to bottom.
6089 * in: edge_point (in twilight zone)
6090 * edge[-1] (in twilight zone)
6091 * edge[1] (in twilight zone)
6092 * ... stuff for bci_align_segments (edge) ...
6094 * uses: bci_serif_anchor_common
6095 * bci_upper_lower_bound
6098 static const unsigned char FPGM(bci_action_serif_anchor_down_upper_lower_bound
) [] =
6102 bci_action_serif_anchor_down_upper_lower_bound
,
6107 bci_serif_anchor_common
,
6111 bci_upper_lower_bound
,
6120 * bci_serif_link1_common
6122 * Common code for bci_action_serif_link1 routines.
6124 * in: top_to_bottom_hinting
6129 * out: edge (adjusted)
6131 * sal: sal_top_to_bottom_hinting
6135 static const unsigned char FPGM(bci_serif_link1_common
) [] =
6139 bci_serif_link1_common
,
6144 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
6147 sal_top_to_bottom_hinting
,
6153 CINDEX
, /* s: [...] after edge before after */
6156 CINDEX
, /* s: [...] after edge before after before */
6160 EQ
, /* after_orig_pos == before_orig_pos */
6161 IF
, /* s: [...] after edge before */
6162 MDAP_noround
, /* set rp0 and rp1 to `before' */
6164 ALIGNRP
, /* align `edge' with `before' */
6169 /* we have to execute `a*b/c', with b/c very near to 1: */
6170 /* to avoid overflow while retaining precision, */
6171 /* we transform this to `a + a * (b-c)/c' */
6175 CINDEX
, /* s: [...] after edge before edge */
6178 CINDEX
, /* s: [...] after edge before edge before */
6179 MD_orig_ZP2_0
, /* a = edge_orig_pos - before_orig_pos */
6184 CINDEX
, /* s: [...] after edge before a a after */
6187 CINDEX
, /* s: [...] after edge before a a after before */
6188 MD_orig_ZP2_0
, /* c = after_orig_pos - before_orig_pos */
6192 CINDEX
, /* s: [...] after edge before a a c after */
6195 CINDEX
, /* s: [...] after edge before a a c after before */
6196 MD_cur
, /* b = after_pos - before_pos */
6200 CINDEX
, /* s: [...] after edge before a a c b c */
6209 MUL
, /* (b-c) in 16.16 format */
6214 DIV
, /* s: [...] after edge before a a (b-c)/c */
6216 POP
, /* avoid division by zero */
6219 MUL
, /* a * (b-c)/c * 2^10 */
6220 DIV_BY_1024
, /* a * (b-c)/c */
6224 MDAP_noround
, /* set rp0 and rp1 to `before' */
6225 SWAP
, /* s: [...] after a*b/c edge */
6228 ALIGNRP
, /* align `edge' with `before' */
6230 SHPIX
, /* shift `edge' by `a*b/c' */
6232 SWAP
, /* s: [...] edge after */
6242 * bci_action_serif_link1
6244 * Handle the SERIF_LINK1 action to align a serif, depending on edges
6247 * in: before_point (in twilight zone)
6248 * edge_point (in twilight zone)
6249 * after_point (in twilight zone)
6250 * ... stuff for bci_align_segments (edge) ...
6252 * uses: bci_serif_link1_common
6253 * bci_align_segments
6256 static const unsigned char FPGM(bci_action_serif_link1
) [] =
6260 bci_action_serif_link1
,
6265 bci_serif_link1_common
,
6268 MDAP_noround
, /* set rp0 and rp1 to `edge' */
6273 SZP1
, /* set zp1 to normal zone 1 */
6282 * bci_action_serif_link1_lower_bound
6284 * Handle the SERIF_LINK1 action to align a serif, depending on edges
6285 * before and after. Additionally, move the serif again if necessary to
6286 * stay within a lower bound.
6288 * in: before_point (in twilight zone)
6289 * edge_point (in twilight zone)
6290 * after_point (in twilight zone)
6291 * edge[-1] (in twilight zone)
6292 * ... stuff for bci_align_segments (edge) ...
6294 * uses: bci_serif_link1_common
6298 static const unsigned char FPGM(bci_action_serif_link1_lower_bound
) [] =
6302 bci_action_serif_link1_lower_bound
,
6307 bci_serif_link1_common
,
6320 * bci_action_serif_link1_upper_bound
6322 * Handle the SERIF_LINK1 action to align a serif, depending on edges
6323 * before and after. Additionally, move the serif again if necessary to
6324 * stay within an upper bound.
6326 * in: before_point (in twilight zone)
6327 * edge_point (in twilight zone)
6328 * after_point (in twilight zone)
6329 * edge[1] (in twilight zone)
6330 * ... stuff for bci_align_segments (edge) ...
6332 * uses: bci_serif_link1_common
6336 static const unsigned char FPGM(bci_action_serif_link1_upper_bound
) [] =
6340 bci_action_serif_link1_upper_bound
,
6345 bci_serif_link1_common
,
6358 * bci_action_serif_link1_upper_lower_bound
6360 * Handle the SERIF_LINK1 action to align a serif, depending on edges
6361 * before and after. Additionally, move the serif again if necessary to
6362 * stay within a lower and upper bound.
6364 * in: before_point (in twilight zone)
6365 * edge_point (in twilight zone)
6366 * after_point (in twilight zone)
6367 * edge[-1] (in twilight zone)
6368 * edge[1] (in twilight zone)
6369 * ... stuff for bci_align_segments (edge) ...
6371 * uses: bci_serif_link1_common
6372 * bci_upper_lower_bound
6375 static const unsigned char FPGM(bci_action_serif_link1_upper_lower_bound
) [] =
6379 bci_action_serif_link1_upper_lower_bound
,
6384 bci_serif_link1_common
,
6388 bci_upper_lower_bound
,
6397 * bci_action_serif_link1_down_lower_bound
6399 * Handle the SERIF_LINK1 action to align a serif, depending on edges
6400 * before and after. Additionally, move the serif again if necessary to
6401 * stay within a lower bound. We hint top to bottom.
6403 * in: before_point (in twilight zone)
6404 * edge_point (in twilight zone)
6405 * after_point (in twilight zone)
6406 * edge[-1] (in twilight zone)
6407 * ... stuff for bci_align_segments (edge) ...
6409 * uses: bci_serif_link1_common
6413 static const unsigned char FPGM(bci_action_serif_link1_down_lower_bound
) [] =
6417 bci_action_serif_link1_down_lower_bound
,
6422 bci_serif_link1_common
,
6435 * bci_action_serif_link1_down_upper_bound
6437 * Handle the SERIF_LINK1 action to align a serif, depending on edges
6438 * before and after. Additionally, move the serif again if necessary to
6439 * stay within an upper bound. We hint top to bottom.
6441 * in: before_point (in twilight zone)
6442 * edge_point (in twilight zone)
6443 * after_point (in twilight zone)
6444 * edge[1] (in twilight zone)
6445 * ... stuff for bci_align_segments (edge) ...
6447 * uses: bci_serif_link1_common
6451 static const unsigned char FPGM(bci_action_serif_link1_down_upper_bound
) [] =
6455 bci_action_serif_link1_down_upper_bound
,
6460 bci_serif_link1_common
,
6473 * bci_action_serif_link1_down_upper_lower_bound
6475 * Handle the SERIF_LINK1 action to align a serif, depending on edges
6476 * before and after. Additionally, move the serif again if necessary to
6477 * stay within a lower and upper bound. We hint top to bottom.
6479 * in: before_point (in twilight zone)
6480 * edge_point (in twilight zone)
6481 * after_point (in twilight zone)
6482 * edge[-1] (in twilight zone)
6483 * edge[1] (in twilight zone)
6484 * ... stuff for bci_align_segments (edge) ...
6486 * uses: bci_serif_link1_common
6487 * bci_upper_lower_bound
6490 static const unsigned char FPGM(bci_action_serif_link1_down_upper_lower_bound
) [] =
6494 bci_action_serif_link1_down_upper_lower_bound
,
6499 bci_serif_link1_common
,
6503 bci_upper_lower_bound
,
6512 * bci_serif_link2_common
6514 * Common code for bci_action_serif_link2 routines.
6516 * in: top_to_bottom_hinting
6519 * out: edge (adjusted)
6522 * sal_top_to_bottom_hinting
6526 static const unsigned char FPGM(bci_serif_link2_common
) [] =
6530 bci_serif_link2_common
,
6535 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
6538 sal_top_to_bottom_hinting
,
6542 DUP
, /* s: [...] edge edge */
6546 DUP
, /* s: [...] edge edge anchor anchor */
6547 MDAP_noround
, /* set rp0 and rp1 to `sal_anchor' */
6556 DIV_BY_2
, /* delta = (edge_orig_pos - anchor_orig_pos + 16) & ~31 */
6561 ALIGNRP
, /* align `edge' with `sal_anchor' */
6563 SHPIX
, /* shift `edge' by `delta' */
6571 * bci_action_serif_link2
6573 * Handle the SERIF_LINK2 action to align a serif relative to the anchor.
6575 * in: edge_point (in twilight zone)
6576 * ... stuff for bci_align_segments (edge) ...
6578 * uses: bci_serif_link2_common
6579 * bci_align_segments
6582 static const unsigned char FPGM(bci_action_serif_link2
) [] =
6586 bci_action_serif_link2
,
6591 bci_serif_link2_common
,
6594 MDAP_noround
, /* set rp0 and rp1 to `edge' */
6599 SZP1
, /* set zp1 to normal zone 1 */
6608 * bci_action_serif_link2_lower_bound
6610 * Handle the SERIF_LINK2 action to align a serif relative to the anchor.
6611 * Additionally, move the serif again if necessary to stay within a lower
6614 * in: edge_point (in twilight zone)
6615 * edge[-1] (in twilight zone)
6616 * ... stuff for bci_align_segments (edge) ...
6618 * uses: bci_serif_link2_common
6622 static const unsigned char FPGM(bci_action_serif_link2_lower_bound
) [] =
6626 bci_action_serif_link2_lower_bound
,
6631 bci_serif_link2_common
,
6644 * bci_action_serif_link2_upper_bound
6646 * Handle the SERIF_LINK2 action to align a serif relative to the anchor.
6647 * Additionally, move the serif again if necessary to stay within an upper
6650 * in: edge_point (in twilight zone)
6651 * edge[1] (in twilight zone)
6652 * ... stuff for bci_align_segments (edge) ...
6654 * uses: bci_serif_link2_common
6658 static const unsigned char FPGM(bci_action_serif_link2_upper_bound
) [] =
6662 bci_action_serif_link2_upper_bound
,
6667 bci_serif_link2_common
,
6680 * bci_action_serif_link2_upper_lower_bound
6682 * Handle the SERIF_LINK2 action to align a serif relative to the anchor.
6683 * Additionally, move the serif again if necessary to stay within a lower
6686 * in: edge_point (in twilight zone)
6687 * edge[-1] (in twilight zone)
6688 * edge[1] (in twilight zone)
6689 * ... stuff for bci_align_segments (edge) ...
6691 * uses: bci_serif_link2_common
6692 * bci_upper_lower_bound
6695 static const unsigned char FPGM(bci_action_serif_link2_upper_lower_bound
) [] =
6699 bci_action_serif_link2_upper_lower_bound
,
6704 bci_serif_link2_common
,
6708 bci_upper_lower_bound
,
6717 * bci_action_serif_link2_down_lower_bound
6719 * Handle the SERIF_LINK2 action to align a serif relative to the anchor.
6720 * Additionally, move the serif again if necessary to stay within a lower
6721 * bound. We hint top to bottom.
6723 * in: edge_point (in twilight zone)
6724 * edge[-1] (in twilight zone)
6725 * ... stuff for bci_align_segments (edge) ...
6727 * uses: bci_serif_link2_common
6731 static const unsigned char FPGM(bci_action_serif_link2_down_lower_bound
) [] =
6735 bci_action_serif_link2_down_lower_bound
,
6740 bci_serif_link2_common
,
6753 * bci_action_serif_link2_down_upper_bound
6755 * Handle the SERIF_LINK2 action to align a serif relative to the anchor.
6756 * Additionally, move the serif again if necessary to stay within an upper
6757 * bound. We hint top to bottom.
6759 * in: edge_point (in twilight zone)
6760 * edge[1] (in twilight zone)
6761 * ... stuff for bci_align_segments (edge) ...
6763 * uses: bci_serif_link2_common
6767 static const unsigned char FPGM(bci_action_serif_link2_down_upper_bound
) [] =
6771 bci_action_serif_link2_down_upper_bound
,
6776 bci_serif_link2_common
,
6789 * bci_action_serif_link2_down_upper_lower_bound
6791 * Handle the SERIF_LINK2 action to align a serif relative to the anchor.
6792 * Additionally, move the serif again if necessary to stay within a lower
6793 * and upper bound. We hint top to bottom.
6795 * in: edge_point (in twilight zone)
6796 * edge[-1] (in twilight zone)
6797 * edge[1] (in twilight zone)
6798 * ... stuff for bci_align_segments (edge) ...
6800 * uses: bci_serif_link2_common
6801 * bci_upper_lower_bound
6804 static const unsigned char FPGM(bci_action_serif_link2_down_upper_lower_bound
) [] =
6808 bci_action_serif_link2_down_upper_lower_bound
,
6813 bci_serif_link2_common
,
6817 bci_upper_lower_bound
,
6828 * This is the top-level glyph hinting function which parses the arguments
6829 * on the stack and calls subroutines.
6831 * in: action_0_func_idx
6837 * CVT: cvtl_is_subglyph
6838 * cvtl_stem_width_mode
6841 * sal: sal_stem_width_function
6843 * uses: bci_action_ip_before
6844 * bci_action_ip_after
6846 * bci_action_ip_between
6848 * bci_action_adjust_bound
6849 * bci_action_adjust_bound_serif
6850 * bci_action_adjust_bound_round
6851 * bci_action_adjust_bound_round_serif
6853 * bci_action_stem_bound
6854 * bci_action_stem_bound_serif
6855 * bci_action_stem_bound_round
6856 * bci_action_stem_bound_round_serif
6859 * bci_action_link_serif
6860 * bci_action_link_round
6861 * bci_action_link_round_serif
6864 * bci_action_anchor_serif
6865 * bci_action_anchor_round
6866 * bci_action_anchor_round_serif
6868 * bci_action_blue_anchor
6871 * bci_action_adjust_serif
6872 * bci_action_adjust_round
6873 * bci_action_adjust_round_serif
6876 * bci_action_stem_serif
6877 * bci_action_stem_round
6878 * bci_action_stem_round_serif
6883 * bci_action_serif_lower_bound
6884 * bci_action_serif_upper_bound
6885 * bci_action_serif_upper_lower_bound
6887 * bci_action_serif_anchor
6888 * bci_action_serif_anchor_lower_bound
6889 * bci_action_serif_anchor_upper_bound
6890 * bci_action_serif_anchor_upper_lower_bound
6892 * bci_action_serif_link1
6893 * bci_action_serif_link1_lower_bound
6894 * bci_action_serif_link1_upper_bound
6895 * bci_action_serif_link1_upper_lower_bound
6897 * bci_action_serif_link2
6898 * bci_action_serif_link2_lower_bound
6899 * bci_action_serif_link2_upper_bound
6900 * bci_action_serif_link2_upper_lower_bound
6903 static const unsigned char FPGM(bci_hint_glyph
) [] =
6911 * set up stem width function based on flag in CVT:
6913 * < 0: bci_natural_stem_width
6914 * == 0: bci_smooth_stem_width
6915 * > 0: bci_strong_stem_width
6918 sal_stem_width_function
,
6920 cvtl_stem_width_mode
,
6925 bci_strong_stem_width
,
6929 bci_smooth_stem_width
,
6930 bci_natural_stem_width
,
6931 cvtl_stem_width_mode
,
6944 /* loop until all data on stack is used */
6953 JROT
, /* goto start_loop */
6958 SZP2
, /* set zp2 to normal zone 1 */
6969 #define COPY_FPGM(func_name) \
6972 memcpy(bufp, fpgm_ ## func_name, \
6973 sizeof (fpgm_ ## func_name)); \
6974 bufp += sizeof (fpgm_ ## func_name); \
6978 TA_table_build_fpgm(FT_Byte
** fpgm
,
6983 SFNT_Table
* glyf_table
= &font
->tables
[sfnt
->glyf_idx
];
6984 glyf_Data
* data
= (glyf_Data
*)glyf_table
->data
;
6986 unsigned char num_used_styles
= (unsigned char)data
->num_used_styles
;
6987 unsigned char fallback_style
=
6988 CVT_SCALING_VALUE_OFFSET(0)
6989 + (unsigned char)data
->style_ids
[font
->fallback_style
];
6997 /* for compatibility with dumb bytecode interpreters or analyzers, */
6998 /* FDEFs are stored in ascending index order, without holes -- */
6999 /* note that some FDEFs are not always needed */
7000 /* (depending on options of `TTFautohint'), */
7001 /* but implementing dynamic FDEF indices would be a lot of work */
7003 buf_len
= sizeof (FPGM(bci_align_x_height_a
))
7004 + (font
->increase_x_height
7005 ? (sizeof (FPGM(bci_align_x_height_b1a
))
7007 + sizeof (FPGM(bci_align_x_height_b1b
)))
7008 : sizeof (FPGM(bci_align_x_height_b2
)))
7009 + sizeof (FPGM(bci_align_x_height_c
))
7010 + sizeof (FPGM(bci_round
))
7011 + sizeof (FPGM(bci_natural_stem_width
))
7012 + sizeof (FPGM(bci_quantize_stem_width
))
7013 + sizeof (FPGM(bci_smooth_stem_width
))
7014 + sizeof (FPGM(bci_get_best_width
))
7015 + sizeof (FPGM(bci_strong_stem_width_a
))
7017 + sizeof (FPGM(bci_strong_stem_width_b
))
7018 + sizeof (FPGM(bci_loop_do
))
7019 + sizeof (FPGM(bci_loop
))
7020 + sizeof (FPGM(bci_cvt_rescale
))
7021 + sizeof (FPGM(bci_cvt_rescale_range
))
7022 + sizeof (FPGM(bci_vwidth_data_store
))
7023 + sizeof (FPGM(bci_smooth_blue_round
))
7024 + sizeof (FPGM(bci_strong_blue_round
))
7025 + sizeof (FPGM(bci_blue_round_range
))
7026 + sizeof (FPGM(bci_decrement_component_counter
))
7027 + sizeof (FPGM(bci_get_point_extrema
))
7028 + sizeof (FPGM(bci_nibbles
))
7029 + sizeof (FPGM(bci_number_set_is_element
))
7030 + sizeof (FPGM(bci_number_set_is_element2
))
7032 + sizeof (FPGM(bci_create_segment
))
7033 + sizeof (FPGM(bci_create_segments_a
))
7035 + sizeof (FPGM(bci_create_segments_b
))
7036 + (font
->control_data_head
!= 0
7037 ? sizeof (FPGM(bci_create_segments_c
))
7039 + sizeof (FPGM(bci_create_segments_d
))
7041 + sizeof (FPGM(bci_create_segments_0
))
7042 + sizeof (FPGM(bci_create_segments_1
))
7043 + sizeof (FPGM(bci_create_segments_2
))
7044 + sizeof (FPGM(bci_create_segments_3
))
7045 + sizeof (FPGM(bci_create_segments_4
))
7046 + sizeof (FPGM(bci_create_segments_5
))
7047 + sizeof (FPGM(bci_create_segments_6
))
7048 + sizeof (FPGM(bci_create_segments_7
))
7049 + sizeof (FPGM(bci_create_segments_8
))
7050 + sizeof (FPGM(bci_create_segments_9
))
7052 + sizeof (FPGM(bci_deltap1
))
7053 + sizeof (FPGM(bci_deltap2
))
7054 + sizeof (FPGM(bci_deltap3
))
7056 + sizeof (FPGM(bci_create_segments_composite_a
))
7058 + sizeof (FPGM(bci_create_segments_composite_b
))
7059 + (font
->control_data_head
!= 0
7060 ? sizeof (FPGM(bci_create_segments_composite_c
))
7062 + sizeof (FPGM(bci_create_segments_composite_d
))
7064 + sizeof (FPGM(bci_create_segments_composite_0
))
7065 + sizeof (FPGM(bci_create_segments_composite_1
))
7066 + sizeof (FPGM(bci_create_segments_composite_2
))
7067 + sizeof (FPGM(bci_create_segments_composite_3
))
7068 + sizeof (FPGM(bci_create_segments_composite_4
))
7069 + sizeof (FPGM(bci_create_segments_composite_5
))
7070 + sizeof (FPGM(bci_create_segments_composite_6
))
7071 + sizeof (FPGM(bci_create_segments_composite_7
))
7072 + sizeof (FPGM(bci_create_segments_composite_8
))
7073 + sizeof (FPGM(bci_create_segments_composite_9
))
7075 + sizeof (FPGM(bci_align_point
))
7076 + sizeof (FPGM(bci_align_segment
))
7077 + sizeof (FPGM(bci_align_segments
))
7079 + sizeof (FPGM(bci_scale_contour
))
7080 + sizeof (FPGM(bci_scale_glyph_a
))
7082 + sizeof (FPGM(bci_scale_glyph_b
))
7083 + sizeof (FPGM(bci_scale_composite_glyph_a
))
7085 + sizeof (FPGM(bci_scale_composite_glyph_b
))
7086 + sizeof (FPGM(bci_shift_contour
))
7087 + sizeof (FPGM(bci_shift_subglyph_a
))
7089 + sizeof (FPGM(bci_shift_subglyph_b
))
7090 + (font
->control_data_head
!= 0
7091 ? sizeof (FPGM(bci_shift_subglyph_c
))
7093 + sizeof (FPGM(bci_shift_subglyph_d
))
7095 + sizeof (FPGM(bci_ip_outer_align_point
))
7096 + sizeof (FPGM(bci_ip_on_align_points
))
7097 + sizeof (FPGM(bci_ip_between_align_point
))
7098 + sizeof (FPGM(bci_ip_between_align_points
))
7100 + sizeof (FPGM(bci_adjust_common
))
7101 + sizeof (FPGM(bci_stem_common
))
7102 + sizeof (FPGM(bci_serif_common
))
7103 + sizeof (FPGM(bci_serif_anchor_common
))
7104 + sizeof (FPGM(bci_serif_link1_common
))
7105 + sizeof (FPGM(bci_serif_link2_common
))
7107 + sizeof (FPGM(bci_lower_bound
))
7108 + sizeof (FPGM(bci_upper_bound
))
7109 + sizeof (FPGM(bci_upper_lower_bound
))
7111 + sizeof (FPGM(bci_adjust_bound
))
7112 + sizeof (FPGM(bci_stem_bound
))
7113 + sizeof (FPGM(bci_link
))
7114 + sizeof (FPGM(bci_anchor
))
7115 + sizeof (FPGM(bci_adjust
))
7116 + sizeof (FPGM(bci_stem
))
7118 + sizeof (FPGM(bci_action_ip_before
))
7119 + sizeof (FPGM(bci_action_ip_after
))
7120 + sizeof (FPGM(bci_action_ip_on
))
7121 + sizeof (FPGM(bci_action_ip_between
))
7123 + sizeof (FPGM(bci_action_blue
))
7124 + sizeof (FPGM(bci_action_blue_anchor
))
7126 + sizeof (FPGM(bci_action_anchor
))
7127 + sizeof (FPGM(bci_action_anchor_serif
))
7128 + sizeof (FPGM(bci_action_anchor_round
))
7129 + sizeof (FPGM(bci_action_anchor_round_serif
))
7131 + sizeof (FPGM(bci_action_adjust
))
7132 + sizeof (FPGM(bci_action_adjust_serif
))
7133 + sizeof (FPGM(bci_action_adjust_round
))
7134 + sizeof (FPGM(bci_action_adjust_round_serif
))
7135 + sizeof (FPGM(bci_action_adjust_bound
))
7136 + sizeof (FPGM(bci_action_adjust_bound_serif
))
7137 + sizeof (FPGM(bci_action_adjust_bound_round
))
7138 + sizeof (FPGM(bci_action_adjust_bound_round_serif
))
7139 + sizeof (FPGM(bci_action_adjust_down_bound
))
7140 + sizeof (FPGM(bci_action_adjust_down_bound_serif
))
7141 + sizeof (FPGM(bci_action_adjust_down_bound_round
))
7142 + sizeof (FPGM(bci_action_adjust_down_bound_round_serif
))
7144 + sizeof (FPGM(bci_action_link
))
7145 + sizeof (FPGM(bci_action_link_serif
))
7146 + sizeof (FPGM(bci_action_link_round
))
7147 + sizeof (FPGM(bci_action_link_round_serif
))
7149 + sizeof (FPGM(bci_action_stem
))
7150 + sizeof (FPGM(bci_action_stem_serif
))
7151 + sizeof (FPGM(bci_action_stem_round
))
7152 + sizeof (FPGM(bci_action_stem_round_serif
))
7153 + sizeof (FPGM(bci_action_stem_bound
))
7154 + sizeof (FPGM(bci_action_stem_bound_serif
))
7155 + sizeof (FPGM(bci_action_stem_bound_round
))
7156 + sizeof (FPGM(bci_action_stem_bound_round_serif
))
7157 + sizeof (FPGM(bci_action_stem_down_bound
))
7158 + sizeof (FPGM(bci_action_stem_down_bound_serif
))
7159 + sizeof (FPGM(bci_action_stem_down_bound_round
))
7160 + sizeof (FPGM(bci_action_stem_down_bound_round_serif
))
7162 + sizeof (FPGM(bci_action_serif
))
7163 + sizeof (FPGM(bci_action_serif_lower_bound
))
7164 + sizeof (FPGM(bci_action_serif_upper_bound
))
7165 + sizeof (FPGM(bci_action_serif_upper_lower_bound
))
7166 + sizeof (FPGM(bci_action_serif_down_lower_bound
))
7167 + sizeof (FPGM(bci_action_serif_down_upper_bound
))
7168 + sizeof (FPGM(bci_action_serif_down_upper_lower_bound
))
7170 + sizeof (FPGM(bci_action_serif_anchor
))
7171 + sizeof (FPGM(bci_action_serif_anchor_lower_bound
))
7172 + sizeof (FPGM(bci_action_serif_anchor_upper_bound
))
7173 + sizeof (FPGM(bci_action_serif_anchor_upper_lower_bound
))
7174 + sizeof (FPGM(bci_action_serif_anchor_down_lower_bound
))
7175 + sizeof (FPGM(bci_action_serif_anchor_down_upper_bound
))
7176 + sizeof (FPGM(bci_action_serif_anchor_down_upper_lower_bound
))
7178 + sizeof (FPGM(bci_action_serif_link1
))
7179 + sizeof (FPGM(bci_action_serif_link1_lower_bound
))
7180 + sizeof (FPGM(bci_action_serif_link1_upper_bound
))
7181 + sizeof (FPGM(bci_action_serif_link1_upper_lower_bound
))
7182 + sizeof (FPGM(bci_action_serif_link1_down_lower_bound
))
7183 + sizeof (FPGM(bci_action_serif_link1_down_upper_bound
))
7184 + sizeof (FPGM(bci_action_serif_link1_down_upper_lower_bound
))
7186 + sizeof (FPGM(bci_action_serif_link2
))
7187 + sizeof (FPGM(bci_action_serif_link2_lower_bound
))
7188 + sizeof (FPGM(bci_action_serif_link2_upper_bound
))
7189 + sizeof (FPGM(bci_action_serif_link2_upper_lower_bound
))
7190 + sizeof (FPGM(bci_action_serif_link2_down_lower_bound
))
7191 + sizeof (FPGM(bci_action_serif_link2_down_upper_bound
))
7192 + sizeof (FPGM(bci_action_serif_link2_down_upper_lower_bound
))
7194 + sizeof (FPGM(bci_hint_glyph
));
7196 /* buffer length must be a multiple of four */
7197 len
= (buf_len
+ 3) & ~3U;
7198 buf
= (FT_Byte
*)malloc(len
);
7200 return FT_Err_Out_Of_Memory
;
7202 /* pad end of buffer with zeros */
7203 buf
[len
- 1] = 0x00;
7204 buf
[len
- 2] = 0x00;
7205 buf
[len
- 3] = 0x00;
7207 /* copy font program into buffer and fill in the missing variables */
7210 COPY_FPGM(bci_align_x_height_a
);
7211 if (font
->increase_x_height
)
7213 COPY_FPGM(bci_align_x_height_b1a
);
7214 *(bufp
++) = HIGH(font
->increase_x_height
);
7215 *(bufp
++) = LOW(font
->increase_x_height
);
7216 COPY_FPGM(bci_align_x_height_b1b
);
7219 COPY_FPGM(bci_align_x_height_b2
);
7220 COPY_FPGM(bci_align_x_height_c
);
7222 COPY_FPGM(bci_round
);
7223 COPY_FPGM(bci_natural_stem_width
);
7224 COPY_FPGM(bci_quantize_stem_width
);
7225 COPY_FPGM(bci_smooth_stem_width
);
7226 COPY_FPGM(bci_get_best_width
);
7227 COPY_FPGM(bci_strong_stem_width_a
);
7228 *(bufp
++) = num_used_styles
;
7229 COPY_FPGM(bci_strong_stem_width_b
);
7230 COPY_FPGM(bci_loop_do
);
7231 COPY_FPGM(bci_loop
);
7232 COPY_FPGM(bci_cvt_rescale
);
7233 COPY_FPGM(bci_cvt_rescale_range
);
7234 COPY_FPGM(bci_vwidth_data_store
);
7235 COPY_FPGM(bci_smooth_blue_round
);
7236 COPY_FPGM(bci_strong_blue_round
);
7237 COPY_FPGM(bci_blue_round_range
);
7238 COPY_FPGM(bci_decrement_component_counter
);
7239 COPY_FPGM(bci_get_point_extrema
);
7240 COPY_FPGM(bci_nibbles
);
7241 COPY_FPGM(bci_number_set_is_element
);
7242 COPY_FPGM(bci_number_set_is_element2
);
7244 COPY_FPGM(bci_create_segment
);
7245 COPY_FPGM(bci_create_segments_a
);
7246 *(bufp
++) = num_used_styles
;
7247 COPY_FPGM(bci_create_segments_b
);
7248 if (font
->control_data_head
)
7249 COPY_FPGM(bci_create_segments_c
);
7250 COPY_FPGM(bci_create_segments_d
);
7252 COPY_FPGM(bci_create_segments_0
);
7253 COPY_FPGM(bci_create_segments_1
);
7254 COPY_FPGM(bci_create_segments_2
);
7255 COPY_FPGM(bci_create_segments_3
);
7256 COPY_FPGM(bci_create_segments_4
);
7257 COPY_FPGM(bci_create_segments_5
);
7258 COPY_FPGM(bci_create_segments_6
);
7259 COPY_FPGM(bci_create_segments_7
);
7260 COPY_FPGM(bci_create_segments_8
);
7261 COPY_FPGM(bci_create_segments_9
);
7263 COPY_FPGM(bci_deltap1
);
7264 COPY_FPGM(bci_deltap2
);
7265 COPY_FPGM(bci_deltap3
);
7267 COPY_FPGM(bci_create_segments_composite_a
);
7268 *(bufp
++) = num_used_styles
;
7269 COPY_FPGM(bci_create_segments_composite_b
);
7270 if (font
->control_data_head
)
7271 COPY_FPGM(bci_create_segments_composite_c
);
7272 COPY_FPGM(bci_create_segments_composite_d
);
7274 COPY_FPGM(bci_create_segments_composite_0
);
7275 COPY_FPGM(bci_create_segments_composite_1
);
7276 COPY_FPGM(bci_create_segments_composite_2
);
7277 COPY_FPGM(bci_create_segments_composite_3
);
7278 COPY_FPGM(bci_create_segments_composite_4
);
7279 COPY_FPGM(bci_create_segments_composite_5
);
7280 COPY_FPGM(bci_create_segments_composite_6
);
7281 COPY_FPGM(bci_create_segments_composite_7
);
7282 COPY_FPGM(bci_create_segments_composite_8
);
7283 COPY_FPGM(bci_create_segments_composite_9
);
7285 COPY_FPGM(bci_align_point
);
7286 COPY_FPGM(bci_align_segment
);
7287 COPY_FPGM(bci_align_segments
);
7289 COPY_FPGM(bci_scale_contour
);
7290 COPY_FPGM(bci_scale_glyph_a
);
7291 *(bufp
++) = fallback_style
;
7292 COPY_FPGM(bci_scale_glyph_b
);
7293 COPY_FPGM(bci_scale_composite_glyph_a
);
7294 *(bufp
++) = fallback_style
;
7295 COPY_FPGM(bci_scale_composite_glyph_b
);
7296 COPY_FPGM(bci_shift_contour
);
7297 COPY_FPGM(bci_shift_subglyph_a
);
7298 *(bufp
++) = fallback_style
;
7299 COPY_FPGM(bci_shift_subglyph_b
);
7300 if (font
->control_data_head
)
7301 COPY_FPGM(bci_shift_subglyph_c
);
7302 COPY_FPGM(bci_shift_subglyph_d
);
7304 COPY_FPGM(bci_ip_outer_align_point
);
7305 COPY_FPGM(bci_ip_on_align_points
);
7306 COPY_FPGM(bci_ip_between_align_point
);
7307 COPY_FPGM(bci_ip_between_align_points
);
7309 COPY_FPGM(bci_adjust_common
);
7310 COPY_FPGM(bci_stem_common
);
7311 COPY_FPGM(bci_serif_common
);
7312 COPY_FPGM(bci_serif_anchor_common
);
7313 COPY_FPGM(bci_serif_link1_common
);
7314 COPY_FPGM(bci_serif_link2_common
);
7316 COPY_FPGM(bci_lower_bound
);
7317 COPY_FPGM(bci_upper_bound
);
7318 COPY_FPGM(bci_upper_lower_bound
);
7320 COPY_FPGM(bci_adjust_bound
);
7321 COPY_FPGM(bci_stem_bound
);
7322 COPY_FPGM(bci_link
);
7323 COPY_FPGM(bci_anchor
);
7324 COPY_FPGM(bci_adjust
);
7325 COPY_FPGM(bci_stem
);
7327 COPY_FPGM(bci_action_ip_before
);
7328 COPY_FPGM(bci_action_ip_after
);
7329 COPY_FPGM(bci_action_ip_on
);
7330 COPY_FPGM(bci_action_ip_between
);
7332 COPY_FPGM(bci_action_blue
);
7333 COPY_FPGM(bci_action_blue_anchor
);
7335 COPY_FPGM(bci_action_anchor
);
7336 COPY_FPGM(bci_action_anchor_serif
);
7337 COPY_FPGM(bci_action_anchor_round
);
7338 COPY_FPGM(bci_action_anchor_round_serif
);
7340 COPY_FPGM(bci_action_adjust
);
7341 COPY_FPGM(bci_action_adjust_serif
);
7342 COPY_FPGM(bci_action_adjust_round
);
7343 COPY_FPGM(bci_action_adjust_round_serif
);
7344 COPY_FPGM(bci_action_adjust_bound
);
7345 COPY_FPGM(bci_action_adjust_bound_serif
);
7346 COPY_FPGM(bci_action_adjust_bound_round
);
7347 COPY_FPGM(bci_action_adjust_bound_round_serif
);
7348 COPY_FPGM(bci_action_adjust_down_bound
);
7349 COPY_FPGM(bci_action_adjust_down_bound_serif
);
7350 COPY_FPGM(bci_action_adjust_down_bound_round
);
7351 COPY_FPGM(bci_action_adjust_down_bound_round_serif
);
7353 COPY_FPGM(bci_action_link
);
7354 COPY_FPGM(bci_action_link_serif
);
7355 COPY_FPGM(bci_action_link_round
);
7356 COPY_FPGM(bci_action_link_round_serif
);
7358 COPY_FPGM(bci_action_stem
);
7359 COPY_FPGM(bci_action_stem_serif
);
7360 COPY_FPGM(bci_action_stem_round
);
7361 COPY_FPGM(bci_action_stem_round_serif
);
7362 COPY_FPGM(bci_action_stem_bound
);
7363 COPY_FPGM(bci_action_stem_bound_serif
);
7364 COPY_FPGM(bci_action_stem_bound_round
);
7365 COPY_FPGM(bci_action_stem_bound_round_serif
);
7366 COPY_FPGM(bci_action_stem_down_bound
);
7367 COPY_FPGM(bci_action_stem_down_bound_serif
);
7368 COPY_FPGM(bci_action_stem_down_bound_round
);
7369 COPY_FPGM(bci_action_stem_down_bound_round_serif
);
7371 COPY_FPGM(bci_action_serif
);
7372 COPY_FPGM(bci_action_serif_lower_bound
);
7373 COPY_FPGM(bci_action_serif_upper_bound
);
7374 COPY_FPGM(bci_action_serif_upper_lower_bound
);
7375 COPY_FPGM(bci_action_serif_down_lower_bound
);
7376 COPY_FPGM(bci_action_serif_down_upper_bound
);
7377 COPY_FPGM(bci_action_serif_down_upper_lower_bound
);
7379 COPY_FPGM(bci_action_serif_anchor
);
7380 COPY_FPGM(bci_action_serif_anchor_lower_bound
);
7381 COPY_FPGM(bci_action_serif_anchor_upper_bound
);
7382 COPY_FPGM(bci_action_serif_anchor_upper_lower_bound
);
7383 COPY_FPGM(bci_action_serif_anchor_down_lower_bound
);
7384 COPY_FPGM(bci_action_serif_anchor_down_upper_bound
);
7385 COPY_FPGM(bci_action_serif_anchor_down_upper_lower_bound
);
7387 COPY_FPGM(bci_action_serif_link1
);
7388 COPY_FPGM(bci_action_serif_link1_lower_bound
);
7389 COPY_FPGM(bci_action_serif_link1_upper_bound
);
7390 COPY_FPGM(bci_action_serif_link1_upper_lower_bound
);
7391 COPY_FPGM(bci_action_serif_link1_down_lower_bound
);
7392 COPY_FPGM(bci_action_serif_link1_down_upper_bound
);
7393 COPY_FPGM(bci_action_serif_link1_down_upper_lower_bound
);
7395 COPY_FPGM(bci_action_serif_link2
);
7396 COPY_FPGM(bci_action_serif_link2_lower_bound
);
7397 COPY_FPGM(bci_action_serif_link2_upper_bound
);
7398 COPY_FPGM(bci_action_serif_link2_upper_lower_bound
);
7399 COPY_FPGM(bci_action_serif_link2_down_lower_bound
);
7400 COPY_FPGM(bci_action_serif_link2_down_upper_bound
);
7401 COPY_FPGM(bci_action_serif_link2_down_upper_lower_bound
);
7403 COPY_FPGM(bci_hint_glyph
);
7406 *fpgm_len
= buf_len
;
7413 TA_sfnt_build_fpgm_table(SFNT
* sfnt
,
7418 SFNT_Table
* glyf_table
= &font
->tables
[sfnt
->glyf_idx
];
7419 glyf_Data
* data
= (glyf_Data
*)glyf_table
->data
;
7425 error
= TA_sfnt_add_table_info(sfnt
);
7429 /* `glyf', `cvt', `fpgm', and `prep' are always used in parallel */
7430 if (glyf_table
->processed
)
7432 sfnt
->table_infos
[sfnt
->num_table_infos
- 1] = data
->fpgm_idx
;
7436 error
= TA_table_build_fpgm(&fpgm_buf
, &fpgm_len
, sfnt
, font
);
7440 if (fpgm_len
> sfnt
->max_instructions
)
7441 sfnt
->max_instructions
= (FT_UShort
)fpgm_len
;
7443 /* in case of success, `fpgm_buf' gets linked */
7444 /* and is eventually freed in `TA_font_unload' */
7445 error
= TA_font_add_table(font
,
7446 &sfnt
->table_infos
[sfnt
->num_table_infos
- 1],
7447 TTAG_fpgm
, fpgm_len
, fpgm_buf
);
7451 data
->fpgm_idx
= sfnt
->table_infos
[sfnt
->num_table_infos
- 1];
7457 /* end of tafpgm.c */