4 * Copyright (C) 2011-2012 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 \
41 #define MD_orig_ZP2_1 \
51 /* a convenience shorthand for scaling; see `bci_cvt_rescale' for details */
57 MUL, /* delta * 2^10 */ \
65 /* in the comments below, the top of the stack (`s:') */
66 /* is the rightmost element; the stack is shown */
67 /* after the instruction on the same line has been executed */
73 * Round a 26.6 number. Contrary to the ROUND bytecode instruction, no
74 * engine specific corrections are applied.
80 unsigned char FPGM(bci_round
) [] =
98 * bci_smooth_stem_width
100 * This is the equivalent to the following code from function
101 * `ta_latin_compute_stem_width':
109 * else if base_is_round:
115 * delta = ABS(dist - std_width)
126 * delta = delta - dist
129 * dist = dist + delta
130 * else if delta < 32:
132 * else if delta < 54:
135 * dist = dist + delta
151 * CVT: cvtl_is_extra_light
155 unsigned char FPGM(bci_smooth_stem_width_a
) [] =
159 bci_smooth_stem_width
,
163 ABS
, /* s: base_is_round stem_is_serif width dist */
168 LT
, /* dist < 3*64 */
172 MINDEX
, /* s: base_is_round width dist (dist<3*64) stem_is_serif */
173 AND
, /* stem_is_serif && dist < 3*64 */
178 OR
, /* (stem_is_serif && dist < 3*64) || is_extra_light */
180 IF
, /* s: base_is_round width dist */
186 ROLL
, /* s: width dist base_is_round */
187 IF
, /* s: width dist */
192 IF
, /* s: width dist */
203 IF
, /* s: width dist */
210 DUP
, /* s: width dist dist */
215 /* %c, index of std_width */
217 unsigned char FPGM(bci_smooth_stem_width_b
) [] =
222 ABS
, /* s: width dist delta */
227 IF
, /* s: width dist */
233 /* %c, index of std_width */
235 unsigned char FPGM(bci_smooth_stem_width_c
) [] =
238 RCVT
, /* dist = std_width */
250 DUP
, /* s: width dist dist */
253 LT
, /* dist < 3*64 */
255 DUP
, /* s: width delta dist */
256 FLOOR
, /* dist = FLOOR(dist) */
257 DUP
, /* s: width delta dist dist */
259 ROLL
, /* s: width dist delta dist */
260 SUB
, /* delta = delta - dist */
262 DUP
, /* s: width dist delta delta */
266 IF
, /* s: width dist delta */
267 ADD
, /* dist = dist + delta */
278 ADD
, /* dist = dist + 10 */
289 ADD
, /* dist = dist + 54 */
292 ADD
, /* dist = dist + delta */
301 CALL
, /* dist = round(dist) */
306 SWAP
, /* s: dist width */
311 NEG
, /* dist = -dist */
323 * An auxiliary function for `bci_strong_stem_width'.
325 * in: n (initialized with CVT index for first vertical width)
337 unsigned char FPGM(bci_get_best_width
) [] =
345 RCVT
, /* s: dist n w */
349 CINDEX
, /* s: dist n w w dist */
351 ABS
, /* s: dist n w d */
355 RS
, /* s: dist n w d d best */
365 WS
, /* reference = w */
382 * bci_strong_stem_width
384 * This is the equivalent to the following code (function
385 * `ta_latin_snap_width' and some lines from
386 * `ta_latin_compute_stem_width'):
388 * best = 64 + 32 + 2;
392 * for n in 0 .. num_widths:
400 * if dist >= reference:
401 * if dist < ROUND(reference) + 48:
404 * if dist > ROUND(reference) - 48:
417 * stem_is_serif (unused)
418 * base_is_round (unused)
425 unsigned char FPGM(bci_strong_stem_width_a
) [] =
429 bci_strong_stem_width
,
437 ABS
, /* s: width dist */
442 WS
, /* sal_best = 98 */
448 WS
, /* sal_ref = width */
453 /* %c, first index of vertical widths */
454 /* %c, number of vertical widths */
456 unsigned char FPGM(bci_strong_stem_width_b
) [] =
462 POP
, /* s: width dist */
466 RS
, /* s: width dist dist reference */
473 CALL
, /* s: width dist reference dist dist ROUND(reference) */
478 ROLL
, /* s: width dist reference dist ROUND(reference) 48 reference dist */
480 LTEQ
, /* dist >= reference */
481 IF
, /* s: width dist reference dist ROUND(reference) 48 */
483 LT
, /* dist < ROUND(reference) + 48 */
487 GT
, /* dist > ROUND(reference) - 48 */
491 SWAP
, /* s: width reference dist */
498 GTEQ
, /* dist >= 64 */
502 CALL
, /* dist = ROUND(dist) */
510 SWAP
, /* s: dist width */
515 NEG
, /* dist = -dist */
526 * Take a range and a function number and apply the function to all
527 * elements of the range.
533 * sal: sal_i (counter initialized with `start')
535 * sal_func (`func_num')
538 unsigned char FPGM(bci_loop
) [] =
548 WS
, /* sal_func = func_num */
552 WS
, /* sal_limit = end */
556 WS
, /* sal_i = start */
565 LTEQ
, /* start <= end */
576 ADD
, /* start = start + 1 */
582 JMPR
, /* goto start_loop */
593 * Rescale CVT value by `cvtl_scale' (in 16.16 format).
595 * The scaling factor `cvtl_scale' isn't stored as `b/c' but as `(b-c)/c';
596 * consequently, the calculation `a * b/c' is done as `a + delta' with
597 * `delta = a * (b-c)/c'. This avoids overflow.
599 * sal: sal_i (CVT index)
605 unsigned char FPGM(bci_cvt_rescale
) [] =
628 * Round a blue ref value and adjust its corresponding shoot value.
630 * sal: sal_i (CVT index)
634 unsigned char FPGM(bci_blue_round_a
) [] =
645 RCVT
, /* s: ref_idx ref */
651 SWAP
, /* s: ref_idx round(ref) ref */
659 unsigned char FPGM(bci_blue_round_b
) [] =
664 ADD
, /* s: ref_idx round(ref) ref shoot_idx */
666 RCVT
, /* s: ref_idx round(ref) ref shoot_idx shoot */
668 ROLL
, /* s: ref_idx round(ref) shoot_idx shoot ref */
670 SUB
, /* s: ref_idx round(ref) shoot_idx dist */
672 ABS
, /* s: ref_idx round(ref) shoot_idx dist delta */
697 SWAP
, /* s: ref_idx round(ref) shoot_idx delta dist */
702 NEG
, /* delta = -delta */
709 SUB
, /* s: ref_idx round(ref) shoot_idx (round(ref) - delta) */
720 * bci_decrement_component_counter
722 * An auxiliary function for composite glyphs.
724 * CVT: cvtl_is_subglyph
727 unsigned char FPGM(bci_decrement_component_counter
) [] =
731 bci_decrement_component_counter
,
734 /* decrement `cvtl_is_subglyph' counter */
750 * bci_get_point_extrema
752 * An auxiliary function for `bci_create_segment'.
761 unsigned char FPGM(bci_get_point_extrema
) [] =
765 bci_get_point_extrema
,
774 /* check whether `point' is a new minimum */
777 RS
, /* s: point point point point_min */
779 /* if distance is negative, we have a new minimum */
783 IF
, /* s: point point */
791 /* check whether `point' is a new maximum */
794 RS
, /* s: point point point_max */
796 /* if distance is positive, we have a new maximum */
816 * Pop a byte with two delta arguments in its nibbles and push the
817 * expanded arguments separately as two bytes.
819 * in: 16 * (end - start) + (start - base)
824 * sal: sal_base (set to `end' at return)
828 unsigned char FPGM(bci_nibbles
) [] =
838 DIV
, /* s: in hnibble */
843 MUL
, /* s: in hnibble (hnibble * 16) */
846 SUB
, /* s: hnibble lnibble */
851 ADD
, /* s: hnibble start */
854 ADD
, /* s: start end */
860 WS
, /* sal_base = end */
870 * bci_number_set_is_element
872 * Pop values from stack until it is empty. If one of them is equal to
873 * the current PPEM value, set `cvtl_is_element' to 1 (and to 0
880 * CVT: cvtl_is_element
883 unsigned char FPGM(bci_number_set_is_element
) [] =
887 bci_number_set_is_element
,
909 JROT
, /* goto start_loop if stack depth != 0 */
917 * bci_number_set_is_element2
919 * Pop value ranges from stack until it is empty. If one of them contains
920 * the current PPEM value, set `cvtl_is_element' to 1 (and to 0
923 * in: ppem_range_1_start
929 * CVT: cvtl_is_element
932 unsigned char FPGM(bci_number_set_is_element2
) [] =
936 bci_number_set_is_element2
,
964 JROT
, /* goto start_loop if stack depth != 0 */
974 * Store start and end point of a segment in the storage area,
975 * then construct a point in the twilight zone to represent it.
977 * This function is used by `bci_create_segment_points'.
981 * [last (if wrap-around segment)]
982 * [first (if wrap-around segment)]
984 * uses: bci_get_point_extrema
987 * sal: sal_i (start of current segment)
988 * sal_j (current twilight point)
992 * sal_num_packed_segments
998 * If `sal_num_packed_segments' is > 0, the start/end pair is stored as
999 * delta values in nibbles (without a wrap-around segment).
1002 unsigned char FPGM(bci_create_segment
) [] =
1011 sal_num_packed_segments
,
1016 sal_num_packed_segments
,
1017 sal_num_packed_segments
,
1022 WS
, /* sal_num_packed_segments = sal_num_packed_segments - 1 */
1035 WS
, /* sal[sal_i] = start */
1037 /* increase `sal_i'; together with the outer loop, this makes sal_i += 2 */
1043 ADD
, /* sal_i = sal_i + 1 */
1046 /* initialize inner loop(s) */
1051 WS
, /* sal_point_min = start */
1056 WS
, /* sal_point_max = start */
1060 SZPS
, /* set zp0, zp1, and zp2 to normal zone 1 */
1066 CINDEX
, /* s: start end end start */
1067 LT
, /* start > end */
1069 /* we have a wrap-around segment with two more arguments */
1070 /* to give the last and first point of the contour, respectively; */
1071 /* our job is to store a segment `start'-`last', */
1072 /* and to get extrema for the two segments */
1073 /* `start'-`last' and `first'-`end' */
1075 /* s: first last start end */
1082 WS
, /* sal[sal_i] = last */
1085 ROLL
, /* s: first end last start */
1088 SWAP
, /* s: first end start last start */
1089 SUB
, /* s: first end start loop_count */
1092 bci_get_point_extrema
,
1094 /* clean up stack */
1097 SWAP
, /* s: end first */
1102 ROLL
, /* s: (first - 1) (first - 1) end */
1104 SUB
, /* s: (first - 1) loop_count */
1107 bci_get_point_extrema
,
1109 /* clean up stack */
1112 ELSE
, /* s: start end */
1119 WS
, /* sal[sal_i] = end */
1124 SUB
, /* s: start loop_count */
1127 bci_get_point_extrema
,
1129 /* clean up stack */
1133 /* the twilight point representing a segment */
1134 /* is in the middle between the minimum and maximum */
1146 DIV
, /* s: middle_pos */
1148 DO_SCALE
, /* middle_pos = middle_pos * scale */
1150 /* write it to temporary CVT location */
1154 SZP0
, /* set zp0 to twilight zone 0 */
1158 /* create twilight point with index `sal_j' */
1171 ADD
, /* twilight_point = twilight_point + 1 */
1180 * bci_create_segments
1182 * This is the top-level entry function.
1184 * It pops point ranges from the stack to define segments, computes
1185 * twilight points to represent segments, and finally calls
1186 * `bci_hint_glyph' to handle the rest.
1188 * in: num_packed_segments
1192 * [contour_last 0 (if wrap-around segment)]
1193 * [contour_first 0 (if wrap-around segment)]
1196 * [contour_last 0 (if wrap-around segment)]
1197 * [contour_first 0 (if wrap-around segment)]
1199 * segment_start_(N-1)
1201 * [contour_last (N-1) (if wrap-around segment)]
1202 * [contour_first (N-1) (if wrap-around segment)]
1203 * ... stuff for bci_hint_glyph ...
1205 * uses: bci_create_segment
1207 * sal: sal_i (start of current segment)
1208 * sal_j (current twilight point)
1209 * sal_num_packed_segments
1210 * sal_base (the base for delta values in nibbles)
1212 * CVT: cvtl_is_subglyph
1214 * If `num_packed_segments' is set to p, the first p start/end pairs are
1215 * stored as delta values in nibbles, with the `start' delta in the lower
1216 * nibble (and there are no wrap-around segments). For example, if the
1217 * first three pairs are 1/3, 5/8, and 12/13, the topmost three bytes on the
1218 * stack are 0x21, 0x32, and 0x14.
1222 unsigned char FPGM(bci_create_segments
) [] =
1226 bci_create_segments
,
1229 /* only do something if we are not a subglyph */
1236 /* all our measurements are taken along the y axis */
1240 sal_num_packed_segments
,
1248 SUB
, /* delta = (2*num_segments - 1) */
1258 WS
, /* sal_base = 0 */
1259 WS
, /* sal_j = 0 (point offset) */
1262 ADD
, /* s: ... sal_segment_offset (sal_segment_offset + delta) */
1264 /* `bci_create_segment_point' also increases the loop counter by 1; */
1265 /* this effectively means we have a loop step of 2 */
1285 * bci_create_segments_X
1287 * Top-level routines for calling `bci_create_segments'.
1290 unsigned char FPGM(bci_create_segments_0
) [] =
1294 bci_create_segments_0
,
1299 bci_create_segments
,
1306 unsigned char FPGM(bci_create_segments_1
) [] =
1310 bci_create_segments_1
,
1315 bci_create_segments
,
1322 unsigned char FPGM(bci_create_segments_2
) [] =
1326 bci_create_segments_2
,
1331 bci_create_segments
,
1338 unsigned char FPGM(bci_create_segments_3
) [] =
1342 bci_create_segments_3
,
1347 bci_create_segments
,
1354 unsigned char FPGM(bci_create_segments_4
) [] =
1358 bci_create_segments_4
,
1363 bci_create_segments
,
1370 unsigned char FPGM(bci_create_segments_5
) [] =
1374 bci_create_segments_5
,
1379 bci_create_segments
,
1386 unsigned char FPGM(bci_create_segments_6
) [] =
1390 bci_create_segments_6
,
1395 bci_create_segments
,
1402 unsigned char FPGM(bci_create_segments_7
) [] =
1406 bci_create_segments_7
,
1411 bci_create_segments
,
1418 unsigned char FPGM(bci_create_segments_8
) [] =
1422 bci_create_segments_8
,
1427 bci_create_segments
,
1434 unsigned char FPGM(bci_create_segments_9
) [] =
1438 bci_create_segments_9
,
1443 bci_create_segments
,
1452 * bci_create_segments_composite
1454 * The same as `bci_create_segments'.
1455 * It also decrements the composite component counter.
1457 * uses: bci_decrement_composite_counter
1459 * CVT: cvtl_is_subglyph
1462 unsigned char FPGM(bci_create_segments_composite
) [] =
1466 bci_create_segments_composite
,
1470 bci_decrement_component_counter
,
1473 /* only do something if we are not a subglyph */
1480 /* all our measurements are taken along the y axis */
1484 sal_num_packed_segments
,
1492 SUB
, /* delta = (2*num_segments - 1) */
1502 WS
, /* sal_base = 0 */
1503 WS
, /* sal_j = 0 (point offset) */
1506 ADD
, /* s: ... sal_segment_offset (sal_segment_offset + delta) */
1508 /* `bci_create_segment_point' also increases the loop counter by 1; */
1509 /* this effectively means we have a loop step of 2 */
1529 * bci_create_segments_composite_X
1531 * Top-level routines for calling `bci_create_segments_composite'.
1534 unsigned char FPGM(bci_create_segments_composite_0
) [] =
1538 bci_create_segments_composite_0
,
1543 bci_create_segments_composite
,
1550 unsigned char FPGM(bci_create_segments_composite_1
) [] =
1554 bci_create_segments_composite_1
,
1559 bci_create_segments_composite
,
1566 unsigned char FPGM(bci_create_segments_composite_2
) [] =
1570 bci_create_segments_composite_2
,
1575 bci_create_segments_composite
,
1582 unsigned char FPGM(bci_create_segments_composite_3
) [] =
1586 bci_create_segments_composite_3
,
1591 bci_create_segments_composite
,
1598 unsigned char FPGM(bci_create_segments_composite_4
) [] =
1602 bci_create_segments_composite_4
,
1607 bci_create_segments_composite
,
1614 unsigned char FPGM(bci_create_segments_composite_5
) [] =
1618 bci_create_segments_composite_5
,
1623 bci_create_segments_composite
,
1630 unsigned char FPGM(bci_create_segments_composite_6
) [] =
1634 bci_create_segments_composite_6
,
1639 bci_create_segments_composite
,
1646 unsigned char FPGM(bci_create_segments_composite_7
) [] =
1650 bci_create_segments_composite_7
,
1655 bci_create_segments_composite
,
1662 unsigned char FPGM(bci_create_segments_composite_8
) [] =
1666 bci_create_segments_composite_8
,
1671 bci_create_segments_composite
,
1678 unsigned char FPGM(bci_create_segments_composite_9
) [] =
1682 bci_create_segments_composite_9
,
1687 bci_create_segments_composite
,
1698 * Align all points in a segment to the twilight point in rp0.
1699 * zp0 and zp1 must be set to 0 (twilight) and 1 (normal), respectively.
1704 unsigned char FPGM(bci_align_segment
) [] =
1711 /* we need the values of `sal_segment_offset + 2*segment_index' */
1712 /* and `sal_segment_offset + 2*segment_index + 1' */
1724 RS
, /* s: first last */
1729 CINDEX
, /* s: first last first */
1732 CINDEX
, /* s: first last first last */
1733 LTEQ
, /* first <= end */
1734 IF
, /* s: first last */
1736 DUP
, /* s: last first first */
1737 ALIGNRP
, /* align point with index `first' with rp0 */
1741 ADD
, /* first = first + 1 */
1742 SWAP
, /* s: first last */
1747 JMPR
, /* goto start_loop */
1760 * bci_align_segments
1762 * Align segments to the twilight point in rp0.
1763 * zp0 and zp1 must be set to 0 (twilight) and 1 (normal), respectively.
1772 * uses: handle_segment
1776 unsigned char FPGM(bci_align_segments
) [] =
1799 * Scale a contour using two points giving the maximum and minimum
1802 * It expects that no point on the contour is touched.
1811 unsigned char FPGM(bci_scale_contour
) [] =
1822 DO_SCALE
, /* min_pos_new = min_pos * scale */
1827 /* don't scale a single-point contour twice */
1836 DO_SCALE
, /* max_pos_new = max_pos * scale */
1853 * Scale a glyph using a list of points (two points per contour, giving
1854 * the maximum and mininum coordinates).
1856 * It expects that no point in the glyph is touched.
1858 * Note that the point numbers are sorted in ascending order;
1859 * `min_point_X' and `max_point_X' thus refer to the two extrema of a
1860 * contour without specifying which one is the minimum and maximum.
1862 * in: num_contours (N)
1871 * uses: bci_scale_contour
1873 * CVT: cvtl_is_subglyph
1876 unsigned char FPGM(bci_scale_glyph
) [] =
1883 /* only do something if we are not a subglyph */
1890 /* all our measurements are taken along the y axis */
1895 SZPS
, /* set zp0, zp1, and zp2 to normal zone 1 */
1903 SZP2
, /* set zp2 to normal zone 1 */
1916 * bci_scale_composite_glyph
1918 * The same as `bci_scale_composite_glyph'.
1919 * It also decrements the composite component counter.
1921 * uses: bci_decrement_component_counter
1923 * CVT: cvtl_is_subglyph
1926 unsigned char FPGM(bci_scale_composite_glyph
) [] =
1930 bci_scale_composite_glyph
,
1934 bci_decrement_component_counter
,
1937 /* only do something if we are not a subglyph */
1944 /* all our measurements are taken along the y axis */
1949 SZPS
, /* set zp0, zp1, and zp2 to normal zone 1 */
1957 SZP2
, /* set zp2 to normal zone 1 */
1972 * Shift a contour by a given amount.
1974 * It expects that rp1 (pointed to by zp0) is set up properly; zp2 must
1975 * point to the normal zone 1.
1981 unsigned char FPGM(bci_shift_contour
) [] =
1989 SHC_rp1
, /* shift `contour' by (rp1_pos - rp1_orig_pos) */
2001 * bci_shift_subglyph
2003 * Shift a subglyph. To be more specific, it corrects the already applied
2004 * subglyph offset (if any) from the `glyf' table which needs to be scaled
2007 * If this function is called, a point `x' in the subglyph has been scaled
2008 * already (during the hinting of the subglyph itself), and `offset' has
2009 * been applied also:
2011 * x -> x * scale + offset (1)
2013 * However, the offset should be applied first, then the scaling:
2015 * x -> (x + offset) * scale (2)
2017 * Our job is now to transform (1) to (2); a simple calculation shows that
2018 * we have to shift all points of the subglyph by
2020 * offset * scale - offset = offset * (scale - 1)
2022 * Note that `cvtl_scale' is equal to the above `scale - 1'.
2024 * in: offset (in FUnits)
2028 * CVT: cvtl_funits_to_pixels
2033 unsigned char FPGM(bci_shift_subglyph
) [] =
2043 cvtl_funits_to_pixels
,
2044 RCVT
, /* scaling factor FUnits -> pixels */
2051 /* the autohinter always rounds offsets */
2054 CALL
, /* offset = round(offset) */
2063 DIV
, /* delta = offset * (scale - 1) */
2065 /* and round again */
2068 CALL
, /* offset = round(offset) */
2072 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
2074 /* we create twilight point 0 as a reference point, */
2075 /* setting the original position to zero (using `cvtl_temp') */
2083 MIAP_noround
, /* rp0 and rp1 now point to twilight point 0 */
2085 SWAP
, /* s: first_contour num_contours 0 delta */
2086 SHPIX
, /* rp1_pos - rp1_orig_pos = delta */
2091 SZP2
, /* set zp2 to normal zone 1 */
2100 * bci_ip_outer_align_point
2102 * Auxiliary function for `bci_action_ip_before' and
2103 * `bci_action_ip_after'.
2105 * It expects rp0 to contain the edge for alignment, zp0 set to twilight
2106 * zone, and both zp1 and zp2 set to normal zone.
2110 * sal: sal_i (edge_orig_pos)
2116 unsigned char FPGM(bci_ip_outer_align_point
) [] =
2120 bci_ip_outer_align_point
,
2124 ALIGNRP
, /* align `point' with `edge' */
2127 DO_SCALE
, /* point_orig_pos = point_orig_pos * scale */
2132 SUB
, /* s: point (point_orig_pos - edge_orig_pos) */
2141 * bci_ip_on_align_points
2143 * Auxiliary function for `bci_action_ip_on'.
2145 * in: edge (in twilight zone)
2153 unsigned char FPGM(bci_ip_on_align_points
) [] =
2157 bci_ip_on_align_points
,
2160 MDAP_noround
, /* set rp0 and rp1 to `edge' */
2171 * bci_ip_between_align_point
2173 * Auxiliary function for `bci_ip_between_align_points'.
2175 * It expects rp0 to contain the edge for alignment, zp0 set to twilight
2176 * zone, and both zp1 and zp2 set to normal zone.
2180 * sal: sal_i (edge_orig_pos)
2181 * sal_j (stretch_factor)
2187 unsigned char FPGM(bci_ip_between_align_point
) [] =
2191 bci_ip_between_align_point
,
2195 ALIGNRP
, /* align `point' with `edge' */
2198 DO_SCALE
, /* point_orig_pos = point_orig_pos * scale */
2203 SUB
, /* s: point (point_orig_pos - edge_orig_pos) */
2207 MUL
, /* s: point delta */
2216 * bci_ip_between_align_points
2218 * Auxiliary function for `bci_action_ip_between'.
2220 * in: after_edge (in twilight zone)
2221 * before_edge (in twilight zone)
2228 * sal: sal_i (before_orig_pos)
2229 * sal_j (stretch_factor)
2231 * uses: bci_ip_between_align_point
2234 unsigned char FPGM(bci_ip_between_align_points
) [] =
2238 bci_ip_between_align_points
,
2244 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
2246 DUP
, /* s: ... before after before before */
2247 MDAP_noround
, /* set rp0 and rp1 to `before' */
2249 GC_orig
, /* s: ... before after before before_orig_pos */
2253 WS
, /* sal_i = before_orig_pos */
2256 CINDEX
, /* s: ... before after before after */
2257 MD_cur
, /* b = after_pos - before_pos */
2260 MD_orig_ZP2_0
, /* a = after_orig_pos - before_orig_pos */
2265 WS
, /* sal_j = stretch_factor */
2268 bci_ip_between_align_point
,
2271 SZP2
, /* set zp2 to normal zone 1 */
2272 SZP1
, /* set zp1 to normal zone 1 */
2281 * bci_action_ip_before
2283 * Handle `ip_before' data to align points located before the first edge.
2285 * in: first_edge (in twilight zone)
2292 * sal: sal_i (first_edge_orig_pos)
2294 * uses: bci_ip_outer_align_point
2297 unsigned char FPGM(bci_action_ip_before
) [] =
2301 bci_action_ip_before
,
2306 SZP2
, /* set zp2 to twilight zone 0 */
2313 WS
, /* sal_i = first_edge_orig_pos */
2319 SZP2
, /* set zp2 to normal zone 1 */
2320 SZP1
, /* set zp1 to normal zone 1 */
2321 SZP0
, /* set zp0 to twilight zone 0 */
2323 MDAP_noround
, /* set rp0 and rp1 to `first_edge' */
2326 bci_ip_outer_align_point
,
2335 * bci_action_ip_after
2337 * Handle `ip_after' data to align points located after the last edge.
2339 * in: last_edge (in twilight zone)
2346 * sal: sal_i (last_edge_orig_pos)
2348 * uses: bci_ip_outer_align_point
2351 unsigned char FPGM(bci_action_ip_after
) [] =
2355 bci_action_ip_after
,
2360 SZP2
, /* set zp2 to twilight zone 0 */
2367 WS
, /* sal_i = last_edge_orig_pos */
2373 SZP2
, /* set zp2 to normal zone 1 */
2374 SZP1
, /* set zp1 to normal zone 1 */
2375 SZP0
, /* set zp0 to twilight zone 0 */
2377 MDAP_noround
, /* set rp0 and rp1 to `last_edge' */
2380 bci_ip_outer_align_point
,
2391 * Handle `ip_on' data to align points located on an edge coordinate (but
2392 * not part of an edge).
2394 * in: loop_counter (M)
2395 * edge_1 (in twilight zone)
2396 * loop_counter (N_1)
2401 * edge_2 (in twilight zone)
2402 * loop_counter (N_2)
2408 * edge_M (in twilight zone)
2409 * loop_counter (N_M)
2415 * uses: bci_ip_on_align_points
2418 unsigned char FPGM(bci_action_ip_on
) [] =
2428 SZP1
, /* set zp1 to normal zone 1 */
2429 SZP0
, /* set zp0 to twilight zone 0 */
2432 bci_ip_on_align_points
,
2441 * bci_action_ip_between
2443 * Handle `ip_between' data to align points located between two edges.
2445 * in: loop_counter (M)
2446 * before_edge_1 (in twilight zone)
2447 * after_edge_1 (in twilight zone)
2448 * loop_counter (N_1)
2453 * before_edge_2 (in twilight zone)
2454 * after_edge_2 (in twilight zone)
2455 * loop_counter (N_2)
2461 * before_edge_M (in twilight zone)
2462 * after_edge_M (in twilight zone)
2463 * loop_counter (N_M)
2469 * uses: bci_ip_between_align_points
2472 unsigned char FPGM(bci_action_ip_between
) [] =
2476 bci_action_ip_between
,
2480 bci_ip_between_align_points
,
2491 * Common code for bci_action_adjust routines.
2494 unsigned char FPGM(bci_adjust_common
) [] =
2503 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
2507 CINDEX
, /* s: [...] edge2 edge is_round is_serif edge2 */
2510 CINDEX
, /* s: [...] edge2 edge is_round is_serif edge2 edge */
2511 MD_orig_ZP2_0
, /* s: [...] edge2 edge is_round is_serif org_len */
2514 cvtl_stem_width_function
,
2517 NEG
, /* s: [...] edge2 edge -cur_len */
2519 ROLL
, /* s: [...] edge -cur_len edge2 */
2520 MDAP_noround
, /* set rp0 and rp1 to `edge2' */
2523 DUP
, /* s: [...] -cur_len edge edge edge */
2524 ALIGNRP
, /* align `edge' with `edge2' */
2526 SHPIX
, /* shift `edge' by -cur_len */
2536 * Handle the ADJUST_BOUND action to align an edge of a stem if the other
2537 * edge of the stem has already been moved, then moving it again if
2538 * necessary to stay bound.
2540 * in: edge2_is_serif
2542 * edge_point (in twilight zone)
2543 * edge2_point (in twilight zone)
2544 * edge[-1] (in twilight zone)
2545 * ... stuff for bci_align_segments (edge) ...
2547 * uses: bci_adjust_common
2550 unsigned char FPGM(bci_adjust_bound
) [] =
2561 SWAP
, /* s: edge edge[-1] */
2563 MDAP_noround
, /* set rp0 and rp1 to `edge[-1]' */
2568 GC_cur
, /* s: edge edge[-1]_pos edge_pos */
2569 GT
, /* edge_pos < edge[-1]_pos */
2572 ALIGNRP
, /* align `edge' to `edge[-1]' */
2575 MDAP_noround
, /* set rp0 and rp1 to `edge' */
2580 SZP1
, /* set zp1 to normal zone 1 */
2589 * bci_action_adjust_bound
2590 * bci_action_adjust_bound_serif
2591 * bci_action_adjust_bound_round
2592 * bci_action_adjust_bound_round_serif
2594 * Higher-level routines for calling `bci_adjust_bound'.
2597 unsigned char FPGM(bci_action_adjust_bound
) [] =
2601 bci_action_adjust_bound
,
2614 unsigned char FPGM(bci_action_adjust_bound_serif
) [] =
2618 bci_action_adjust_bound_serif
,
2631 unsigned char FPGM(bci_action_adjust_bound_round
) [] =
2635 bci_action_adjust_bound_round
,
2648 unsigned char FPGM(bci_action_adjust_bound_round_serif
) [] =
2652 bci_action_adjust_bound_round_serif
,
2669 * Handle the ADJUST action to align an edge of a stem if the other edge
2670 * of the stem has already been moved.
2672 * in: edge2_is_serif
2674 * edge_point (in twilight zone)
2675 * edge2_point (in twilight zone)
2676 * ... stuff for bci_align_segments (edge) ...
2678 * uses: bci_adjust_common
2681 unsigned char FPGM(bci_adjust
) [] =
2692 MDAP_noround
, /* set rp0 and rp1 to `edge' */
2697 SZP1
, /* set zp1 to normal zone 1 */
2707 * bci_action_adjust_serif
2708 * bci_action_adjust_round
2709 * bci_action_adjust_round_serif
2711 * Higher-level routines for calling `bci_adjust'.
2714 unsigned char FPGM(bci_action_adjust
) [] =
2731 unsigned char FPGM(bci_action_adjust_serif
) [] =
2735 bci_action_adjust_serif
,
2748 unsigned char FPGM(bci_action_adjust_round
) [] =
2752 bci_action_adjust_round
,
2765 unsigned char FPGM(bci_action_adjust_round_serif
) [] =
2769 bci_action_adjust_round_serif
,
2786 * Common code for bci_action_stem routines.
2790 #define sal_u_off sal_temp1
2792 #define sal_d_off sal_temp2
2794 #define sal_org_len sal_temp3
2796 #define sal_edge2 sal_temp3
2798 unsigned char FPGM(bci_stem_common
) [] =
2807 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
2815 DUP
, /* s: [...] edge2 edge is_round is_serif edge2 edge edge */
2816 MDAP_noround
, /* set rp0 and rp1 to `edge_point' (for ALIGNRP below) */
2818 MD_orig_ZP2_0
, /* s: [...] edge2 edge is_round is_serif org_len */
2826 cvtl_stem_width_function
,
2828 CALL
, /* s: [...] edge2 edge cur_len */
2833 LT
, /* cur_len < 96 */
2838 LTEQ
, /* cur_len <= 64 */
2856 SWAP
, /* s: [...] edge2 cur_len edge */
2861 DUP
, /* s: [...] edge2 cur_len edge edge anchor anchor */
2867 ADD
, /* s: [...] edge2 cur_len edge org_pos */
2874 ADD
, /* s: [...] edge2 cur_len edge org_center */
2879 CALL
, /* s: [...] edge2 cur_len edge org_center cur_pos1 */
2884 SUB
, /* s: ... cur_len edge cur_pos1 (org_center - cur_pos1) */
2891 ABS
, /* s: ... cur_len edge cur_pos1 (org_center - cur_pos1) delta1 */
2898 ABS
, /* s: [...] edge2 cur_len edge cur_pos1 delta1 delta2 */
2900 LT
, /* delta1 < delta2 */
2905 SUB
, /* cur_pos1 = cur_pos1 - u_off */
2911 ADD
, /* cur_pos1 = cur_pos1 + d_off */
2912 EIF
, /* s: [...] edge2 cur_len edge cur_pos1 */
2920 SUB
, /* arg = cur_pos1 - cur_len/2 */
2922 SWAP
, /* s: [...] edge2 cur_len arg edge */
2928 SWAP
, /* s: [...] edge2 cur_len edge edge arg edge */
2931 SHPIX
, /* edge = cur_pos1 - cur_len/2 */
2934 SWAP
, /* s: [...] edge2 cur_len edge */
2938 GC_cur
, /* s: [...] edge2 cur_len edge anchor_pos */
2946 ADD
, /* s: [...] edge2 cur_len edge org_pos */
2955 ADD
, /* s: [...] edge2 cur_len edge org_pos org_center */
2961 CALL
, /* cur_pos1 = ROUND(org_pos) */
2973 SUB
, /* s: [...] edge2 cur_len edge org_center cur_pos1 cur_pos2 */
2984 SUB
, /* s: ... cur_len edge cur_pos1 cur_pos2 (cur_len/2 - org_center) */
2991 ABS
, /* delta1 = ABS(cur_pos1 + cur_len / 2 - org_center) */
2997 ABS
, /* s: ... edge2 cur_len edge cur_pos1 cur_pos2 delta1 delta2 */
2998 LT
, /* delta1 < delta2 */
3000 POP
, /* arg = cur_pos1 */
3004 POP
, /* arg = cur_pos2 */
3005 EIF
, /* s: [...] edge2 cur_len edge arg */
3012 SWAP
, /* s: [...] edge2 cur_len edge edge arg edge */
3015 SHPIX
, /* edge = arg */
3016 EIF
, /* s: [...] edge2 cur_len edge */
3026 * Handle the STEM action to align two edges of a stem, then moving one
3027 * edge again if necessary to stay bound.
3029 * The code after computing `cur_len' to shift `edge' and `edge2'
3030 * is equivalent to the snippet below (part of `ta_latin_hint_edges'):
3033 * if cur_len < = 64:
3040 * org_pos = anchor + (edge_orig - anchor_orig);
3041 * org_center = org_pos + org_len / 2;
3043 * cur_pos1 = ROUND(org_center)
3044 * delta1 = ABS(org_center - (cur_pos1 - u_off))
3045 * delta2 = ABS(org_center - (cur_pos1 + d_off))
3046 * if (delta1 < delta2):
3047 * cur_pos1 = cur_pos1 - u_off
3049 * cur_pos1 = cur_pos1 + d_off
3051 * edge = cur_pos1 - cur_len / 2
3054 * org_pos = anchor + (edge_orig - anchor_orig)
3055 * org_center = org_pos + org_len / 2;
3057 * cur_pos1 = ROUND(org_pos)
3058 * delta1 = ABS(cur_pos1 + cur_len / 2 - org_center)
3059 * cur_pos2 = ROUND(org_pos + org_len) - cur_len
3060 * delta2 = ABS(cur_pos2 + cur_len / 2 - org_center)
3062 * if (delta1 < delta2):
3067 * edge2 = edge + cur_len
3069 * in: edge2_is_serif
3071 * edge_point (in twilight zone)
3072 * edge2_point (in twilight zone)
3073 * edge[-1] (in twilight zone)
3074 * ... stuff for bci_align_segments (edge) ...
3075 * ... stuff for bci_align_segments (edge2)...
3082 * uses: bci_stem_common
3085 unsigned char FPGM(bci_stem_bound
) [] =
3096 ROLL
, /* s: edge[-1] cur_len edge edge2 */
3099 ALIGNRP
, /* align `edge2' with rp0 (still `edge') */
3103 WS
, /* s: edge[-1] cur_len edge edge2 */
3105 SHPIX
, /* edge2 = edge + cur_len */
3107 SWAP
, /* s: edge edge[-1] */
3109 MDAP_noround
, /* set rp0 and rp1 to `edge[-1]' */
3114 GC_cur
, /* s: edge edge[-1]_pos edge_pos */
3115 GT
, /* edge_pos < edge[-1]_pos */
3118 ALIGNRP
, /* align `edge' to `edge[-1]' */
3121 MDAP_noround
, /* set rp0 and rp1 to `edge' */
3126 SZP1
, /* set zp1 to normal zone 1 */
3132 MDAP_noround
, /* set rp0 and rp1 to `edge2' */
3144 * bci_action_stem_bound
3145 * bci_action_stem_bound_serif
3146 * bci_action_stem_bound_round
3147 * bci_action_stem_bound_round_serif
3149 * Higher-level routines for calling `bci_stem_bound'.
3152 unsigned char FPGM(bci_action_stem_bound
) [] =
3156 bci_action_stem_bound
,
3169 unsigned char FPGM(bci_action_stem_bound_serif
) [] =
3173 bci_action_stem_bound_serif
,
3186 unsigned char FPGM(bci_action_stem_bound_round
) [] =
3190 bci_action_stem_bound_round
,
3203 unsigned char FPGM(bci_action_stem_bound_round_serif
) [] =
3207 bci_action_stem_bound_round_serif
,
3224 * Handle the STEM action to align two edges of a stem.
3226 * See `bci_stem_bound' for more details.
3228 * in: edge2_is_serif
3230 * edge_point (in twilight zone)
3231 * edge2_point (in twilight zone)
3232 * ... stuff for bci_align_segments (edge) ...
3233 * ... stuff for bci_align_segments (edge2)...
3240 * uses: bci_stem_common
3243 unsigned char FPGM(bci_stem
) [] =
3255 SWAP
, /* s: cur_len edge2 */
3258 ALIGNRP
, /* align `edge2' with rp0 (still `edge') */
3262 WS
, /* s: cur_len edge2 */
3264 SHPIX
, /* edge2 = edge + cur_len */
3269 SZP1
, /* set zp1 to normal zone 1 */
3275 MDAP_noround
, /* set rp0 and rp1 to `edge2' */
3287 * bci_action_stem_serif
3288 * bci_action_stem_round
3289 * bci_action_stem_round_serif
3291 * Higher-level routines for calling `bci_stem'.
3294 unsigned char FPGM(bci_action_stem
) [] =
3311 unsigned char FPGM(bci_action_stem_serif
) [] =
3315 bci_action_stem_serif
,
3328 unsigned char FPGM(bci_action_stem_round
) [] =
3332 bci_action_stem_round
,
3345 unsigned char FPGM(bci_action_stem_round_serif
) [] =
3349 bci_action_stem_round_serif
,
3366 * Handle the LINK action to link an edge to another one.
3370 * base_point (in twilight zone)
3371 * stem_point (in twilight zone)
3372 * ... stuff for bci_align_segments (base) ...
3375 unsigned char FPGM(bci_link
) [] =
3384 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
3392 DUP
, /* s: stem is_round is_serif stem base base */
3393 MDAP_noround
, /* set rp0 and rp1 to `base_point' (for ALIGNRP below) */
3395 MD_orig_ZP2_0
, /* s: stem is_round is_serif dist_orig */
3398 cvtl_stem_width_function
,
3400 CALL
, /* s: stem new_dist */
3404 ALIGNRP
, /* align `stem_point' with `base_point' */
3406 MDAP_noround
, /* set rp0 and rp1 to `stem_point' */
3408 SHPIX
, /* stem_point = base_point + new_dist */
3413 SZP1
, /* set zp1 to normal zone 1 */
3423 * bci_action_link_serif
3424 * bci_action_link_round
3425 * bci_action_link_round_serif
3427 * Higher-level routines for calling `bci_link'.
3430 unsigned char FPGM(bci_action_link
) [] =
3447 unsigned char FPGM(bci_action_link_serif
) [] =
3451 bci_action_link_serif
,
3464 unsigned char FPGM(bci_action_link_round
) [] =
3468 bci_action_link_round
,
3481 unsigned char FPGM(bci_action_link_round_serif
) [] =
3485 bci_action_link_round_serif
,
3502 * Handle the ANCHOR action to align two edges
3503 * and to set the edge anchor.
3505 * The code after computing `cur_len' to shift `edge' and `edge2'
3506 * is equivalent to the snippet below (part of `ta_latin_hint_edges'):
3509 * if cur_len < = 64:
3516 * org_center = edge_orig + org_len / 2
3517 * cur_pos1 = ROUND(org_center)
3519 * error1 = ABS(org_center - (cur_pos1 - u_off))
3520 * error2 = ABS(org_center - (cur_pos1 + d_off))
3521 * if (error1 < error2):
3522 * cur_pos1 = cur_pos1 - u_off
3524 * cur_pos1 = cur_pos1 + d_off
3526 * edge = cur_pos1 - cur_len / 2
3527 * edge2 = edge + cur_len
3530 * edge = ROUND(edge_orig)
3532 * in: edge2_is_serif
3534 * edge_point (in twilight zone)
3535 * edge2_point (in twilight zone)
3536 * ... stuff for bci_align_segments (edge) ...
3545 #define sal_u_off sal_temp1
3547 #define sal_d_off sal_temp2
3549 #define sal_org_len sal_temp3
3551 unsigned char FPGM(bci_anchor
) [] =
3558 /* store anchor point number in `sal_anchor' */
3563 WS
, /* sal_anchor = edge_point */
3567 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
3575 DUP
, /* s: edge2 edge is_round is_serif edge2 edge edge */
3576 MDAP_noround
, /* set rp0 and rp1 to `edge_point' (for ALIGNRP below) */
3578 MD_orig_ZP2_0
, /* s: edge2 edge is_round is_serif org_len */
3586 cvtl_stem_width_function
,
3588 CALL
, /* s: edge2 edge cur_len */
3593 LT
, /* cur_len < 96 */
3598 LTEQ
, /* cur_len <= 64 */
3616 SWAP
, /* s: edge2 cur_len edge */
3617 DUP
, /* s: edge2 cur_len edge edge */
3626 ADD
, /* s: edge2 cur_len edge org_center */
3631 CALL
, /* s: edge2 cur_len edge org_center cur_pos1 */
3636 SUB
, /* s: edge2 cur_len edge cur_pos1 (org_center - cur_pos1) */
3643 ABS
, /* s: edge2 cur_len edge cur_pos1 (org_center - cur_pos1) error1 */
3650 ABS
, /* s: edge2 cur_len edge cur_pos1 error1 error2 */
3652 LT
, /* error1 < error2 */
3657 SUB
, /* cur_pos1 = cur_pos1 - u_off */
3663 ADD
, /* cur_pos1 = cur_pos1 + d_off */
3664 EIF
, /* s: edge2 cur_len edge cur_pos1 */
3672 SUB
, /* s: edge2 cur_len edge (cur_pos1 - cur_len/2) */
3676 CINDEX
, /* s: edge2 cur_len edge (cur_pos1 - cur_len/2) edge */
3679 SHPIX
, /* edge = cur_pos1 - cur_len/2 */
3681 SWAP
, /* s: cur_len edge2 */
3683 ALIGNRP
, /* align `edge2' with rp0 (still `edge') */
3685 SHPIX
, /* edge2 = edge1 + cur_len */
3688 POP
, /* s: edge2 edge */
3696 CALL
, /* s: edge2 edge edge_pos round(edge_orig_pos) */
3699 SHPIX
, /* edge = round(edge_orig) */
3701 /* clean up stack */
3708 SZP1
, /* set zp1 to normal zone 1 */
3718 * bci_action_anchor_serif
3719 * bci_action_anchor_round
3720 * bci_action_anchor_round_serif
3722 * Higher-level routines for calling `bci_anchor'.
3725 unsigned char FPGM(bci_action_anchor
) [] =
3742 unsigned char FPGM(bci_action_anchor_serif
) [] =
3746 bci_action_anchor_serif
,
3759 unsigned char FPGM(bci_action_anchor_round
) [] =
3763 bci_action_anchor_round
,
3776 unsigned char FPGM(bci_action_anchor_round_serif
) [] =
3780 bci_action_anchor_round_serif
,
3795 * bci_action_blue_anchor
3797 * Handle the BLUE_ANCHOR action to align an edge with a blue zone
3798 * and to set the edge anchor.
3800 * in: anchor_point (in twilight zone)
3802 * edge_point (in twilight zone)
3803 * ... stuff for bci_align_segments (edge) ...
3807 * uses: bci_action_blue
3810 unsigned char FPGM(bci_action_blue_anchor
) [] =
3814 bci_action_blue_anchor
,
3817 /* store anchor point number in `sal_anchor' */
3835 * Handle the BLUE action to align an edge with a blue zone.
3838 * edge_point (in twilight zone)
3839 * ... stuff for bci_align_segments (edge) ...
3842 unsigned char FPGM(bci_action_blue
) [] =
3851 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
3853 /* move `edge_point' to `blue_cvt_idx' position; */
3854 /* note that we can't use MIAP since this would modify */
3855 /* the twilight point's original coordinates also */
3859 MDAP_noround
, /* set rp0 and rp1 to `edge' */
3861 GC_cur
, /* s: new_pos edge edge_pos */
3864 SUB
, /* s: edge (new_pos - edge_pos) */
3870 SZP1
, /* set zp1 to normal zone 1 */
3881 * Common code for bci_action_serif routines.
3884 unsigned char FPGM(bci_serif_common
) [] =
3893 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
3900 MINDEX
, /* s: [...] serif serif serif serif base */
3902 MDAP_noround
, /* set rp0 and rp1 to `base_point' */
3905 ALIGNRP
, /* align `serif_point' with `base_point' */
3906 SHPIX
, /* serif = base + (serif_orig_pos - base_orig_pos) */
3916 * Move an edge if necessary to stay within a lower bound.
3922 unsigned char FPGM(bci_lower_bound
) [] =
3929 SWAP
, /* s: edge bound */
3931 MDAP_noround
, /* set rp0 and rp1 to `bound' */
3936 GC_cur
, /* s: edge bound_pos edge_pos */
3937 GT
, /* edge_pos < bound_pos */
3940 ALIGNRP
, /* align `edge' to `bound' */
3943 MDAP_noround
, /* set rp0 and rp1 to `edge_point' */
3948 SZP1
, /* set zp1 to normal zone 1 */
3959 * Move an edge if necessary to stay within an upper bound.
3965 unsigned char FPGM(bci_upper_bound
) [] =
3972 SWAP
, /* s: edge bound */
3974 MDAP_noround
, /* set rp0 and rp1 to `bound' */
3979 GC_cur
, /* s: edge bound_pos edge_pos */
3980 LT
, /* edge_pos > bound_pos */
3983 ALIGNRP
, /* align `edge' to `bound' */
3986 MDAP_noround
, /* set rp0 and rp1 to `edge_point' */
3991 SZP1
, /* set zp1 to normal zone 1 */
4000 * bci_upper_lower_bound
4002 * Move an edge if necessary to stay within a lower and lower bound.
4009 unsigned char FPGM(bci_upper_lower_bound
) [] =
4013 bci_upper_lower_bound
,
4016 SWAP
, /* s: upper serif lower */
4018 MDAP_noround
, /* set rp0 and rp1 to `lower' */
4023 GC_cur
, /* s: upper serif lower_pos serif_pos */
4024 GT
, /* serif_pos < lower_pos */
4027 ALIGNRP
, /* align `serif' to `lower' */
4030 SWAP
, /* s: serif upper */
4032 MDAP_noround
, /* set rp0 and rp1 to `upper' */
4037 GC_cur
, /* s: serif upper_pos serif_pos */
4038 LT
, /* serif_pos > upper_pos */
4041 ALIGNRP
, /* align `serif' to `upper' */
4044 MDAP_noround
, /* set rp0 and rp1 to `serif_point' */
4049 SZP1
, /* set zp1 to normal zone 1 */
4060 * Handle the SERIF action to align a serif with its base.
4062 * in: serif_point (in twilight zone)
4063 * base_point (in twilight zone)
4064 * ... stuff for bci_align_segments (serif) ...
4066 * uses: bci_serif_common
4069 unsigned char FPGM(bci_action_serif
) [] =
4080 MDAP_noround
, /* set rp0 and rp1 to `serif_point' */
4085 SZP1
, /* set zp1 to normal zone 1 */
4094 * bci_action_serif_lower_bound
4096 * Handle the SERIF action to align a serif with its base, then moving it
4097 * again if necessary to stay within a lower bound.
4099 * in: serif_point (in twilight zone)
4100 * base_point (in twilight zone)
4101 * edge[-1] (in twilight zone)
4102 * ... stuff for bci_align_segments (serif) ...
4104 * uses: bci_serif_common
4108 unsigned char FPGM(bci_action_serif_lower_bound
) [] =
4112 bci_action_serif_lower_bound
,
4129 * bci_action_serif_upper_bound
4131 * Handle the SERIF action to align a serif with its base, then moving it
4132 * again if necessary to stay within an upper bound.
4134 * in: serif_point (in twilight zone)
4135 * base_point (in twilight zone)
4136 * edge[1] (in twilight zone)
4137 * ... stuff for bci_align_segments (serif) ...
4139 * uses: bci_serif_common
4143 unsigned char FPGM(bci_action_serif_upper_bound
) [] =
4147 bci_action_serif_upper_bound
,
4164 * bci_action_serif_upper_lower_bound
4166 * Handle the SERIF action to align a serif with its base, then moving it
4167 * again if necessary to stay within a lower and upper bound.
4169 * in: serif_point (in twilight zone)
4170 * base_point (in twilight zone)
4171 * edge[-1] (in twilight zone)
4172 * edge[1] (in twilight zone)
4173 * ... stuff for bci_align_segments (serif) ...
4175 * uses: bci_serif_common
4176 * bci_upper_lower_bound
4179 unsigned char FPGM(bci_action_serif_upper_lower_bound
) [] =
4183 bci_action_serif_upper_lower_bound
,
4188 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
4195 bci_upper_lower_bound
,
4204 * bci_serif_anchor_common
4206 * Common code for bci_action_serif_anchor routines.
4209 unsigned char FPGM(bci_serif_anchor_common
) [] =
4213 bci_serif_anchor_common
,
4218 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
4224 WS
, /* sal_anchor = edge_point */
4234 CALL
, /* s: [...] edge edge edge_pos round(edge_orig_pos) */
4237 SHPIX
, /* edge = round(edge_orig) */
4245 * bci_action_serif_anchor
4247 * Handle the SERIF_ANCHOR action to align a serif and to set the edge
4250 * in: edge_point (in twilight zone)
4251 * ... stuff for bci_align_segments (edge) ...
4253 * uses: bci_serif_anchor_common
4256 unsigned char FPGM(bci_action_serif_anchor
) [] =
4260 bci_action_serif_anchor
,
4264 bci_serif_anchor_common
,
4267 MDAP_noround
, /* set rp0 and rp1 to `edge' */
4272 SZP1
, /* set zp1 to normal zone 1 */
4281 * bci_action_serif_anchor_lower_bound
4283 * Handle the SERIF_ANCHOR action to align a serif and to set the edge
4284 * anchor, then moving it again if necessary to stay within a lower
4287 * in: edge_point (in twilight zone)
4288 * edge[-1] (in twilight zone)
4289 * ... stuff for bci_align_segments (edge) ...
4291 * uses: bci_serif_anchor_common
4295 unsigned char FPGM(bci_action_serif_anchor_lower_bound
) [] =
4299 bci_action_serif_anchor_lower_bound
,
4303 bci_serif_anchor_common
,
4316 * bci_action_serif_anchor_upper_bound
4318 * Handle the SERIF_ANCHOR action to align a serif and to set the edge
4319 * anchor, then moving it again if necessary to stay within an upper
4322 * in: edge_point (in twilight zone)
4323 * edge[1] (in twilight zone)
4324 * ... stuff for bci_align_segments (edge) ...
4326 * uses: bci_serif_anchor_common
4330 unsigned char FPGM(bci_action_serif_anchor_upper_bound
) [] =
4334 bci_action_serif_anchor_upper_bound
,
4338 bci_serif_anchor_common
,
4351 * bci_action_serif_anchor_upper_lower_bound
4353 * Handle the SERIF_ANCHOR action to align a serif and to set the edge
4354 * anchor, then moving it again if necessary to stay within a lower and
4357 * in: edge_point (in twilight zone)
4358 * edge[-1] (in twilight zone)
4359 * edge[1] (in twilight zone)
4360 * ... stuff for bci_align_segments (edge) ...
4362 * uses: bci_serif_anchor_common
4363 * bci_upper_lower_bound
4366 unsigned char FPGM(bci_action_serif_anchor_upper_lower_bound
) [] =
4370 bci_action_serif_anchor_upper_lower_bound
,
4374 bci_serif_anchor_common
,
4378 bci_upper_lower_bound
,
4387 * bci_serif_link1_common
4389 * Common code for bci_action_serif_link1 routines.
4392 unsigned char FPGM(bci_serif_link1_common
) [] =
4396 bci_serif_link1_common
,
4401 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
4405 CINDEX
, /* s: [...] after edge before after */
4408 CINDEX
, /* s: [...] after edge before after before */
4412 EQ
, /* after_orig_pos == before_orig_pos */
4413 IF
, /* s: [...] after edge before */
4414 MDAP_noround
, /* set rp0 and rp1 to `before' */
4416 ALIGNRP
, /* align `edge' with `before' */
4421 /* we have to execute `a*b/c', with b/c very near to 1: */
4422 /* to avoid overflow while retaining precision, */
4423 /* we transform this to `a + a * (b-c)/c' */
4427 CINDEX
, /* s: [...] after edge before edge */
4430 CINDEX
, /* s: [...] after edge before edge before */
4431 MD_orig_ZP2_0
, /* a = edge_orig_pos - before_orig_pos */
4436 CINDEX
, /* s: [...] after edge before a a after */
4439 CINDEX
, /* s: [...] after edge before a a after before */
4440 MD_orig_ZP2_0
, /* c = after_orig_pos - before_orig_pos */
4444 CINDEX
, /* s: [...] after edge before a a c after */
4447 CINDEX
, /* s: [...] after edge before a a c after before */
4448 MD_cur
, /* b = after_pos - before_pos */
4452 CINDEX
, /* s: [...] after edge before a a c b c */
4458 MUL
, /* (b-c) in 16.16 format */
4460 DIV
, /* s: [...] after edge before a a (b-c)/c */
4462 MUL
, /* a * (b-c)/c * 2^10 */
4466 DIV
, /* a * (b-c)/c */
4470 MDAP_noround
, /* set rp0 and rp1 to `before' */
4471 SWAP
, /* s: [...] after a*b/c edge */
4474 ALIGNRP
, /* align `edge' with `before' */
4476 SHPIX
, /* shift `edge' by `a*b/c' */
4478 SWAP
, /* s: [...] edge after */
4488 * bci_action_serif_link1
4490 * Handle the SERIF_LINK1 action to align a serif, depending on edges
4493 * in: before_point (in twilight zone)
4494 * edge_point (in twilight zone)
4495 * after_point (in twilight zone)
4496 * ... stuff for bci_align_segments (edge) ...
4498 * uses: bci_serif_link1_common
4501 unsigned char FPGM(bci_action_serif_link1
) [] =
4505 bci_action_serif_link1
,
4509 bci_serif_link1_common
,
4512 MDAP_noround
, /* set rp0 and rp1 to `edge' */
4517 SZP1
, /* set zp1 to normal zone 1 */
4526 * bci_action_serif_link1_lower_bound
4528 * Handle the SERIF_LINK1 action to align a serif, depending on edges
4529 * before and after. Additionally, move the serif again if necessary to
4530 * stay within a lower bound.
4532 * in: before_point (in twilight zone)
4533 * edge_point (in twilight zone)
4534 * after_point (in twilight zone)
4535 * edge[-1] (in twilight zone)
4536 * ... stuff for bci_align_segments (edge) ...
4538 * uses: bci_serif_link1_common
4542 unsigned char FPGM(bci_action_serif_link1_lower_bound
) [] =
4546 bci_action_serif_link1_lower_bound
,
4550 bci_serif_link1_common
,
4563 * bci_action_serif_link1_upper_bound
4565 * Handle the SERIF_LINK1 action to align a serif, depending on edges
4566 * before and after. Additionally, move the serif again if necessary to
4567 * stay within an upper bound.
4569 * in: before_point (in twilight zone)
4570 * edge_point (in twilight zone)
4571 * after_point (in twilight zone)
4572 * edge[1] (in twilight zone)
4573 * ... stuff for bci_align_segments (edge) ...
4575 * uses: bci_serif_link1_common
4579 unsigned char FPGM(bci_action_serif_link1_upper_bound
) [] =
4583 bci_action_serif_link1_upper_bound
,
4587 bci_serif_link1_common
,
4600 * bci_action_serif_link1_upper_lower_bound
4602 * Handle the SERIF_LINK1 action to align a serif, depending on edges
4603 * before and after. Additionally, move the serif again if necessary to
4604 * stay within a lower and upper bound.
4606 * in: before_point (in twilight zone)
4607 * edge_point (in twilight zone)
4608 * after_point (in twilight zone)
4609 * edge[-1] (in twilight zone)
4610 * edge[1] (in twilight zone)
4611 * ... stuff for bci_align_segments (edge) ...
4613 * uses: bci_serif_link1_common
4614 * bci_upper_lower_bound
4617 unsigned char FPGM(bci_action_serif_link1_upper_lower_bound
) [] =
4621 bci_action_serif_link1_upper_lower_bound
,
4625 bci_serif_link1_common
,
4629 bci_upper_lower_bound
,
4638 * bci_serif_link2_common
4640 * Common code for bci_action_serif_link2 routines.
4643 unsigned char FPGM(bci_serif_link2_common
) [] =
4647 bci_serif_link2_common
,
4652 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
4654 DUP
, /* s: [...] edge edge */
4658 DUP
, /* s: [...] edge edge anchor anchor */
4659 MDAP_noround
, /* set rp0 and rp1 to `sal_anchor' */
4670 DIV
, /* delta = (edge_orig_pos - anchor_orig_pos + 16) & ~31 */
4675 ALIGNRP
, /* align `edge' with `sal_anchor' */
4677 SHPIX
, /* shift `edge' by `delta' */
4685 * bci_action_serif_link2
4687 * Handle the SERIF_LINK2 action to align a serif relative to the anchor.
4689 * in: edge_point (in twilight zone)
4690 * ... stuff for bci_align_segments (edge) ...
4692 * uses: bci_serif_link2_common
4695 unsigned char FPGM(bci_action_serif_link2
) [] =
4699 bci_action_serif_link2
,
4703 bci_serif_link2_common
,
4706 MDAP_noround
, /* set rp0 and rp1 to `edge' */
4711 SZP1
, /* set zp1 to normal zone 1 */
4720 * bci_action_serif_link2_lower_bound
4722 * Handle the SERIF_LINK2 action to align a serif relative to the anchor.
4723 * Additionally, move the serif again if necessary to stay within a lower
4726 * in: edge_point (in twilight zone)
4727 * edge[-1] (in twilight zone)
4728 * ... stuff for bci_align_segments (edge) ...
4730 * uses: bci_serif_link2_common
4734 unsigned char FPGM(bci_action_serif_link2_lower_bound
) [] =
4738 bci_action_serif_link2_lower_bound
,
4742 bci_serif_link2_common
,
4755 * bci_action_serif_link2_upper_bound
4757 * Handle the SERIF_LINK2 action to align a serif relative to the anchor.
4758 * Additionally, move the serif again if necessary to stay within an upper
4761 * in: edge_point (in twilight zone)
4762 * edge[1] (in twilight zone)
4763 * ... stuff for bci_align_segments (edge) ...
4765 * uses: bci_serif_link2_common
4769 unsigned char FPGM(bci_action_serif_link2_upper_bound
) [] =
4773 bci_action_serif_link2_upper_bound
,
4777 bci_serif_link2_common
,
4790 * bci_action_serif_link2_upper_lower_bound
4792 * Handle the SERIF_LINK2 action to align a serif relative to the anchor.
4793 * Additionally, move the serif again if necessary to stay within a lower
4796 * in: edge_point (in twilight zone)
4797 * edge[-1] (in twilight zone)
4798 * edge[1] (in twilight zone)
4799 * ... stuff for bci_align_segments (edge) ...
4801 * uses: bci_serif_link2_common
4802 * bci_upper_lower_bound
4805 unsigned char FPGM(bci_action_serif_link2_upper_lower_bound
) [] =
4809 bci_action_serif_link2_upper_lower_bound
,
4813 bci_serif_link2_common
,
4817 bci_upper_lower_bound
,
4828 * This is the top-level glyph hinting function which parses the arguments
4829 * on the stack and calls subroutines.
4831 * in: action_0_func_idx
4837 * uses: bci_action_ip_before
4838 * bci_action_ip_after
4840 * bci_action_ip_between
4842 * bci_action_adjust_bound
4843 * bci_action_adjust_bound_serif
4844 * bci_action_adjust_bound_round
4845 * bci_action_adjust_bound_round_serif
4847 * bci_action_stem_bound
4848 * bci_action_stem_bound_serif
4849 * bci_action_stem_bound_round
4850 * bci_action_stem_bound_round_serif
4853 * bci_action_link_serif
4854 * bci_action_link_round
4855 * bci_action_link_round_serif
4858 * bci_action_anchor_serif
4859 * bci_action_anchor_round
4860 * bci_action_anchor_round_serif
4862 * bci_action_blue_anchor
4865 * bci_action_adjust_serif
4866 * bci_action_adjust_round
4867 * bci_action_adjust_round_serif
4870 * bci_action_stem_serif
4871 * bci_action_stem_round
4872 * bci_action_stem_round_serif
4877 * bci_action_serif_lower_bound
4878 * bci_action_serif_upper_bound
4879 * bci_action_serif_upper_lower_bound
4881 * bci_action_serif_anchor
4882 * bci_action_serif_anchor_lower_bound
4883 * bci_action_serif_anchor_upper_bound
4884 * bci_action_serif_anchor_upper_lower_bound
4886 * bci_action_serif_link1
4887 * bci_action_serif_link1_lower_bound
4888 * bci_action_serif_link1_upper_bound
4889 * bci_action_serif_link1_upper_lower_bound
4891 * bci_action_serif_link2
4892 * bci_action_serif_link2_lower_bound
4893 * bci_action_serif_link2_upper_bound
4894 * bci_action_serif_link2_upper_lower_bound
4896 * CVT: cvtl_is_subglyph
4899 unsigned char FPGM(bci_hint_glyph
) [] =
4907 /* loop until all data on stack is used */
4916 JROT
, /* goto start_loop */
4920 SZP2
, /* set zp2 to normal zone 1 */
4928 #define COPY_FPGM(func_name) \
4929 memcpy(buf_p, fpgm_ ## func_name, \
4930 sizeof (fpgm_ ## func_name)); \
4931 buf_p += sizeof (fpgm_ ## func_name) \
4934 TA_table_build_fpgm(FT_Byte
** fpgm
,
4944 /* for compatibility with dumb bytecode interpreters or analyzers, */
4945 /* FDEFs are stored in ascending index order, without holes -- */
4946 /* note that some FDEFs are not always needed */
4947 /* (depending on options of `TTFautohint'), */
4948 /* but implementing dynamic FDEF indices would be a lot of work */
4950 buf_len
= sizeof (FPGM(bci_round
))
4951 + sizeof (FPGM(bci_smooth_stem_width_a
))
4953 + sizeof (FPGM(bci_smooth_stem_width_b
))
4955 + sizeof (FPGM(bci_smooth_stem_width_c
))
4956 + sizeof (FPGM(bci_get_best_width
))
4957 + sizeof (FPGM(bci_strong_stem_width_a
))
4959 + sizeof (FPGM(bci_strong_stem_width_b
))
4960 + sizeof (FPGM(bci_loop
))
4961 + sizeof (FPGM(bci_cvt_rescale
))
4962 + sizeof (FPGM(bci_blue_round_a
))
4964 + sizeof (FPGM(bci_blue_round_b
))
4965 + sizeof (FPGM(bci_decrement_component_counter
))
4966 + sizeof (FPGM(bci_get_point_extrema
))
4967 + sizeof (FPGM(bci_nibbles
))
4968 + sizeof (FPGM(bci_number_set_is_element
))
4969 + sizeof (FPGM(bci_number_set_is_element2
))
4971 + sizeof (FPGM(bci_create_segment
))
4972 + sizeof (FPGM(bci_create_segments
))
4974 + sizeof (FPGM(bci_create_segments_0
))
4975 + sizeof (FPGM(bci_create_segments_1
))
4976 + sizeof (FPGM(bci_create_segments_2
))
4977 + sizeof (FPGM(bci_create_segments_3
))
4978 + sizeof (FPGM(bci_create_segments_4
))
4979 + sizeof (FPGM(bci_create_segments_5
))
4980 + sizeof (FPGM(bci_create_segments_6
))
4981 + sizeof (FPGM(bci_create_segments_7
))
4982 + sizeof (FPGM(bci_create_segments_8
))
4983 + sizeof (FPGM(bci_create_segments_9
))
4985 + sizeof (FPGM(bci_create_segments_composite
))
4987 + sizeof (FPGM(bci_create_segments_composite_0
))
4988 + sizeof (FPGM(bci_create_segments_composite_1
))
4989 + sizeof (FPGM(bci_create_segments_composite_2
))
4990 + sizeof (FPGM(bci_create_segments_composite_3
))
4991 + sizeof (FPGM(bci_create_segments_composite_4
))
4992 + sizeof (FPGM(bci_create_segments_composite_5
))
4993 + sizeof (FPGM(bci_create_segments_composite_6
))
4994 + sizeof (FPGM(bci_create_segments_composite_7
))
4995 + sizeof (FPGM(bci_create_segments_composite_8
))
4996 + sizeof (FPGM(bci_create_segments_composite_9
))
4998 + sizeof (FPGM(bci_align_segment
))
4999 + sizeof (FPGM(bci_align_segments
))
5001 + sizeof (FPGM(bci_scale_contour
))
5002 + sizeof (FPGM(bci_scale_glyph
))
5003 + sizeof (FPGM(bci_scale_composite_glyph
))
5004 + sizeof (FPGM(bci_shift_contour
))
5005 + sizeof (FPGM(bci_shift_subglyph
))
5007 + sizeof (FPGM(bci_ip_outer_align_point
))
5008 + sizeof (FPGM(bci_ip_on_align_points
))
5009 + sizeof (FPGM(bci_ip_between_align_point
))
5010 + sizeof (FPGM(bci_ip_between_align_points
))
5012 + sizeof (FPGM(bci_adjust_common
))
5013 + sizeof (FPGM(bci_stem_common
))
5014 + sizeof (FPGM(bci_serif_common
))
5015 + sizeof (FPGM(bci_serif_anchor_common
))
5016 + sizeof (FPGM(bci_serif_link1_common
))
5017 + sizeof (FPGM(bci_serif_link2_common
))
5019 + sizeof (FPGM(bci_lower_bound
))
5020 + sizeof (FPGM(bci_upper_bound
))
5021 + sizeof (FPGM(bci_upper_lower_bound
))
5023 + sizeof (FPGM(bci_adjust_bound
))
5024 + sizeof (FPGM(bci_stem_bound
))
5025 + sizeof (FPGM(bci_link
))
5026 + sizeof (FPGM(bci_anchor
))
5027 + sizeof (FPGM(bci_adjust
))
5028 + sizeof (FPGM(bci_stem
))
5030 + sizeof (FPGM(bci_action_ip_before
))
5031 + sizeof (FPGM(bci_action_ip_after
))
5032 + sizeof (FPGM(bci_action_ip_on
))
5033 + sizeof (FPGM(bci_action_ip_between
))
5035 + sizeof (FPGM(bci_action_blue
))
5036 + sizeof (FPGM(bci_action_blue_anchor
))
5038 + sizeof (FPGM(bci_action_anchor
))
5039 + sizeof (FPGM(bci_action_anchor_serif
))
5040 + sizeof (FPGM(bci_action_anchor_round
))
5041 + sizeof (FPGM(bci_action_anchor_round_serif
))
5043 + sizeof (FPGM(bci_action_adjust
))
5044 + sizeof (FPGM(bci_action_adjust_serif
))
5045 + sizeof (FPGM(bci_action_adjust_round
))
5046 + sizeof (FPGM(bci_action_adjust_round_serif
))
5047 + sizeof (FPGM(bci_action_adjust_bound
))
5048 + sizeof (FPGM(bci_action_adjust_bound_serif
))
5049 + sizeof (FPGM(bci_action_adjust_bound_round
))
5050 + sizeof (FPGM(bci_action_adjust_bound_round_serif
))
5052 + sizeof (FPGM(bci_action_link
))
5053 + sizeof (FPGM(bci_action_link_serif
))
5054 + sizeof (FPGM(bci_action_link_round
))
5055 + sizeof (FPGM(bci_action_link_round_serif
))
5057 + sizeof (FPGM(bci_action_stem
))
5058 + sizeof (FPGM(bci_action_stem_serif
))
5059 + sizeof (FPGM(bci_action_stem_round
))
5060 + sizeof (FPGM(bci_action_stem_round_serif
))
5061 + sizeof (FPGM(bci_action_stem_bound
))
5062 + sizeof (FPGM(bci_action_stem_bound_serif
))
5063 + sizeof (FPGM(bci_action_stem_bound_round
))
5064 + sizeof (FPGM(bci_action_stem_bound_round_serif
))
5066 + sizeof (FPGM(bci_action_serif
))
5067 + sizeof (FPGM(bci_action_serif_lower_bound
))
5068 + sizeof (FPGM(bci_action_serif_upper_bound
))
5069 + sizeof (FPGM(bci_action_serif_upper_lower_bound
))
5071 + sizeof (FPGM(bci_action_serif_anchor
))
5072 + sizeof (FPGM(bci_action_serif_anchor_lower_bound
))
5073 + sizeof (FPGM(bci_action_serif_anchor_upper_bound
))
5074 + sizeof (FPGM(bci_action_serif_anchor_upper_lower_bound
))
5076 + sizeof (FPGM(bci_action_serif_link1
))
5077 + sizeof (FPGM(bci_action_serif_link1_lower_bound
))
5078 + sizeof (FPGM(bci_action_serif_link1_upper_bound
))
5079 + sizeof (FPGM(bci_action_serif_link1_upper_lower_bound
))
5081 + sizeof (FPGM(bci_action_serif_link2
))
5082 + sizeof (FPGM(bci_action_serif_link2_lower_bound
))
5083 + sizeof (FPGM(bci_action_serif_link2_upper_bound
))
5084 + sizeof (FPGM(bci_action_serif_link2_upper_lower_bound
))
5086 + sizeof (FPGM(bci_hint_glyph
));
5088 /* buffer length must be a multiple of four */
5089 len
= (buf_len
+ 3) & ~3;
5090 buf
= (FT_Byte
*)malloc(len
);
5092 return FT_Err_Out_Of_Memory
;
5094 /* pad end of buffer with zeros */
5095 buf
[len
- 1] = 0x00;
5096 buf
[len
- 2] = 0x00;
5097 buf
[len
- 3] = 0x00;
5099 /* copy font program into buffer and fill in the missing variables */
5102 COPY_FPGM(bci_round
);
5103 COPY_FPGM(bci_smooth_stem_width_a
);
5104 *(buf_p
++) = (unsigned char)CVT_VERT_WIDTHS_OFFSET(font
);
5105 COPY_FPGM(bci_smooth_stem_width_b
);
5106 *(buf_p
++) = (unsigned char)CVT_VERT_WIDTHS_OFFSET(font
);
5107 COPY_FPGM(bci_smooth_stem_width_c
);
5108 COPY_FPGM(bci_get_best_width
);
5109 COPY_FPGM(bci_strong_stem_width_a
);
5110 *(buf_p
++) = (unsigned char)CVT_VERT_WIDTHS_OFFSET(font
);
5111 *(buf_p
++) = (unsigned char)CVT_VERT_WIDTHS_SIZE(font
);
5112 COPY_FPGM(bci_strong_stem_width_b
);
5113 COPY_FPGM(bci_loop
);
5114 COPY_FPGM(bci_cvt_rescale
);
5115 COPY_FPGM(bci_blue_round_a
);
5116 *(buf_p
++) = (unsigned char)CVT_BLUES_SIZE(font
);
5117 COPY_FPGM(bci_blue_round_b
);
5118 COPY_FPGM(bci_decrement_component_counter
);
5119 COPY_FPGM(bci_get_point_extrema
);
5120 COPY_FPGM(bci_nibbles
);
5121 COPY_FPGM(bci_number_set_is_element
);
5122 COPY_FPGM(bci_number_set_is_element2
);
5124 COPY_FPGM(bci_create_segment
);
5125 COPY_FPGM(bci_create_segments
);
5127 COPY_FPGM(bci_create_segments_0
);
5128 COPY_FPGM(bci_create_segments_1
);
5129 COPY_FPGM(bci_create_segments_2
);
5130 COPY_FPGM(bci_create_segments_3
);
5131 COPY_FPGM(bci_create_segments_4
);
5132 COPY_FPGM(bci_create_segments_5
);
5133 COPY_FPGM(bci_create_segments_6
);
5134 COPY_FPGM(bci_create_segments_7
);
5135 COPY_FPGM(bci_create_segments_8
);
5136 COPY_FPGM(bci_create_segments_9
);
5138 COPY_FPGM(bci_create_segments_composite
);
5140 COPY_FPGM(bci_create_segments_composite_0
);
5141 COPY_FPGM(bci_create_segments_composite_1
);
5142 COPY_FPGM(bci_create_segments_composite_2
);
5143 COPY_FPGM(bci_create_segments_composite_3
);
5144 COPY_FPGM(bci_create_segments_composite_4
);
5145 COPY_FPGM(bci_create_segments_composite_5
);
5146 COPY_FPGM(bci_create_segments_composite_6
);
5147 COPY_FPGM(bci_create_segments_composite_7
);
5148 COPY_FPGM(bci_create_segments_composite_8
);
5149 COPY_FPGM(bci_create_segments_composite_9
);
5151 COPY_FPGM(bci_align_segment
);
5152 COPY_FPGM(bci_align_segments
);
5154 COPY_FPGM(bci_scale_contour
);
5155 COPY_FPGM(bci_scale_glyph
);
5156 COPY_FPGM(bci_scale_composite_glyph
);
5157 COPY_FPGM(bci_shift_contour
);
5158 COPY_FPGM(bci_shift_subglyph
);
5160 COPY_FPGM(bci_ip_outer_align_point
);
5161 COPY_FPGM(bci_ip_on_align_points
);
5162 COPY_FPGM(bci_ip_between_align_point
);
5163 COPY_FPGM(bci_ip_between_align_points
);
5165 COPY_FPGM(bci_adjust_common
);
5166 COPY_FPGM(bci_stem_common
);
5167 COPY_FPGM(bci_serif_common
);
5168 COPY_FPGM(bci_serif_anchor_common
);
5169 COPY_FPGM(bci_serif_link1_common
);
5170 COPY_FPGM(bci_serif_link2_common
);
5172 COPY_FPGM(bci_lower_bound
);
5173 COPY_FPGM(bci_upper_bound
);
5174 COPY_FPGM(bci_upper_lower_bound
);
5176 COPY_FPGM(bci_adjust_bound
);
5177 COPY_FPGM(bci_stem_bound
);
5178 COPY_FPGM(bci_link
);
5179 COPY_FPGM(bci_anchor
);
5180 COPY_FPGM(bci_adjust
);
5181 COPY_FPGM(bci_stem
);
5183 COPY_FPGM(bci_action_ip_before
);
5184 COPY_FPGM(bci_action_ip_after
);
5185 COPY_FPGM(bci_action_ip_on
);
5186 COPY_FPGM(bci_action_ip_between
);
5188 COPY_FPGM(bci_action_blue
);
5189 COPY_FPGM(bci_action_blue_anchor
);
5191 COPY_FPGM(bci_action_anchor
);
5192 COPY_FPGM(bci_action_anchor_serif
);
5193 COPY_FPGM(bci_action_anchor_round
);
5194 COPY_FPGM(bci_action_anchor_round_serif
);
5196 COPY_FPGM(bci_action_adjust
);
5197 COPY_FPGM(bci_action_adjust_serif
);
5198 COPY_FPGM(bci_action_adjust_round
);
5199 COPY_FPGM(bci_action_adjust_round_serif
);
5200 COPY_FPGM(bci_action_adjust_bound
);
5201 COPY_FPGM(bci_action_adjust_bound_serif
);
5202 COPY_FPGM(bci_action_adjust_bound_round
);
5203 COPY_FPGM(bci_action_adjust_bound_round_serif
);
5205 COPY_FPGM(bci_action_link
);
5206 COPY_FPGM(bci_action_link_serif
);
5207 COPY_FPGM(bci_action_link_round
);
5208 COPY_FPGM(bci_action_link_round_serif
);
5210 COPY_FPGM(bci_action_stem
);
5211 COPY_FPGM(bci_action_stem_serif
);
5212 COPY_FPGM(bci_action_stem_round
);
5213 COPY_FPGM(bci_action_stem_round_serif
);
5214 COPY_FPGM(bci_action_stem_bound
);
5215 COPY_FPGM(bci_action_stem_bound_serif
);
5216 COPY_FPGM(bci_action_stem_bound_round
);
5217 COPY_FPGM(bci_action_stem_bound_round_serif
);
5219 COPY_FPGM(bci_action_serif
);
5220 COPY_FPGM(bci_action_serif_lower_bound
);
5221 COPY_FPGM(bci_action_serif_upper_bound
);
5222 COPY_FPGM(bci_action_serif_upper_lower_bound
);
5224 COPY_FPGM(bci_action_serif_anchor
);
5225 COPY_FPGM(bci_action_serif_anchor_lower_bound
);
5226 COPY_FPGM(bci_action_serif_anchor_upper_bound
);
5227 COPY_FPGM(bci_action_serif_anchor_upper_lower_bound
);
5229 COPY_FPGM(bci_action_serif_link1
);
5230 COPY_FPGM(bci_action_serif_link1_lower_bound
);
5231 COPY_FPGM(bci_action_serif_link1_upper_bound
);
5232 COPY_FPGM(bci_action_serif_link1_upper_lower_bound
);
5234 COPY_FPGM(bci_action_serif_link2
);
5235 COPY_FPGM(bci_action_serif_link2_lower_bound
);
5236 COPY_FPGM(bci_action_serif_link2_upper_bound
);
5237 COPY_FPGM(bci_action_serif_link2_upper_lower_bound
);
5239 COPY_FPGM(bci_hint_glyph
);
5242 *fpgm_len
= buf_len
;
5249 TA_sfnt_build_fpgm_table(SFNT
* sfnt
,
5252 FT_Error error
= FT_Err_Ok
;
5254 SFNT_Table
* glyf_table
= &font
->tables
[sfnt
->glyf_idx
];
5255 glyf_Data
* data
= (glyf_Data
*)glyf_table
->data
;
5261 error
= TA_sfnt_add_table_info(sfnt
);
5265 /* `glyf', `cvt', `fpgm', and `prep' are always used in parallel */
5266 if (glyf_table
->processed
)
5268 sfnt
->table_infos
[sfnt
->num_table_infos
- 1] = data
->fpgm_idx
;
5272 error
= TA_table_build_fpgm(&fpgm_buf
, &fpgm_len
, font
);
5276 if (fpgm_len
> sfnt
->max_instructions
)
5277 sfnt
->max_instructions
= fpgm_len
;
5279 /* in case of success, `fpgm_buf' gets linked */
5280 /* and is eventually freed in `TA_font_unload' */
5281 error
= TA_font_add_table(font
,
5282 &sfnt
->table_infos
[sfnt
->num_table_infos
- 1],
5283 TTAG_fpgm
, fpgm_len
, fpgm_buf
);
5287 data
->fpgm_idx
= sfnt
->table_infos
[sfnt
->num_table_infos
- 1];
5293 /* end of tafpgm.c */