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 */
872 * Store start and end point of a segment in the storage area,
873 * then construct a point in the twilight zone to represent it.
875 * This function is used by `bci_create_segment_points'.
879 * [last (if wrap-around segment)]
880 * [first (if wrap-around segment)]
882 * uses: bci_get_point_extrema
885 * sal: sal_i (start of current segment)
886 * sal_j (current twilight point)
890 * sal_num_packed_segments
896 * If `sal_num_packed_segments' is > 0, the start/end pair is stored as
897 * delta values in nibbles (without a wrap-around segment).
900 unsigned char FPGM(bci_create_segment
) [] =
909 sal_num_packed_segments
,
914 sal_num_packed_segments
,
915 sal_num_packed_segments
,
920 WS
, /* sal_num_packed_segments = sal_num_packed_segments - 1 */
933 WS
, /* sal[sal_i] = start */
935 /* increase `sal_i'; together with the outer loop, this makes sal_i += 2 */
941 ADD
, /* sal_i = sal_i + 1 */
944 /* initialize inner loop(s) */
949 WS
, /* sal_point_min = start */
954 WS
, /* sal_point_max = start */
958 SZPS
, /* set zp0, zp1, and zp2 to normal zone 1 */
964 CINDEX
, /* s: start end end start */
965 LT
, /* start > end */
967 /* we have a wrap-around segment with two more arguments */
968 /* to give the last and first point of the contour, respectively; */
969 /* our job is to store a segment `start'-`last', */
970 /* and to get extrema for the two segments */
971 /* `start'-`last' and `first'-`end' */
973 /* s: first last start end */
980 WS
, /* sal[sal_i] = last */
983 ROLL
, /* s: first end last start */
986 SWAP
, /* s: first end start last start */
987 SUB
, /* s: first end start loop_count */
990 bci_get_point_extrema
,
995 SWAP
, /* s: end first */
1000 ROLL
, /* s: (first - 1) (first - 1) end */
1002 SUB
, /* s: (first - 1) loop_count */
1005 bci_get_point_extrema
,
1007 /* clean up stack */
1010 ELSE
, /* s: start end */
1017 WS
, /* sal[sal_i] = end */
1022 SUB
, /* s: start loop_count */
1025 bci_get_point_extrema
,
1027 /* clean up stack */
1031 /* the twilight point representing a segment */
1032 /* is in the middle between the minimum and maximum */
1044 DIV
, /* s: middle_pos */
1046 DO_SCALE
, /* middle_pos = middle_pos * scale */
1048 /* write it to temporary CVT location */
1052 SZP0
, /* set zp0 to twilight zone 0 */
1056 /* create twilight point with index `sal_j' */
1069 ADD
, /* twilight_point = twilight_point + 1 */
1078 * bci_create_segments
1080 * This is the top-level entry function.
1082 * It pops point ranges from the stack to define segments, computes
1083 * twilight points to represent segments, and finally calls
1084 * `bci_hint_glyph' to handle the rest.
1086 * in: num_packed_segments
1090 * [contour_last 0 (if wrap-around segment)]
1091 * [contour_first 0 (if wrap-around segment)]
1094 * [contour_last 0 (if wrap-around segment)]
1095 * [contour_first 0 (if wrap-around segment)]
1097 * segment_start_(N-1)
1099 * [contour_last (N-1) (if wrap-around segment)]
1100 * [contour_first (N-1) (if wrap-around segment)]
1101 * ... stuff for bci_hint_glyph ...
1103 * uses: bci_create_segment
1105 * sal: sal_i (start of current segment)
1106 * sal_j (current twilight point)
1107 * sal_num_packed_segments
1108 * sal_base (the base for delta values in nibbles)
1110 * CVT: cvtl_is_subglyph
1112 * If `num_packed_segments' is set to p, the first p start/end pairs are
1113 * stored as delta values in nibbles, with the `start' delta in the lower
1114 * nibble (and there are no wrap-around segments). For example, if the
1115 * first three pairs are 1/3, 5/8, and 12/13, the topmost three bytes on the
1116 * stack are 0x21, 0x32, and 0x14.
1120 unsigned char FPGM(bci_create_segments
) [] =
1124 bci_create_segments
,
1127 /* only do something if we are not a subglyph */
1134 /* all our measurements are taken along the y axis */
1138 sal_num_packed_segments
,
1146 SUB
, /* delta = (2*num_segments - 1) */
1156 WS
, /* sal_base = 0 */
1157 WS
, /* sal_j = 0 (point offset) */
1160 ADD
, /* s: ... sal_segment_offset (sal_segment_offset + delta) */
1162 /* `bci_create_segment_point' also increases the loop counter by 1; */
1163 /* this effectively means we have a loop step of 2 */
1183 * bci_create_segments_X
1185 * Top-level routines for calling `bci_create_segments'.
1188 unsigned char FPGM(bci_create_segments_0
) [] =
1192 bci_create_segments_0
,
1197 bci_create_segments
,
1204 unsigned char FPGM(bci_create_segments_1
) [] =
1208 bci_create_segments_1
,
1213 bci_create_segments
,
1220 unsigned char FPGM(bci_create_segments_2
) [] =
1224 bci_create_segments_2
,
1229 bci_create_segments
,
1236 unsigned char FPGM(bci_create_segments_3
) [] =
1240 bci_create_segments_3
,
1245 bci_create_segments
,
1252 unsigned char FPGM(bci_create_segments_4
) [] =
1256 bci_create_segments_4
,
1261 bci_create_segments
,
1268 unsigned char FPGM(bci_create_segments_5
) [] =
1272 bci_create_segments_5
,
1277 bci_create_segments
,
1284 unsigned char FPGM(bci_create_segments_6
) [] =
1288 bci_create_segments_6
,
1293 bci_create_segments
,
1300 unsigned char FPGM(bci_create_segments_7
) [] =
1304 bci_create_segments_7
,
1309 bci_create_segments
,
1316 unsigned char FPGM(bci_create_segments_8
) [] =
1320 bci_create_segments_8
,
1325 bci_create_segments
,
1332 unsigned char FPGM(bci_create_segments_9
) [] =
1336 bci_create_segments_9
,
1341 bci_create_segments
,
1350 * bci_create_segments_composite
1352 * The same as `bci_create_segments'.
1353 * It also decrements the composite component counter.
1355 * uses: bci_decrement_composite_counter
1357 * CVT: cvtl_is_subglyph
1360 unsigned char FPGM(bci_create_segments_composite
) [] =
1364 bci_create_segments_composite
,
1368 bci_decrement_component_counter
,
1371 /* only do something if we are not a subglyph */
1378 /* all our measurements are taken along the y axis */
1382 sal_num_packed_segments
,
1390 SUB
, /* delta = (2*num_segments - 1) */
1400 WS
, /* sal_base = 0 */
1401 WS
, /* sal_j = 0 (point offset) */
1404 ADD
, /* s: ... sal_segment_offset (sal_segment_offset + delta) */
1406 /* `bci_create_segment_point' also increases the loop counter by 1; */
1407 /* this effectively means we have a loop step of 2 */
1427 * bci_create_segments_composite_X
1429 * Top-level routines for calling `bci_create_segments_composite'.
1432 unsigned char FPGM(bci_create_segments_composite_0
) [] =
1436 bci_create_segments_composite_0
,
1441 bci_create_segments_composite
,
1448 unsigned char FPGM(bci_create_segments_composite_1
) [] =
1452 bci_create_segments_composite_1
,
1457 bci_create_segments_composite
,
1464 unsigned char FPGM(bci_create_segments_composite_2
) [] =
1468 bci_create_segments_composite_2
,
1473 bci_create_segments_composite
,
1480 unsigned char FPGM(bci_create_segments_composite_3
) [] =
1484 bci_create_segments_composite_3
,
1489 bci_create_segments_composite
,
1496 unsigned char FPGM(bci_create_segments_composite_4
) [] =
1500 bci_create_segments_composite_4
,
1505 bci_create_segments_composite
,
1512 unsigned char FPGM(bci_create_segments_composite_5
) [] =
1516 bci_create_segments_composite_5
,
1521 bci_create_segments_composite
,
1528 unsigned char FPGM(bci_create_segments_composite_6
) [] =
1532 bci_create_segments_composite_6
,
1537 bci_create_segments_composite
,
1544 unsigned char FPGM(bci_create_segments_composite_7
) [] =
1548 bci_create_segments_composite_7
,
1553 bci_create_segments_composite
,
1560 unsigned char FPGM(bci_create_segments_composite_8
) [] =
1564 bci_create_segments_composite_8
,
1569 bci_create_segments_composite
,
1576 unsigned char FPGM(bci_create_segments_composite_9
) [] =
1580 bci_create_segments_composite_9
,
1585 bci_create_segments_composite
,
1596 * Align all points in a segment to the twilight point in rp0.
1597 * zp0 and zp1 must be set to 0 (twilight) and 1 (normal), respectively.
1602 unsigned char FPGM(bci_align_segment
) [] =
1609 /* we need the values of `sal_segment_offset + 2*segment_index' */
1610 /* and `sal_segment_offset + 2*segment_index + 1' */
1622 RS
, /* s: first last */
1627 CINDEX
, /* s: first last first */
1630 CINDEX
, /* s: first last first last */
1631 LTEQ
, /* first <= end */
1632 IF
, /* s: first last */
1634 DUP
, /* s: last first first */
1635 ALIGNRP
, /* align point with index `first' with rp0 */
1639 ADD
, /* first = first + 1 */
1640 SWAP
, /* s: first last */
1645 JMPR
, /* goto start_loop */
1658 * bci_align_segments
1660 * Align segments to the twilight point in rp0.
1661 * zp0 and zp1 must be set to 0 (twilight) and 1 (normal), respectively.
1670 * uses: handle_segment
1674 unsigned char FPGM(bci_align_segments
) [] =
1697 * Scale a contour using two points giving the maximum and minimum
1700 * It expects that no point on the contour is touched.
1709 unsigned char FPGM(bci_scale_contour
) [] =
1720 DO_SCALE
, /* min_pos_new = min_pos * scale */
1725 /* don't scale a single-point contour twice */
1734 DO_SCALE
, /* max_pos_new = max_pos * scale */
1751 * Scale a glyph using a list of points (two points per contour, giving
1752 * the maximum and mininum coordinates).
1754 * It expects that no point in the glyph is touched.
1756 * Note that the point numbers are sorted in ascending order;
1757 * `min_point_X' and `max_point_X' thus refer to the two extrema of a
1758 * contour without specifying which one is the minimum and maximum.
1760 * in: num_contours (N)
1769 * uses: bci_scale_contour
1771 * CVT: cvtl_is_subglyph
1774 unsigned char FPGM(bci_scale_glyph
) [] =
1781 /* only do something if we are not a subglyph */
1788 /* all our measurements are taken along the y axis */
1793 SZPS
, /* set zp0, zp1, and zp2 to normal zone 1 */
1801 SZP2
, /* set zp2 to normal zone 1 */
1814 * bci_scale_composite_glyph
1816 * The same as `bci_scale_composite_glyph'.
1817 * It also decrements the composite component counter.
1819 * uses: bci_decrement_component_counter
1821 * CVT: cvtl_is_subglyph
1824 unsigned char FPGM(bci_scale_composite_glyph
) [] =
1828 bci_scale_composite_glyph
,
1832 bci_decrement_component_counter
,
1835 /* only do something if we are not a subglyph */
1842 /* all our measurements are taken along the y axis */
1847 SZPS
, /* set zp0, zp1, and zp2 to normal zone 1 */
1855 SZP2
, /* set zp2 to normal zone 1 */
1870 * Shift a contour by a given amount.
1872 * It expects that rp1 (pointed to by zp0) is set up properly; zp2 must
1873 * point to the normal zone 1.
1879 unsigned char FPGM(bci_shift_contour
) [] =
1887 SHC_rp1
, /* shift `contour' by (rp1_pos - rp1_orig_pos) */
1899 * bci_shift_subglyph
1901 * Shift a subglyph. To be more specific, it corrects the already applied
1902 * subglyph offset (if any) from the `glyf' table which needs to be scaled
1905 * If this function is called, a point `x' in the subglyph has been scaled
1906 * already (during the hinting of the subglyph itself), and `offset' has
1907 * been applied also:
1909 * x -> x * scale + offset (1)
1911 * However, the offset should be applied first, then the scaling:
1913 * x -> (x + offset) * scale (2)
1915 * Our job is now to transform (1) to (2); a simple calculation shows that
1916 * we have to shift all points of the subglyph by
1918 * offset * scale - offset = offset * (scale - 1)
1920 * Note that `cvtl_scale' is equal to the above `scale - 1'.
1922 * in: offset (in FUnits)
1926 * CVT: cvtl_funits_to_pixels
1931 unsigned char FPGM(bci_shift_subglyph
) [] =
1941 cvtl_funits_to_pixels
,
1942 RCVT
, /* scaling factor FUnits -> pixels */
1949 /* the autohinter always rounds offsets */
1952 CALL
, /* offset = round(offset) */
1961 DIV
, /* delta = offset * (scale - 1) */
1963 /* and round again */
1966 CALL
, /* offset = round(offset) */
1970 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
1972 /* we create twilight point 0 as a reference point, */
1973 /* setting the original position to zero (using `cvtl_temp') */
1981 MIAP_noround
, /* rp0 and rp1 now point to twilight point 0 */
1983 SWAP
, /* s: first_contour num_contours 0 delta */
1984 SHPIX
, /* rp1_pos - rp1_orig_pos = delta */
1989 SZP2
, /* set zp2 to normal zone 1 */
1998 * bci_ip_outer_align_point
2000 * Auxiliary function for `bci_action_ip_before' and
2001 * `bci_action_ip_after'.
2003 * It expects rp0 to contain the edge for alignment, zp0 set to twilight
2004 * zone, and both zp1 and zp2 set to normal zone.
2008 * sal: sal_i (edge_orig_pos)
2014 unsigned char FPGM(bci_ip_outer_align_point
) [] =
2018 bci_ip_outer_align_point
,
2022 ALIGNRP
, /* align `point' with `edge' */
2025 DO_SCALE
, /* point_orig_pos = point_orig_pos * scale */
2030 SUB
, /* s: point (point_orig_pos - edge_orig_pos) */
2039 * bci_ip_on_align_points
2041 * Auxiliary function for `bci_action_ip_on'.
2043 * in: edge (in twilight zone)
2051 unsigned char FPGM(bci_ip_on_align_points
) [] =
2055 bci_ip_on_align_points
,
2058 MDAP_noround
, /* set rp0 and rp1 to `edge' */
2069 * bci_ip_between_align_point
2071 * Auxiliary function for `bci_ip_between_align_points'.
2073 * It expects rp0 to contain the edge for alignment, zp0 set to twilight
2074 * zone, and both zp1 and zp2 set to normal zone.
2078 * sal: sal_i (edge_orig_pos)
2079 * sal_j (stretch_factor)
2085 unsigned char FPGM(bci_ip_between_align_point
) [] =
2089 bci_ip_between_align_point
,
2093 ALIGNRP
, /* align `point' with `edge' */
2096 DO_SCALE
, /* point_orig_pos = point_orig_pos * scale */
2101 SUB
, /* s: point (point_orig_pos - edge_orig_pos) */
2105 MUL
, /* s: point delta */
2114 * bci_ip_between_align_points
2116 * Auxiliary function for `bci_action_ip_between'.
2118 * in: after_edge (in twilight zone)
2119 * before_edge (in twilight zone)
2126 * sal: sal_i (before_orig_pos)
2127 * sal_j (stretch_factor)
2129 * uses: bci_ip_between_align_point
2132 unsigned char FPGM(bci_ip_between_align_points
) [] =
2136 bci_ip_between_align_points
,
2142 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
2144 DUP
, /* s: ... before after before before */
2145 MDAP_noround
, /* set rp0 and rp1 to `before' */
2147 GC_orig
, /* s: ... before after before before_orig_pos */
2151 WS
, /* sal_i = before_orig_pos */
2154 CINDEX
, /* s: ... before after before after */
2155 MD_cur
, /* b = after_pos - before_pos */
2158 MD_orig_ZP2_0
, /* a = after_orig_pos - before_orig_pos */
2163 WS
, /* sal_j = stretch_factor */
2166 bci_ip_between_align_point
,
2169 SZP2
, /* set zp2 to normal zone 1 */
2170 SZP1
, /* set zp1 to normal zone 1 */
2179 * bci_action_ip_before
2181 * Handle `ip_before' data to align points located before the first edge.
2183 * in: first_edge (in twilight zone)
2190 * sal: sal_i (first_edge_orig_pos)
2192 * uses: bci_ip_outer_align_point
2195 unsigned char FPGM(bci_action_ip_before
) [] =
2199 bci_action_ip_before
,
2204 SZP2
, /* set zp2 to twilight zone 0 */
2211 WS
, /* sal_i = first_edge_orig_pos */
2217 SZP2
, /* set zp2 to normal zone 1 */
2218 SZP1
, /* set zp1 to normal zone 1 */
2219 SZP0
, /* set zp0 to twilight zone 0 */
2221 MDAP_noround
, /* set rp0 and rp1 to `first_edge' */
2224 bci_ip_outer_align_point
,
2233 * bci_action_ip_after
2235 * Handle `ip_after' data to align points located after the last edge.
2237 * in: last_edge (in twilight zone)
2244 * sal: sal_i (last_edge_orig_pos)
2246 * uses: bci_ip_outer_align_point
2249 unsigned char FPGM(bci_action_ip_after
) [] =
2253 bci_action_ip_after
,
2258 SZP2
, /* set zp2 to twilight zone 0 */
2265 WS
, /* sal_i = last_edge_orig_pos */
2271 SZP2
, /* set zp2 to normal zone 1 */
2272 SZP1
, /* set zp1 to normal zone 1 */
2273 SZP0
, /* set zp0 to twilight zone 0 */
2275 MDAP_noround
, /* set rp0 and rp1 to `last_edge' */
2278 bci_ip_outer_align_point
,
2289 * Handle `ip_on' data to align points located on an edge coordinate (but
2290 * not part of an edge).
2292 * in: loop_counter (M)
2293 * edge_1 (in twilight zone)
2294 * loop_counter (N_1)
2299 * edge_2 (in twilight zone)
2300 * loop_counter (N_2)
2306 * edge_M (in twilight zone)
2307 * loop_counter (N_M)
2313 * uses: bci_ip_on_align_points
2316 unsigned char FPGM(bci_action_ip_on
) [] =
2326 SZP1
, /* set zp1 to normal zone 1 */
2327 SZP0
, /* set zp0 to twilight zone 0 */
2330 bci_ip_on_align_points
,
2339 * bci_action_ip_between
2341 * Handle `ip_between' data to align points located between two edges.
2343 * in: loop_counter (M)
2344 * before_edge_1 (in twilight zone)
2345 * after_edge_1 (in twilight zone)
2346 * loop_counter (N_1)
2351 * before_edge_2 (in twilight zone)
2352 * after_edge_2 (in twilight zone)
2353 * loop_counter (N_2)
2359 * before_edge_M (in twilight zone)
2360 * after_edge_M (in twilight zone)
2361 * loop_counter (N_M)
2367 * uses: bci_ip_between_align_points
2370 unsigned char FPGM(bci_action_ip_between
) [] =
2374 bci_action_ip_between
,
2378 bci_ip_between_align_points
,
2389 * Common code for bci_action_adjust routines.
2392 unsigned char FPGM(bci_adjust_common
) [] =
2401 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
2405 CINDEX
, /* s: [...] edge2 edge is_round is_serif edge2 */
2408 CINDEX
, /* s: [...] edge2 edge is_round is_serif edge2 edge */
2409 MD_orig_ZP2_0
, /* s: [...] edge2 edge is_round is_serif org_len */
2412 cvtl_stem_width_function
,
2415 NEG
, /* s: [...] edge2 edge -cur_len */
2417 ROLL
, /* s: [...] edge -cur_len edge2 */
2418 MDAP_noround
, /* set rp0 and rp1 to `edge2' */
2421 DUP
, /* s: [...] -cur_len edge edge edge */
2422 ALIGNRP
, /* align `edge' with `edge2' */
2424 SHPIX
, /* shift `edge' by -cur_len */
2434 * Handle the ADJUST_BOUND action to align an edge of a stem if the other
2435 * edge of the stem has already been moved, then moving it again if
2436 * necessary to stay bound.
2438 * in: edge2_is_serif
2440 * edge_point (in twilight zone)
2441 * edge2_point (in twilight zone)
2442 * edge[-1] (in twilight zone)
2443 * ... stuff for bci_align_segments (edge) ...
2445 * uses: bci_adjust_common
2448 unsigned char FPGM(bci_adjust_bound
) [] =
2459 SWAP
, /* s: edge edge[-1] */
2461 MDAP_noround
, /* set rp0 and rp1 to `edge[-1]' */
2466 GC_cur
, /* s: edge edge[-1]_pos edge_pos */
2467 GT
, /* edge_pos < edge[-1]_pos */
2470 ALIGNRP
, /* align `edge' to `edge[-1]' */
2473 MDAP_noround
, /* set rp0 and rp1 to `edge' */
2478 SZP1
, /* set zp1 to normal zone 1 */
2487 * bci_action_adjust_bound
2488 * bci_action_adjust_bound_serif
2489 * bci_action_adjust_bound_round
2490 * bci_action_adjust_bound_round_serif
2492 * Higher-level routines for calling `bci_adjust_bound'.
2495 unsigned char FPGM(bci_action_adjust_bound
) [] =
2499 bci_action_adjust_bound
,
2512 unsigned char FPGM(bci_action_adjust_bound_serif
) [] =
2516 bci_action_adjust_bound_serif
,
2529 unsigned char FPGM(bci_action_adjust_bound_round
) [] =
2533 bci_action_adjust_bound_round
,
2546 unsigned char FPGM(bci_action_adjust_bound_round_serif
) [] =
2550 bci_action_adjust_bound_round_serif
,
2567 * Handle the ADJUST action to align an edge of a stem if the other edge
2568 * of the stem has already been moved.
2570 * in: edge2_is_serif
2572 * edge_point (in twilight zone)
2573 * edge2_point (in twilight zone)
2574 * ... stuff for bci_align_segments (edge) ...
2576 * uses: bci_adjust_common
2579 unsigned char FPGM(bci_adjust
) [] =
2590 MDAP_noround
, /* set rp0 and rp1 to `edge' */
2595 SZP1
, /* set zp1 to normal zone 1 */
2605 * bci_action_adjust_serif
2606 * bci_action_adjust_round
2607 * bci_action_adjust_round_serif
2609 * Higher-level routines for calling `bci_adjust'.
2612 unsigned char FPGM(bci_action_adjust
) [] =
2629 unsigned char FPGM(bci_action_adjust_serif
) [] =
2633 bci_action_adjust_serif
,
2646 unsigned char FPGM(bci_action_adjust_round
) [] =
2650 bci_action_adjust_round
,
2663 unsigned char FPGM(bci_action_adjust_round_serif
) [] =
2667 bci_action_adjust_round_serif
,
2684 * Common code for bci_action_stem routines.
2688 #define sal_u_off sal_temp1
2690 #define sal_d_off sal_temp2
2692 #define sal_org_len sal_temp3
2694 #define sal_edge2 sal_temp3
2696 unsigned char FPGM(bci_stem_common
) [] =
2705 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
2713 DUP
, /* s: [...] edge2 edge is_round is_serif edge2 edge edge */
2714 MDAP_noround
, /* set rp0 and rp1 to `edge_point' (for ALIGNRP below) */
2716 MD_orig_ZP2_0
, /* s: [...] edge2 edge is_round is_serif org_len */
2724 cvtl_stem_width_function
,
2726 CALL
, /* s: [...] edge2 edge cur_len */
2731 LT
, /* cur_len < 96 */
2736 LTEQ
, /* cur_len <= 64 */
2754 SWAP
, /* s: [...] edge2 cur_len edge */
2759 DUP
, /* s: [...] edge2 cur_len edge edge anchor anchor */
2765 ADD
, /* s: [...] edge2 cur_len edge org_pos */
2772 ADD
, /* s: [...] edge2 cur_len edge org_center */
2777 CALL
, /* s: [...] edge2 cur_len edge org_center cur_pos1 */
2782 SUB
, /* s: ... cur_len edge cur_pos1 (org_center - cur_pos1) */
2789 ABS
, /* s: ... cur_len edge cur_pos1 (org_center - cur_pos1) delta1 */
2796 ABS
, /* s: [...] edge2 cur_len edge cur_pos1 delta1 delta2 */
2798 LT
, /* delta1 < delta2 */
2803 SUB
, /* cur_pos1 = cur_pos1 - u_off */
2809 ADD
, /* cur_pos1 = cur_pos1 + d_off */
2810 EIF
, /* s: [...] edge2 cur_len edge cur_pos1 */
2818 SUB
, /* arg = cur_pos1 - cur_len/2 */
2820 SWAP
, /* s: [...] edge2 cur_len arg edge */
2826 SWAP
, /* s: [...] edge2 cur_len edge edge arg edge */
2829 SHPIX
, /* edge = cur_pos1 - cur_len/2 */
2832 SWAP
, /* s: [...] edge2 cur_len edge */
2836 GC_cur
, /* s: [...] edge2 cur_len edge anchor_pos */
2844 ADD
, /* s: [...] edge2 cur_len edge org_pos */
2853 ADD
, /* s: [...] edge2 cur_len edge org_pos org_center */
2859 CALL
, /* cur_pos1 = ROUND(org_pos) */
2871 SUB
, /* s: [...] edge2 cur_len edge org_center cur_pos1 cur_pos2 */
2882 SUB
, /* s: ... cur_len edge cur_pos1 cur_pos2 (cur_len/2 - org_center) */
2889 ABS
, /* delta1 = ABS(cur_pos1 + cur_len / 2 - org_center) */
2895 ABS
, /* s: ... edge2 cur_len edge cur_pos1 cur_pos2 delta1 delta2 */
2896 LT
, /* delta1 < delta2 */
2898 POP
, /* arg = cur_pos1 */
2902 POP
, /* arg = cur_pos2 */
2903 EIF
, /* s: [...] edge2 cur_len edge arg */
2910 SWAP
, /* s: [...] edge2 cur_len edge edge arg edge */
2913 SHPIX
, /* edge = arg */
2914 EIF
, /* s: [...] edge2 cur_len edge */
2924 * Handle the STEM action to align two edges of a stem, then moving one
2925 * edge again if necessary to stay bound.
2927 * The code after computing `cur_len' to shift `edge' and `edge2'
2928 * is equivalent to the snippet below (part of `ta_latin_hint_edges'):
2931 * if cur_len < = 64:
2938 * org_pos = anchor + (edge_orig - anchor_orig);
2939 * org_center = org_pos + org_len / 2;
2941 * cur_pos1 = ROUND(org_center)
2942 * delta1 = ABS(org_center - (cur_pos1 - u_off))
2943 * delta2 = ABS(org_center - (cur_pos1 + d_off))
2944 * if (delta1 < delta2):
2945 * cur_pos1 = cur_pos1 - u_off
2947 * cur_pos1 = cur_pos1 + d_off
2949 * edge = cur_pos1 - cur_len / 2
2952 * org_pos = anchor + (edge_orig - anchor_orig)
2953 * org_center = org_pos + org_len / 2;
2955 * cur_pos1 = ROUND(org_pos)
2956 * delta1 = ABS(cur_pos1 + cur_len / 2 - org_center)
2957 * cur_pos2 = ROUND(org_pos + org_len) - cur_len
2958 * delta2 = ABS(cur_pos2 + cur_len / 2 - org_center)
2960 * if (delta1 < delta2):
2965 * edge2 = edge + cur_len
2967 * in: edge2_is_serif
2969 * edge_point (in twilight zone)
2970 * edge2_point (in twilight zone)
2971 * edge[-1] (in twilight zone)
2972 * ... stuff for bci_align_segments (edge) ...
2973 * ... stuff for bci_align_segments (edge2)...
2980 * uses: bci_stem_common
2983 unsigned char FPGM(bci_stem_bound
) [] =
2994 ROLL
, /* s: edge[-1] cur_len edge edge2 */
2997 ALIGNRP
, /* align `edge2' with rp0 (still `edge') */
3001 WS
, /* s: edge[-1] cur_len edge edge2 */
3003 SHPIX
, /* edge2 = edge + cur_len */
3005 SWAP
, /* s: edge edge[-1] */
3007 MDAP_noround
, /* set rp0 and rp1 to `edge[-1]' */
3012 GC_cur
, /* s: edge edge[-1]_pos edge_pos */
3013 GT
, /* edge_pos < edge[-1]_pos */
3016 ALIGNRP
, /* align `edge' to `edge[-1]' */
3019 MDAP_noround
, /* set rp0 and rp1 to `edge' */
3024 SZP1
, /* set zp1 to normal zone 1 */
3030 MDAP_noround
, /* set rp0 and rp1 to `edge2' */
3042 * bci_action_stem_bound
3043 * bci_action_stem_bound_serif
3044 * bci_action_stem_bound_round
3045 * bci_action_stem_bound_round_serif
3047 * Higher-level routines for calling `bci_stem_bound'.
3050 unsigned char FPGM(bci_action_stem_bound
) [] =
3054 bci_action_stem_bound
,
3067 unsigned char FPGM(bci_action_stem_bound_serif
) [] =
3071 bci_action_stem_bound_serif
,
3084 unsigned char FPGM(bci_action_stem_bound_round
) [] =
3088 bci_action_stem_bound_round
,
3101 unsigned char FPGM(bci_action_stem_bound_round_serif
) [] =
3105 bci_action_stem_bound_round_serif
,
3122 * Handle the STEM action to align two edges of a stem.
3124 * See `bci_stem_bound' for more details.
3126 * in: edge2_is_serif
3128 * edge_point (in twilight zone)
3129 * edge2_point (in twilight zone)
3130 * ... stuff for bci_align_segments (edge) ...
3131 * ... stuff for bci_align_segments (edge2)...
3138 * uses: bci_stem_common
3141 unsigned char FPGM(bci_stem
) [] =
3153 SWAP
, /* s: cur_len edge2 */
3156 ALIGNRP
, /* align `edge2' with rp0 (still `edge') */
3160 WS
, /* s: cur_len edge2 */
3162 SHPIX
, /* edge2 = edge + cur_len */
3167 SZP1
, /* set zp1 to normal zone 1 */
3173 MDAP_noround
, /* set rp0 and rp1 to `edge2' */
3185 * bci_action_stem_serif
3186 * bci_action_stem_round
3187 * bci_action_stem_round_serif
3189 * Higher-level routines for calling `bci_stem'.
3192 unsigned char FPGM(bci_action_stem
) [] =
3209 unsigned char FPGM(bci_action_stem_serif
) [] =
3213 bci_action_stem_serif
,
3226 unsigned char FPGM(bci_action_stem_round
) [] =
3230 bci_action_stem_round
,
3243 unsigned char FPGM(bci_action_stem_round_serif
) [] =
3247 bci_action_stem_round_serif
,
3264 * Handle the LINK action to link an edge to another one.
3268 * base_point (in twilight zone)
3269 * stem_point (in twilight zone)
3270 * ... stuff for bci_align_segments (base) ...
3273 unsigned char FPGM(bci_link
) [] =
3282 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
3290 DUP
, /* s: stem is_round is_serif stem base base */
3291 MDAP_noround
, /* set rp0 and rp1 to `base_point' (for ALIGNRP below) */
3293 MD_orig_ZP2_0
, /* s: stem is_round is_serif dist_orig */
3296 cvtl_stem_width_function
,
3298 CALL
, /* s: stem new_dist */
3302 ALIGNRP
, /* align `stem_point' with `base_point' */
3304 MDAP_noround
, /* set rp0 and rp1 to `stem_point' */
3306 SHPIX
, /* stem_point = base_point + new_dist */
3311 SZP1
, /* set zp1 to normal zone 1 */
3321 * bci_action_link_serif
3322 * bci_action_link_round
3323 * bci_action_link_round_serif
3325 * Higher-level routines for calling `bci_link'.
3328 unsigned char FPGM(bci_action_link
) [] =
3345 unsigned char FPGM(bci_action_link_serif
) [] =
3349 bci_action_link_serif
,
3362 unsigned char FPGM(bci_action_link_round
) [] =
3366 bci_action_link_round
,
3379 unsigned char FPGM(bci_action_link_round_serif
) [] =
3383 bci_action_link_round_serif
,
3400 * Handle the ANCHOR action to align two edges
3401 * and to set the edge anchor.
3403 * The code after computing `cur_len' to shift `edge' and `edge2'
3404 * is equivalent to the snippet below (part of `ta_latin_hint_edges'):
3407 * if cur_len < = 64:
3414 * org_center = edge_orig + org_len / 2
3415 * cur_pos1 = ROUND(org_center)
3417 * error1 = ABS(org_center - (cur_pos1 - u_off))
3418 * error2 = ABS(org_center - (cur_pos1 + d_off))
3419 * if (error1 < error2):
3420 * cur_pos1 = cur_pos1 - u_off
3422 * cur_pos1 = cur_pos1 + d_off
3424 * edge = cur_pos1 - cur_len / 2
3425 * edge2 = edge + cur_len
3428 * edge = ROUND(edge_orig)
3430 * in: edge2_is_serif
3432 * edge_point (in twilight zone)
3433 * edge2_point (in twilight zone)
3434 * ... stuff for bci_align_segments (edge) ...
3443 #define sal_u_off sal_temp1
3445 #define sal_d_off sal_temp2
3447 #define sal_org_len sal_temp3
3449 unsigned char FPGM(bci_anchor
) [] =
3456 /* store anchor point number in `sal_anchor' */
3461 WS
, /* sal_anchor = edge_point */
3465 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
3473 DUP
, /* s: edge2 edge is_round is_serif edge2 edge edge */
3474 MDAP_noround
, /* set rp0 and rp1 to `edge_point' (for ALIGNRP below) */
3476 MD_orig_ZP2_0
, /* s: edge2 edge is_round is_serif org_len */
3484 cvtl_stem_width_function
,
3486 CALL
, /* s: edge2 edge cur_len */
3491 LT
, /* cur_len < 96 */
3496 LTEQ
, /* cur_len <= 64 */
3514 SWAP
, /* s: edge2 cur_len edge */
3515 DUP
, /* s: edge2 cur_len edge edge */
3524 ADD
, /* s: edge2 cur_len edge org_center */
3529 CALL
, /* s: edge2 cur_len edge org_center cur_pos1 */
3534 SUB
, /* s: edge2 cur_len edge cur_pos1 (org_center - cur_pos1) */
3541 ABS
, /* s: edge2 cur_len edge cur_pos1 (org_center - cur_pos1) error1 */
3548 ABS
, /* s: edge2 cur_len edge cur_pos1 error1 error2 */
3550 LT
, /* error1 < error2 */
3555 SUB
, /* cur_pos1 = cur_pos1 - u_off */
3561 ADD
, /* cur_pos1 = cur_pos1 + d_off */
3562 EIF
, /* s: edge2 cur_len edge cur_pos1 */
3570 SUB
, /* s: edge2 cur_len edge (cur_pos1 - cur_len/2) */
3574 CINDEX
, /* s: edge2 cur_len edge (cur_pos1 - cur_len/2) edge */
3577 SHPIX
, /* edge = cur_pos1 - cur_len/2 */
3579 SWAP
, /* s: cur_len edge2 */
3581 ALIGNRP
, /* align `edge2' with rp0 (still `edge') */
3583 SHPIX
, /* edge2 = edge1 + cur_len */
3586 POP
, /* s: edge2 edge */
3594 CALL
, /* s: edge2 edge edge_pos round(edge_orig_pos) */
3597 SHPIX
, /* edge = round(edge_orig) */
3599 /* clean up stack */
3606 SZP1
, /* set zp1 to normal zone 1 */
3616 * bci_action_anchor_serif
3617 * bci_action_anchor_round
3618 * bci_action_anchor_round_serif
3620 * Higher-level routines for calling `bci_anchor'.
3623 unsigned char FPGM(bci_action_anchor
) [] =
3640 unsigned char FPGM(bci_action_anchor_serif
) [] =
3644 bci_action_anchor_serif
,
3657 unsigned char FPGM(bci_action_anchor_round
) [] =
3661 bci_action_anchor_round
,
3674 unsigned char FPGM(bci_action_anchor_round_serif
) [] =
3678 bci_action_anchor_round_serif
,
3693 * bci_action_blue_anchor
3695 * Handle the BLUE_ANCHOR action to align an edge with a blue zone
3696 * and to set the edge anchor.
3698 * in: anchor_point (in twilight zone)
3700 * edge_point (in twilight zone)
3701 * ... stuff for bci_align_segments (edge) ...
3705 * uses: bci_action_blue
3708 unsigned char FPGM(bci_action_blue_anchor
) [] =
3712 bci_action_blue_anchor
,
3715 /* store anchor point number in `sal_anchor' */
3733 * Handle the BLUE action to align an edge with a blue zone.
3736 * edge_point (in twilight zone)
3737 * ... stuff for bci_align_segments (edge) ...
3740 unsigned char FPGM(bci_action_blue
) [] =
3749 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
3751 /* move `edge_point' to `blue_cvt_idx' position; */
3752 /* note that we can't use MIAP since this would modify */
3753 /* the twilight point's original coordinates also */
3757 MDAP_noround
, /* set rp0 and rp1 to `edge' */
3759 GC_cur
, /* s: new_pos edge edge_pos */
3762 SUB
, /* s: edge (new_pos - edge_pos) */
3768 SZP1
, /* set zp1 to normal zone 1 */
3779 * Common code for bci_action_serif routines.
3782 unsigned char FPGM(bci_serif_common
) [] =
3791 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
3798 MINDEX
, /* s: [...] serif serif serif serif base */
3800 MDAP_noround
, /* set rp0 and rp1 to `base_point' */
3803 ALIGNRP
, /* align `serif_point' with `base_point' */
3804 SHPIX
, /* serif = base + (serif_orig_pos - base_orig_pos) */
3814 * Move an edge if necessary to stay within a lower bound.
3820 unsigned char FPGM(bci_lower_bound
) [] =
3827 SWAP
, /* s: edge bound */
3829 MDAP_noround
, /* set rp0 and rp1 to `bound' */
3834 GC_cur
, /* s: edge bound_pos edge_pos */
3835 GT
, /* edge_pos < bound_pos */
3838 ALIGNRP
, /* align `edge' to `bound' */
3841 MDAP_noround
, /* set rp0 and rp1 to `edge_point' */
3846 SZP1
, /* set zp1 to normal zone 1 */
3857 * Move an edge if necessary to stay within an upper bound.
3863 unsigned char FPGM(bci_upper_bound
) [] =
3870 SWAP
, /* s: edge bound */
3872 MDAP_noround
, /* set rp0 and rp1 to `bound' */
3877 GC_cur
, /* s: edge bound_pos edge_pos */
3878 LT
, /* edge_pos > bound_pos */
3881 ALIGNRP
, /* align `edge' to `bound' */
3884 MDAP_noround
, /* set rp0 and rp1 to `edge_point' */
3889 SZP1
, /* set zp1 to normal zone 1 */
3898 * bci_upper_lower_bound
3900 * Move an edge if necessary to stay within a lower and lower bound.
3907 unsigned char FPGM(bci_upper_lower_bound
) [] =
3911 bci_upper_lower_bound
,
3914 SWAP
, /* s: upper serif lower */
3916 MDAP_noround
, /* set rp0 and rp1 to `lower' */
3921 GC_cur
, /* s: upper serif lower_pos serif_pos */
3922 GT
, /* serif_pos < lower_pos */
3925 ALIGNRP
, /* align `serif' to `lower' */
3928 SWAP
, /* s: serif upper */
3930 MDAP_noround
, /* set rp0 and rp1 to `upper' */
3935 GC_cur
, /* s: serif upper_pos serif_pos */
3936 LT
, /* serif_pos > upper_pos */
3939 ALIGNRP
, /* align `serif' to `upper' */
3942 MDAP_noround
, /* set rp0 and rp1 to `serif_point' */
3947 SZP1
, /* set zp1 to normal zone 1 */
3958 * Handle the SERIF action to align a serif with its base.
3960 * in: serif_point (in twilight zone)
3961 * base_point (in twilight zone)
3962 * ... stuff for bci_align_segments (serif) ...
3964 * uses: bci_serif_common
3967 unsigned char FPGM(bci_action_serif
) [] =
3978 MDAP_noround
, /* set rp0 and rp1 to `serif_point' */
3983 SZP1
, /* set zp1 to normal zone 1 */
3992 * bci_action_serif_lower_bound
3994 * Handle the SERIF action to align a serif with its base, then moving it
3995 * again if necessary to stay within a lower bound.
3997 * in: serif_point (in twilight zone)
3998 * base_point (in twilight zone)
3999 * edge[-1] (in twilight zone)
4000 * ... stuff for bci_align_segments (serif) ...
4002 * uses: bci_serif_common
4006 unsigned char FPGM(bci_action_serif_lower_bound
) [] =
4010 bci_action_serif_lower_bound
,
4027 * bci_action_serif_upper_bound
4029 * Handle the SERIF action to align a serif with its base, then moving it
4030 * again if necessary to stay within an upper bound.
4032 * in: serif_point (in twilight zone)
4033 * base_point (in twilight zone)
4034 * edge[1] (in twilight zone)
4035 * ... stuff for bci_align_segments (serif) ...
4037 * uses: bci_serif_common
4041 unsigned char FPGM(bci_action_serif_upper_bound
) [] =
4045 bci_action_serif_upper_bound
,
4062 * bci_action_serif_upper_lower_bound
4064 * Handle the SERIF action to align a serif with its base, then moving it
4065 * again if necessary to stay within a lower and upper bound.
4067 * in: serif_point (in twilight zone)
4068 * base_point (in twilight zone)
4069 * edge[-1] (in twilight zone)
4070 * edge[1] (in twilight zone)
4071 * ... stuff for bci_align_segments (serif) ...
4073 * uses: bci_serif_common
4074 * bci_upper_lower_bound
4077 unsigned char FPGM(bci_action_serif_upper_lower_bound
) [] =
4081 bci_action_serif_upper_lower_bound
,
4086 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
4093 bci_upper_lower_bound
,
4102 * bci_serif_anchor_common
4104 * Common code for bci_action_serif_anchor routines.
4107 unsigned char FPGM(bci_serif_anchor_common
) [] =
4111 bci_serif_anchor_common
,
4116 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
4122 WS
, /* sal_anchor = edge_point */
4132 CALL
, /* s: [...] edge edge edge_pos round(edge_orig_pos) */
4135 SHPIX
, /* edge = round(edge_orig) */
4143 * bci_action_serif_anchor
4145 * Handle the SERIF_ANCHOR action to align a serif and to set the edge
4148 * in: edge_point (in twilight zone)
4149 * ... stuff for bci_align_segments (edge) ...
4151 * uses: bci_serif_anchor_common
4154 unsigned char FPGM(bci_action_serif_anchor
) [] =
4158 bci_action_serif_anchor
,
4162 bci_serif_anchor_common
,
4165 MDAP_noround
, /* set rp0 and rp1 to `edge' */
4170 SZP1
, /* set zp1 to normal zone 1 */
4179 * bci_action_serif_anchor_lower_bound
4181 * Handle the SERIF_ANCHOR action to align a serif and to set the edge
4182 * anchor, then moving it again if necessary to stay within a lower
4185 * in: edge_point (in twilight zone)
4186 * edge[-1] (in twilight zone)
4187 * ... stuff for bci_align_segments (edge) ...
4189 * uses: bci_serif_anchor_common
4193 unsigned char FPGM(bci_action_serif_anchor_lower_bound
) [] =
4197 bci_action_serif_anchor_lower_bound
,
4201 bci_serif_anchor_common
,
4214 * bci_action_serif_anchor_upper_bound
4216 * Handle the SERIF_ANCHOR action to align a serif and to set the edge
4217 * anchor, then moving it again if necessary to stay within an upper
4220 * in: edge_point (in twilight zone)
4221 * edge[1] (in twilight zone)
4222 * ... stuff for bci_align_segments (edge) ...
4224 * uses: bci_serif_anchor_common
4228 unsigned char FPGM(bci_action_serif_anchor_upper_bound
) [] =
4232 bci_action_serif_anchor_upper_bound
,
4236 bci_serif_anchor_common
,
4249 * bci_action_serif_anchor_upper_lower_bound
4251 * Handle the SERIF_ANCHOR action to align a serif and to set the edge
4252 * anchor, then moving it again if necessary to stay within a lower and
4255 * in: edge_point (in twilight zone)
4256 * edge[-1] (in twilight zone)
4257 * edge[1] (in twilight zone)
4258 * ... stuff for bci_align_segments (edge) ...
4260 * uses: bci_serif_anchor_common
4261 * bci_upper_lower_bound
4264 unsigned char FPGM(bci_action_serif_anchor_upper_lower_bound
) [] =
4268 bci_action_serif_anchor_upper_lower_bound
,
4272 bci_serif_anchor_common
,
4276 bci_upper_lower_bound
,
4285 * bci_serif_link1_common
4287 * Common code for bci_action_serif_link1 routines.
4290 unsigned char FPGM(bci_serif_link1_common
) [] =
4294 bci_serif_link1_common
,
4299 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
4303 CINDEX
, /* s: [...] after edge before after */
4306 CINDEX
, /* s: [...] after edge before after before */
4310 EQ
, /* after_orig_pos == before_orig_pos */
4311 IF
, /* s: [...] after edge before */
4312 MDAP_noround
, /* set rp0 and rp1 to `before' */
4314 ALIGNRP
, /* align `edge' with `before' */
4319 /* we have to execute `a*b/c', with b/c very near to 1: */
4320 /* to avoid overflow while retaining precision, */
4321 /* we transform this to `a + a * (b-c)/c' */
4325 CINDEX
, /* s: [...] after edge before edge */
4328 CINDEX
, /* s: [...] after edge before edge before */
4329 MD_orig_ZP2_0
, /* a = edge_orig_pos - before_orig_pos */
4334 CINDEX
, /* s: [...] after edge before a a after */
4337 CINDEX
, /* s: [...] after edge before a a after before */
4338 MD_orig_ZP2_0
, /* c = after_orig_pos - before_orig_pos */
4342 CINDEX
, /* s: [...] after edge before a a c after */
4345 CINDEX
, /* s: [...] after edge before a a c after before */
4346 MD_cur
, /* b = after_pos - before_pos */
4350 CINDEX
, /* s: [...] after edge before a a c b c */
4356 MUL
, /* (b-c) in 16.16 format */
4358 DIV
, /* s: [...] after edge before a a (b-c)/c */
4360 MUL
, /* a * (b-c)/c * 2^10 */
4364 DIV
, /* a * (b-c)/c */
4368 MDAP_noround
, /* set rp0 and rp1 to `before' */
4369 SWAP
, /* s: [...] after a*b/c edge */
4372 ALIGNRP
, /* align `edge' with `before' */
4374 SHPIX
, /* shift `edge' by `a*b/c' */
4376 SWAP
, /* s: [...] edge after */
4386 * bci_action_serif_link1
4388 * Handle the SERIF_LINK1 action to align a serif, depending on edges
4391 * in: before_point (in twilight zone)
4392 * edge_point (in twilight zone)
4393 * after_point (in twilight zone)
4394 * ... stuff for bci_align_segments (edge) ...
4396 * uses: bci_serif_link1_common
4399 unsigned char FPGM(bci_action_serif_link1
) [] =
4403 bci_action_serif_link1
,
4407 bci_serif_link1_common
,
4410 MDAP_noround
, /* set rp0 and rp1 to `edge' */
4415 SZP1
, /* set zp1 to normal zone 1 */
4424 * bci_action_serif_link1_lower_bound
4426 * Handle the SERIF_LINK1 action to align a serif, depending on edges
4427 * before and after. Additionally, move the serif again if necessary to
4428 * stay within a lower bound.
4430 * in: before_point (in twilight zone)
4431 * edge_point (in twilight zone)
4432 * after_point (in twilight zone)
4433 * edge[-1] (in twilight zone)
4434 * ... stuff for bci_align_segments (edge) ...
4436 * uses: bci_serif_link1_common
4440 unsigned char FPGM(bci_action_serif_link1_lower_bound
) [] =
4444 bci_action_serif_link1_lower_bound
,
4448 bci_serif_link1_common
,
4461 * bci_action_serif_link1_upper_bound
4463 * Handle the SERIF_LINK1 action to align a serif, depending on edges
4464 * before and after. Additionally, move the serif again if necessary to
4465 * stay within an upper bound.
4467 * in: before_point (in twilight zone)
4468 * edge_point (in twilight zone)
4469 * after_point (in twilight zone)
4470 * edge[1] (in twilight zone)
4471 * ... stuff for bci_align_segments (edge) ...
4473 * uses: bci_serif_link1_common
4477 unsigned char FPGM(bci_action_serif_link1_upper_bound
) [] =
4481 bci_action_serif_link1_upper_bound
,
4485 bci_serif_link1_common
,
4498 * bci_action_serif_link1_upper_lower_bound
4500 * Handle the SERIF_LINK1 action to align a serif, depending on edges
4501 * before and after. Additionally, move the serif again if necessary to
4502 * stay within a lower and upper bound.
4504 * in: before_point (in twilight zone)
4505 * edge_point (in twilight zone)
4506 * after_point (in twilight zone)
4507 * edge[-1] (in twilight zone)
4508 * edge[1] (in twilight zone)
4509 * ... stuff for bci_align_segments (edge) ...
4511 * uses: bci_serif_link1_common
4512 * bci_upper_lower_bound
4515 unsigned char FPGM(bci_action_serif_link1_upper_lower_bound
) [] =
4519 bci_action_serif_link1_upper_lower_bound
,
4523 bci_serif_link1_common
,
4527 bci_upper_lower_bound
,
4536 * bci_serif_link2_common
4538 * Common code for bci_action_serif_link2 routines.
4541 unsigned char FPGM(bci_serif_link2_common
) [] =
4545 bci_serif_link2_common
,
4550 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
4552 DUP
, /* s: [...] edge edge */
4556 DUP
, /* s: [...] edge edge anchor anchor */
4557 MDAP_noround
, /* set rp0 and rp1 to `sal_anchor' */
4568 DIV
, /* delta = (edge_orig_pos - anchor_orig_pos + 16) & ~31 */
4573 ALIGNRP
, /* align `edge' with `sal_anchor' */
4575 SHPIX
, /* shift `edge' by `delta' */
4583 * bci_action_serif_link2
4585 * Handle the SERIF_LINK2 action to align a serif relative to the anchor.
4587 * in: edge_point (in twilight zone)
4588 * ... stuff for bci_align_segments (edge) ...
4590 * uses: bci_serif_link2_common
4593 unsigned char FPGM(bci_action_serif_link2
) [] =
4597 bci_action_serif_link2
,
4601 bci_serif_link2_common
,
4604 MDAP_noround
, /* set rp0 and rp1 to `edge' */
4609 SZP1
, /* set zp1 to normal zone 1 */
4618 * bci_action_serif_link2_lower_bound
4620 * Handle the SERIF_LINK2 action to align a serif relative to the anchor.
4621 * Additionally, move the serif again if necessary to stay within a lower
4624 * in: edge_point (in twilight zone)
4625 * edge[-1] (in twilight zone)
4626 * ... stuff for bci_align_segments (edge) ...
4628 * uses: bci_serif_link2_common
4632 unsigned char FPGM(bci_action_serif_link2_lower_bound
) [] =
4636 bci_action_serif_link2_lower_bound
,
4640 bci_serif_link2_common
,
4653 * bci_action_serif_link2_upper_bound
4655 * Handle the SERIF_LINK2 action to align a serif relative to the anchor.
4656 * Additionally, move the serif again if necessary to stay within an upper
4659 * in: edge_point (in twilight zone)
4660 * edge[1] (in twilight zone)
4661 * ... stuff for bci_align_segments (edge) ...
4663 * uses: bci_serif_link2_common
4667 unsigned char FPGM(bci_action_serif_link2_upper_bound
) [] =
4671 bci_action_serif_link2_upper_bound
,
4675 bci_serif_link2_common
,
4688 * bci_action_serif_link2_upper_lower_bound
4690 * Handle the SERIF_LINK2 action to align a serif relative to the anchor.
4691 * Additionally, move the serif again if necessary to stay within a lower
4694 * in: edge_point (in twilight zone)
4695 * edge[-1] (in twilight zone)
4696 * edge[1] (in twilight zone)
4697 * ... stuff for bci_align_segments (edge) ...
4699 * uses: bci_serif_link2_common
4700 * bci_upper_lower_bound
4703 unsigned char FPGM(bci_action_serif_link2_upper_lower_bound
) [] =
4707 bci_action_serif_link2_upper_lower_bound
,
4711 bci_serif_link2_common
,
4715 bci_upper_lower_bound
,
4726 * This is the top-level glyph hinting function which parses the arguments
4727 * on the stack and calls subroutines.
4729 * in: action_0_func_idx
4735 * uses: bci_action_ip_before
4736 * bci_action_ip_after
4738 * bci_action_ip_between
4740 * bci_action_adjust_bound
4741 * bci_action_adjust_bound_serif
4742 * bci_action_adjust_bound_round
4743 * bci_action_adjust_bound_round_serif
4745 * bci_action_stem_bound
4746 * bci_action_stem_bound_serif
4747 * bci_action_stem_bound_round
4748 * bci_action_stem_bound_round_serif
4751 * bci_action_link_serif
4752 * bci_action_link_round
4753 * bci_action_link_round_serif
4756 * bci_action_anchor_serif
4757 * bci_action_anchor_round
4758 * bci_action_anchor_round_serif
4760 * bci_action_blue_anchor
4763 * bci_action_adjust_serif
4764 * bci_action_adjust_round
4765 * bci_action_adjust_round_serif
4768 * bci_action_stem_serif
4769 * bci_action_stem_round
4770 * bci_action_stem_round_serif
4775 * bci_action_serif_lower_bound
4776 * bci_action_serif_upper_bound
4777 * bci_action_serif_upper_lower_bound
4779 * bci_action_serif_anchor
4780 * bci_action_serif_anchor_lower_bound
4781 * bci_action_serif_anchor_upper_bound
4782 * bci_action_serif_anchor_upper_lower_bound
4784 * bci_action_serif_link1
4785 * bci_action_serif_link1_lower_bound
4786 * bci_action_serif_link1_upper_bound
4787 * bci_action_serif_link1_upper_lower_bound
4789 * bci_action_serif_link2
4790 * bci_action_serif_link2_lower_bound
4791 * bci_action_serif_link2_upper_bound
4792 * bci_action_serif_link2_upper_lower_bound
4794 * CVT: cvtl_is_subglyph
4797 unsigned char FPGM(bci_hint_glyph
) [] =
4805 /* loop until all data on stack is used */
4814 JROT
, /* goto start_loop */
4818 SZP2
, /* set zp2 to normal zone 1 */
4826 #define COPY_FPGM(func_name) \
4827 memcpy(buf_p, fpgm_ ## func_name, \
4828 sizeof (fpgm_ ## func_name)); \
4829 buf_p += sizeof (fpgm_ ## func_name) \
4832 TA_table_build_fpgm(FT_Byte
** fpgm
,
4842 buf_len
= sizeof (FPGM(bci_round
))
4843 + sizeof (FPGM(bci_smooth_stem_width_a
))
4845 + sizeof (FPGM(bci_smooth_stem_width_b
))
4847 + sizeof (FPGM(bci_smooth_stem_width_c
))
4848 + sizeof (FPGM(bci_get_best_width
))
4849 + sizeof (FPGM(bci_strong_stem_width_a
))
4851 + sizeof (FPGM(bci_strong_stem_width_b
))
4852 + sizeof (FPGM(bci_loop
))
4853 + sizeof (FPGM(bci_cvt_rescale
))
4854 + sizeof (FPGM(bci_blue_round_a
))
4856 + sizeof (FPGM(bci_blue_round_b
))
4857 + sizeof (FPGM(bci_decrement_component_counter
))
4858 + sizeof (FPGM(bci_get_point_extrema
))
4859 + sizeof (FPGM(bci_nibbles
))
4861 + sizeof (FPGM(bci_create_segment
))
4862 + sizeof (FPGM(bci_create_segments
))
4863 + sizeof (FPGM(bci_create_segments_0
))
4864 + sizeof (FPGM(bci_create_segments_1
))
4865 + sizeof (FPGM(bci_create_segments_2
))
4866 + sizeof (FPGM(bci_create_segments_3
))
4867 + sizeof (FPGM(bci_create_segments_4
))
4868 + sizeof (FPGM(bci_create_segments_5
))
4869 + sizeof (FPGM(bci_create_segments_6
))
4870 + sizeof (FPGM(bci_create_segments_7
))
4871 + sizeof (FPGM(bci_create_segments_8
))
4872 + sizeof (FPGM(bci_create_segments_9
))
4873 + sizeof (FPGM(bci_create_segments_composite
))
4874 + sizeof (FPGM(bci_create_segments_composite_0
))
4875 + sizeof (FPGM(bci_create_segments_composite_1
))
4876 + sizeof (FPGM(bci_create_segments_composite_2
))
4877 + sizeof (FPGM(bci_create_segments_composite_3
))
4878 + sizeof (FPGM(bci_create_segments_composite_4
))
4879 + sizeof (FPGM(bci_create_segments_composite_5
))
4880 + sizeof (FPGM(bci_create_segments_composite_6
))
4881 + sizeof (FPGM(bci_create_segments_composite_7
))
4882 + sizeof (FPGM(bci_create_segments_composite_8
))
4883 + sizeof (FPGM(bci_create_segments_composite_9
))
4884 + sizeof (FPGM(bci_align_segment
))
4885 + sizeof (FPGM(bci_align_segments
))
4887 + sizeof (FPGM(bci_scale_contour
))
4888 + sizeof (FPGM(bci_scale_glyph
))
4889 + sizeof (FPGM(bci_scale_composite_glyph
))
4890 + sizeof (FPGM(bci_shift_contour
))
4891 + sizeof (FPGM(bci_shift_subglyph
))
4893 + sizeof (FPGM(bci_ip_outer_align_point
))
4894 + sizeof (FPGM(bci_ip_on_align_points
))
4895 + sizeof (FPGM(bci_ip_between_align_point
))
4896 + sizeof (FPGM(bci_ip_between_align_points
))
4898 + sizeof (FPGM(bci_adjust_common
))
4899 + sizeof (FPGM(bci_stem_common
))
4900 + sizeof (FPGM(bci_serif_common
))
4901 + sizeof (FPGM(bci_serif_anchor_common
))
4902 + sizeof (FPGM(bci_serif_link1_common
))
4903 + sizeof (FPGM(bci_serif_link2_common
))
4905 + sizeof (FPGM(bci_lower_bound
))
4906 + sizeof (FPGM(bci_upper_bound
))
4907 + sizeof (FPGM(bci_upper_lower_bound
))
4909 + sizeof (FPGM(bci_action_ip_before
))
4910 + sizeof (FPGM(bci_action_ip_after
))
4911 + sizeof (FPGM(bci_action_ip_on
))
4912 + sizeof (FPGM(bci_action_ip_between
))
4914 + sizeof (FPGM(bci_adjust_bound
))
4915 + sizeof (FPGM(bci_action_adjust_bound
))
4916 + sizeof (FPGM(bci_action_adjust_bound_serif
))
4917 + sizeof (FPGM(bci_action_adjust_bound_round
))
4918 + sizeof (FPGM(bci_action_adjust_bound_round_serif
))
4919 + sizeof (FPGM(bci_stem_bound
))
4920 + sizeof (FPGM(bci_action_stem_bound
))
4921 + sizeof (FPGM(bci_action_stem_bound_serif
))
4922 + sizeof (FPGM(bci_action_stem_bound_round
))
4923 + sizeof (FPGM(bci_action_stem_bound_round_serif
))
4924 + sizeof (FPGM(bci_link
))
4925 + sizeof (FPGM(bci_action_link
))
4926 + sizeof (FPGM(bci_action_link_serif
))
4927 + sizeof (FPGM(bci_action_link_round
))
4928 + sizeof (FPGM(bci_action_link_round_serif
))
4929 + sizeof (FPGM(bci_anchor
))
4930 + sizeof (FPGM(bci_action_anchor
))
4931 + sizeof (FPGM(bci_action_anchor_serif
))
4932 + sizeof (FPGM(bci_action_anchor_round
))
4933 + sizeof (FPGM(bci_action_anchor_round_serif
))
4934 + sizeof (FPGM(bci_action_blue_anchor
))
4935 + sizeof (FPGM(bci_adjust
))
4936 + sizeof (FPGM(bci_action_adjust
))
4937 + sizeof (FPGM(bci_action_adjust_serif
))
4938 + sizeof (FPGM(bci_action_adjust_round
))
4939 + sizeof (FPGM(bci_action_adjust_round_serif
))
4940 + sizeof (FPGM(bci_stem
))
4941 + sizeof (FPGM(bci_action_stem
))
4942 + sizeof (FPGM(bci_action_stem_serif
))
4943 + sizeof (FPGM(bci_action_stem_round
))
4944 + sizeof (FPGM(bci_action_stem_round_serif
))
4945 + sizeof (FPGM(bci_action_blue
))
4946 + sizeof (FPGM(bci_action_serif
))
4947 + sizeof (FPGM(bci_action_serif_lower_bound
))
4948 + sizeof (FPGM(bci_action_serif_upper_bound
))
4949 + sizeof (FPGM(bci_action_serif_upper_lower_bound
))
4950 + sizeof (FPGM(bci_action_serif_anchor
))
4951 + sizeof (FPGM(bci_action_serif_anchor_lower_bound
))
4952 + sizeof (FPGM(bci_action_serif_anchor_upper_bound
))
4953 + sizeof (FPGM(bci_action_serif_anchor_upper_lower_bound
))
4954 + sizeof (FPGM(bci_action_serif_link1
))
4955 + sizeof (FPGM(bci_action_serif_link1_lower_bound
))
4956 + sizeof (FPGM(bci_action_serif_link1_upper_bound
))
4957 + sizeof (FPGM(bci_action_serif_link1_upper_lower_bound
))
4958 + sizeof (FPGM(bci_action_serif_link2
))
4959 + sizeof (FPGM(bci_action_serif_link2_lower_bound
))
4960 + sizeof (FPGM(bci_action_serif_link2_upper_bound
))
4961 + sizeof (FPGM(bci_action_serif_link2_upper_lower_bound
))
4963 + sizeof (FPGM(bci_hint_glyph
));
4965 /* buffer length must be a multiple of four */
4966 len
= (buf_len
+ 3) & ~3;
4967 buf
= (FT_Byte
*)malloc(len
);
4969 return FT_Err_Out_Of_Memory
;
4971 /* pad end of buffer with zeros */
4972 buf
[len
- 1] = 0x00;
4973 buf
[len
- 2] = 0x00;
4974 buf
[len
- 3] = 0x00;
4976 /* copy font program into buffer and fill in the missing variables */
4979 COPY_FPGM(bci_round
);
4980 COPY_FPGM(bci_smooth_stem_width_a
);
4981 *(buf_p
++) = (unsigned char)CVT_VERT_WIDTHS_OFFSET(font
);
4982 COPY_FPGM(bci_smooth_stem_width_b
);
4983 *(buf_p
++) = (unsigned char)CVT_VERT_WIDTHS_OFFSET(font
);
4984 COPY_FPGM(bci_smooth_stem_width_c
);
4985 COPY_FPGM(bci_get_best_width
);
4986 COPY_FPGM(bci_strong_stem_width_a
);
4987 *(buf_p
++) = (unsigned char)CVT_VERT_WIDTHS_OFFSET(font
);
4988 *(buf_p
++) = (unsigned char)CVT_VERT_WIDTHS_SIZE(font
);
4989 COPY_FPGM(bci_strong_stem_width_b
);
4990 COPY_FPGM(bci_loop
);
4991 COPY_FPGM(bci_cvt_rescale
);
4992 COPY_FPGM(bci_blue_round_a
);
4993 *(buf_p
++) = (unsigned char)CVT_BLUES_SIZE(font
);
4994 COPY_FPGM(bci_blue_round_b
);
4995 COPY_FPGM(bci_decrement_component_counter
);
4996 COPY_FPGM(bci_get_point_extrema
);
4997 COPY_FPGM(bci_nibbles
);
4999 COPY_FPGM(bci_create_segment
);
5000 COPY_FPGM(bci_create_segments
);
5001 COPY_FPGM(bci_create_segments_0
);
5002 COPY_FPGM(bci_create_segments_1
);
5003 COPY_FPGM(bci_create_segments_2
);
5004 COPY_FPGM(bci_create_segments_3
);
5005 COPY_FPGM(bci_create_segments_4
);
5006 COPY_FPGM(bci_create_segments_5
);
5007 COPY_FPGM(bci_create_segments_6
);
5008 COPY_FPGM(bci_create_segments_7
);
5009 COPY_FPGM(bci_create_segments_8
);
5010 COPY_FPGM(bci_create_segments_9
);
5011 COPY_FPGM(bci_create_segments_composite
);
5012 COPY_FPGM(bci_create_segments_composite_0
);
5013 COPY_FPGM(bci_create_segments_composite_1
);
5014 COPY_FPGM(bci_create_segments_composite_2
);
5015 COPY_FPGM(bci_create_segments_composite_3
);
5016 COPY_FPGM(bci_create_segments_composite_4
);
5017 COPY_FPGM(bci_create_segments_composite_5
);
5018 COPY_FPGM(bci_create_segments_composite_6
);
5019 COPY_FPGM(bci_create_segments_composite_7
);
5020 COPY_FPGM(bci_create_segments_composite_8
);
5021 COPY_FPGM(bci_create_segments_composite_9
);
5022 COPY_FPGM(bci_align_segment
);
5023 COPY_FPGM(bci_align_segments
);
5025 COPY_FPGM(bci_scale_contour
);
5026 COPY_FPGM(bci_scale_glyph
);
5027 COPY_FPGM(bci_scale_composite_glyph
);
5028 COPY_FPGM(bci_shift_contour
);
5029 COPY_FPGM(bci_shift_subglyph
);
5031 COPY_FPGM(bci_ip_outer_align_point
);
5032 COPY_FPGM(bci_ip_on_align_points
);
5033 COPY_FPGM(bci_ip_between_align_point
);
5034 COPY_FPGM(bci_ip_between_align_points
);
5036 COPY_FPGM(bci_adjust_common
);
5037 COPY_FPGM(bci_stem_common
);
5038 COPY_FPGM(bci_serif_common
);
5039 COPY_FPGM(bci_serif_anchor_common
);
5040 COPY_FPGM(bci_serif_link1_common
);
5041 COPY_FPGM(bci_serif_link2_common
);
5043 COPY_FPGM(bci_lower_bound
);
5044 COPY_FPGM(bci_upper_bound
);
5045 COPY_FPGM(bci_upper_lower_bound
);
5047 COPY_FPGM(bci_action_ip_before
);
5048 COPY_FPGM(bci_action_ip_after
);
5049 COPY_FPGM(bci_action_ip_on
);
5050 COPY_FPGM(bci_action_ip_between
);
5052 COPY_FPGM(bci_adjust_bound
);
5053 COPY_FPGM(bci_action_adjust_bound
);
5054 COPY_FPGM(bci_action_adjust_bound_serif
);
5055 COPY_FPGM(bci_action_adjust_bound_round
);
5056 COPY_FPGM(bci_action_adjust_bound_round_serif
);
5057 COPY_FPGM(bci_stem_bound
);
5058 COPY_FPGM(bci_action_stem_bound
);
5059 COPY_FPGM(bci_action_stem_bound_serif
);
5060 COPY_FPGM(bci_action_stem_bound_round
);
5061 COPY_FPGM(bci_action_stem_bound_round_serif
);
5062 COPY_FPGM(bci_link
);
5063 COPY_FPGM(bci_action_link
);
5064 COPY_FPGM(bci_action_link_serif
);
5065 COPY_FPGM(bci_action_link_round
);
5066 COPY_FPGM(bci_action_link_round_serif
);
5067 COPY_FPGM(bci_anchor
);
5068 COPY_FPGM(bci_action_anchor
);
5069 COPY_FPGM(bci_action_anchor_serif
);
5070 COPY_FPGM(bci_action_anchor_round
);
5071 COPY_FPGM(bci_action_anchor_round_serif
);
5072 COPY_FPGM(bci_action_blue_anchor
);
5073 COPY_FPGM(bci_adjust
);
5074 COPY_FPGM(bci_action_adjust
);
5075 COPY_FPGM(bci_action_adjust_serif
);
5076 COPY_FPGM(bci_action_adjust_round
);
5077 COPY_FPGM(bci_action_adjust_round_serif
);
5078 COPY_FPGM(bci_stem
);
5079 COPY_FPGM(bci_action_stem
);
5080 COPY_FPGM(bci_action_stem_serif
);
5081 COPY_FPGM(bci_action_stem_round
);
5082 COPY_FPGM(bci_action_stem_round_serif
);
5083 COPY_FPGM(bci_action_blue
);
5084 COPY_FPGM(bci_action_serif
);
5085 COPY_FPGM(bci_action_serif_lower_bound
);
5086 COPY_FPGM(bci_action_serif_upper_bound
);
5087 COPY_FPGM(bci_action_serif_upper_lower_bound
);
5088 COPY_FPGM(bci_action_serif_anchor
);
5089 COPY_FPGM(bci_action_serif_anchor_lower_bound
);
5090 COPY_FPGM(bci_action_serif_anchor_upper_bound
);
5091 COPY_FPGM(bci_action_serif_anchor_upper_lower_bound
);
5092 COPY_FPGM(bci_action_serif_link1
);
5093 COPY_FPGM(bci_action_serif_link1_lower_bound
);
5094 COPY_FPGM(bci_action_serif_link1_upper_bound
);
5095 COPY_FPGM(bci_action_serif_link1_upper_lower_bound
);
5096 COPY_FPGM(bci_action_serif_link2
);
5097 COPY_FPGM(bci_action_serif_link2_lower_bound
);
5098 COPY_FPGM(bci_action_serif_link2_upper_bound
);
5099 COPY_FPGM(bci_action_serif_link2_upper_lower_bound
);
5101 COPY_FPGM(bci_hint_glyph
);
5104 *fpgm_len
= buf_len
;
5111 TA_sfnt_build_fpgm_table(SFNT
* sfnt
,
5114 FT_Error error
= FT_Err_Ok
;
5116 SFNT_Table
* glyf_table
= &font
->tables
[sfnt
->glyf_idx
];
5117 glyf_Data
* data
= (glyf_Data
*)glyf_table
->data
;
5123 error
= TA_sfnt_add_table_info(sfnt
);
5127 /* `glyf', `cvt', `fpgm', and `prep' are always used in parallel */
5128 if (glyf_table
->processed
)
5130 sfnt
->table_infos
[sfnt
->num_table_infos
- 1] = data
->fpgm_idx
;
5134 error
= TA_table_build_fpgm(&fpgm_buf
, &fpgm_len
, font
);
5138 if (fpgm_len
> sfnt
->max_instructions
)
5139 sfnt
->max_instructions
= fpgm_len
;
5141 /* in case of success, `fpgm_buf' gets linked */
5142 /* and is eventually freed in `TA_font_unload' */
5143 error
= TA_font_add_table(font
,
5144 &sfnt
->table_infos
[sfnt
->num_table_infos
- 1],
5145 TTAG_fpgm
, fpgm_len
, fpgm_buf
);
5149 data
->fpgm_idx
= sfnt
->table_infos
[sfnt
->num_table_infos
- 1];
5155 /* end of tafpgm.c */