4 * Copyright (C) 2011-2013 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.
81 unsigned char FPGM(bci_round
) [] =
99 * bci_smooth_stem_width
101 * This is the equivalent to the following code from function
102 * `ta_latin_compute_stem_width':
110 * else if base_is_round:
116 * delta = ABS(dist - std_width)
127 * delta = delta - dist
130 * dist = dist + delta
131 * else if delta < 32:
133 * else if delta < 54:
136 * dist = dist + delta
152 * CVT: cvtl_is_extra_light
158 unsigned char FPGM(bci_smooth_stem_width_a
) [] =
162 bci_smooth_stem_width
,
166 ABS
, /* s: base_is_round stem_is_serif width dist */
171 LT
, /* dist < 3*64 */
175 MINDEX
, /* s: base_is_round width dist (dist<3*64) stem_is_serif */
176 AND
, /* stem_is_serif && dist < 3*64 */
181 OR
, /* (stem_is_serif && dist < 3*64) || is_extra_light */
183 IF
, /* s: base_is_round width dist */
189 ROLL
, /* s: width dist base_is_round */
190 IF
, /* s: width dist */
195 IF
, /* s: width dist */
206 IF
, /* s: width dist */
213 DUP
, /* s: width dist dist */
218 /* %c, index of std_width */
220 unsigned char FPGM(bci_smooth_stem_width_b
) [] =
225 ABS
, /* s: width dist delta */
230 IF
, /* s: width dist */
236 /* %c, index of std_width */
238 unsigned char FPGM(bci_smooth_stem_width_c
) [] =
241 RCVT
, /* dist = std_width */
253 DUP
, /* s: width dist dist */
256 LT
, /* dist < 3*64 */
258 DUP
, /* s: width delta dist */
259 FLOOR
, /* dist = FLOOR(dist) */
260 DUP
, /* s: width delta dist dist */
262 ROLL
, /* s: width dist delta dist */
263 SUB
, /* delta = delta - dist */
265 DUP
, /* s: width dist delta delta */
269 IF
, /* s: width dist delta */
270 ADD
, /* dist = dist + delta */
281 ADD
, /* dist = dist + 10 */
292 ADD
, /* dist = dist + 54 */
295 ADD
, /* dist = dist + delta */
304 CALL
, /* dist = round(dist) */
309 SWAP
, /* s: dist width */
314 NEG
, /* dist = -dist */
326 * An auxiliary function for `bci_strong_stem_width'.
328 * in: n (initialized with CVT index for first vertical width)
340 unsigned char FPGM(bci_get_best_width
) [] =
348 RCVT
, /* s: dist n w */
352 CINDEX
, /* s: dist n w w dist */
354 ABS
, /* s: dist n w d */
358 RS
, /* s: dist n w d d best */
368 WS
, /* reference = w */
385 * bci_strong_stem_width
387 * This is the equivalent to the following code (function
388 * `ta_latin_snap_width' and some lines from
389 * `ta_latin_compute_stem_width'):
391 * best = 64 + 32 + 2;
395 * for n in 0 .. num_widths:
403 * if dist >= reference:
404 * if dist < ROUND(reference) + 48:
407 * if dist > ROUND(reference) - 48:
420 * stem_is_serif (unused)
421 * base_is_round (unused)
430 * uses: bci_get_best_width
434 unsigned char FPGM(bci_strong_stem_width_a
) [] =
438 bci_strong_stem_width
,
446 ABS
, /* s: width dist */
451 WS
, /* sal_best = 98 */
457 WS
, /* sal_ref = width */
462 /* %c, first index of vertical widths */
463 /* %c, number of vertical widths */
465 unsigned char FPGM(bci_strong_stem_width_b
) [] =
471 POP
, /* s: width dist */
475 RS
, /* s: width dist dist reference */
482 CALL
, /* s: width dist reference dist dist ROUND(reference) */
487 ROLL
, /* s: width dist reference dist ROUND(reference) 48 reference dist */
489 LTEQ
, /* dist >= reference */
490 IF
, /* s: width dist reference dist ROUND(reference) 48 */
492 LT
, /* dist < ROUND(reference) + 48 */
496 GT
, /* dist > ROUND(reference) - 48 */
500 SWAP
, /* s: width reference dist */
507 GTEQ
, /* dist >= 64 */
511 CALL
, /* dist = ROUND(dist) */
519 SWAP
, /* s: dist width */
524 NEG
, /* dist = -dist */
535 * An auxiliary function for `bci_loop'.
537 * sal: sal_i (gets incremented by 2 after execution)
540 * uses: func[sal_func]
543 unsigned char FPGM(bci_loop_do
) [] =
560 ADD
, /* sal_i = sal_i + 2 */
571 * Take a range `start'..`end' and a function number and apply the
572 * associated function to the range elements `start', `start+2',
579 * sal: sal_i (counter initialized with `start')
580 * sal_func (`func_num')
585 unsigned char FPGM(bci_loop
) [] =
595 WS
, /* sal_func = func_num */
602 WS
, /* sal_i = start */
610 ADD
, /* number of loops ((end - start) / 2 + 1) */
624 * Rescale CVT value by `cvtl_scale' (in 16.16 format).
626 * The scaling factor `cvtl_scale' isn't stored as `b/c' but as `(b-c)/c';
627 * consequently, the calculation `a * b/c' is done as `a + delta' with
628 * `delta = a * (b-c)/c'. This avoids overflow.
638 unsigned char FPGM(bci_cvt_rescale
) [] =
663 * Round a blue ref value and adjust its corresponding shoot value.
672 unsigned char FPGM(bci_blue_round_a
) [] =
681 RCVT
, /* s: ref_idx ref_idx ref */
687 SWAP
, /* s: ref_idx ref_idx round(ref) ref */
695 unsigned char FPGM(bci_blue_round_b
) [] =
700 ADD
, /* s: ref_idx ref_idx round(ref) ref shoot_idx */
702 RCVT
, /* s: ref_idx ref_idx round(ref) ref shoot_idx shoot */
704 ROLL
, /* s: ref_idx ref_idx round(ref) shoot_idx shoot ref */
706 SUB
, /* s: ref_idx ref_idx round(ref) shoot_idx dist */
708 ABS
, /* s: ref_idx ref_idx round(ref) shoot_idx dist delta */
733 SWAP
, /* s: ref_idx ref_idx round(ref) shoot_idx delta dist */
738 NEG
, /* delta = -delta */
745 SUB
, /* s: ref_idx ref_idx round(ref) shoot_idx (round(ref) - delta) */
752 ADD
, /* s: (ref_idx + 1) */
760 * bci_decrement_component_counter
762 * An auxiliary function for composite glyphs.
764 * CVT: cvtl_is_subglyph
767 unsigned char FPGM(bci_decrement_component_counter
) [] =
771 bci_decrement_component_counter
,
774 /* decrement `cvtl_is_subglyph' counter */
790 * bci_get_point_extrema
792 * An auxiliary function for `bci_create_segment'.
802 unsigned char FPGM(bci_get_point_extrema
) [] =
806 bci_get_point_extrema
,
815 /* check whether `point' is a new minimum */
818 RS
, /* s: point point point point_min */
820 /* if distance is negative, we have a new minimum */
824 IF
, /* s: point point */
832 /* check whether `point' is a new maximum */
835 RS
, /* s: point point point_max */
837 /* if distance is positive, we have a new maximum */
857 * Pop a byte with two delta arguments in its nibbles and push the
858 * expanded arguments separately as two bytes.
860 * in: 16 * (end - start) + (start - base)
865 * sal: sal_base (set to `end' at return)
869 unsigned char FPGM(bci_nibbles
) [] =
879 DIV
, /* s: in hnibble */
884 MUL
, /* s: in hnibble (hnibble * 16) */
887 SUB
, /* s: hnibble lnibble */
892 ADD
, /* s: hnibble start */
895 ADD
, /* s: start end */
901 WS
, /* sal_base = end */
911 * bci_number_set_is_element
913 * Pop values from stack until it is empty. If one of them is equal to
914 * the current PPEM value, set `cvtl_is_element' to 1 (and to 0
921 * CVT: cvtl_is_element
924 unsigned char FPGM(bci_number_set_is_element
) [] =
928 bci_number_set_is_element
,
946 JROT
, /* goto start_loop if stack depth != 0 */
954 * bci_number_set_is_element2
956 * Pop value ranges from stack until it is empty. If one of them contains
957 * the current PPEM value, set `cvtl_is_element' to 1 (and to 0
960 * in: ppem_range_1_start
966 * CVT: cvtl_is_element
969 unsigned char FPGM(bci_number_set_is_element2
) [] =
973 bci_number_set_is_element2
,
997 JROT
, /* goto start_loop if stack depth != 0 */
1005 * bci_create_segment
1007 * Store start and end point of a segment in the storage area,
1008 * then construct a point in the twilight zone to represent it.
1010 * This function is used by `bci_create_segments'.
1014 * [last (if wrap-around segment)]
1015 * [first (if wrap-around segment)]
1017 * sal: sal_i (start of current segment)
1018 * sal_j (current twilight point)
1022 * sal_num_packed_segments
1028 * uses: bci_get_point_extrema
1031 * If `sal_num_packed_segments' is > 0, the start/end pair is stored as
1032 * delta values in nibbles (without a wrap-around segment).
1035 unsigned char FPGM(bci_create_segment
) [] =
1044 sal_num_packed_segments
,
1049 sal_num_packed_segments
,
1050 sal_num_packed_segments
,
1055 WS
, /* sal_num_packed_segments = sal_num_packed_segments - 1 */
1068 WS
, /* sal[sal_i] = start */
1070 /* initialize inner loop(s) */
1075 WS
, /* sal_point_min = start */
1080 WS
, /* sal_point_max = start */
1084 SZPS
, /* set zp0, zp1, and zp2 to normal zone 1 */
1090 CINDEX
, /* s: start end end start */
1091 LT
, /* start > end */
1093 /* we have a wrap-around segment with two more arguments */
1094 /* to give the last and first point of the contour, respectively; */
1095 /* our job is to store a segment `start'-`last', */
1096 /* and to get extrema for the two segments */
1097 /* `start'-`last' and `first'-`end' */
1099 /* s: first last start end */
1108 WS
, /* sal[sal_i + 1] = last */
1111 ROLL
, /* s: first end last start */
1114 SWAP
, /* s: first end start last start */
1115 SUB
, /* s: first end start loop_count */
1118 bci_get_point_extrema
,
1120 /* clean up stack */
1123 SWAP
, /* s: end first */
1128 ROLL
, /* s: (first - 1) (first - 1) end */
1130 SUB
, /* s: (first - 1) loop_count */
1133 bci_get_point_extrema
,
1135 /* clean up stack */
1138 ELSE
, /* s: start end */
1147 WS
, /* sal[sal_i + 1] = end */
1152 SUB
, /* s: start loop_count */
1155 bci_get_point_extrema
,
1157 /* clean up stack */
1161 /* the twilight point representing a segment */
1162 /* is in the middle between the minimum and maximum */
1174 DIV
, /* s: middle_pos */
1176 DO_SCALE
, /* middle_pos = middle_pos * scale */
1178 /* write it to temporary CVT location */
1182 SZP0
, /* set zp0 to twilight zone 0 */
1186 /* create twilight point with index `sal_j' */
1199 ADD
, /* twilight_point = twilight_point + 1 */
1208 * bci_create_segments
1210 * This is the top-level entry function.
1212 * It pops point ranges from the stack to define segments, computes
1213 * twilight points to represent segments, and finally calls
1214 * `bci_hint_glyph' to handle the rest.
1216 * in: num_packed_segments
1220 * [contour_last 0 (if wrap-around segment)]
1221 * [contour_first 0 (if wrap-around segment)]
1224 * [contour_last 0 (if wrap-around segment)]
1225 * [contour_first 0 (if wrap-around segment)]
1227 * segment_start_(N-1)
1229 * [contour_last (N-1) (if wrap-around segment)]
1230 * [contour_first (N-1) (if wrap-around segment)]
1231 * ... stuff for bci_hint_glyph ...
1233 * sal: sal_i (start of current segment)
1234 * sal_j (current twilight point)
1235 * sal_num_packed_segments
1236 * sal_base (the base for delta values in nibbles)
1238 * CVT: cvtl_is_subglyph
1240 * uses: bci_create_segment
1244 * If `num_packed_segments' is set to p, the first p start/end pairs are
1245 * stored as delta values in nibbles, with the `start' delta in the lower
1246 * nibble (and there are no wrap-around segments). For example, if the
1247 * first three pairs are 1/3, 5/8, and 12/13, the topmost three bytes on the
1248 * stack are 0x21, 0x32, and 0x14.
1252 unsigned char FPGM(bci_create_segments
) [] =
1256 bci_create_segments
,
1259 /* only do something if we are not a subglyph */
1266 /* all our measurements are taken along the y axis */
1270 sal_num_packed_segments
,
1278 SUB
, /* delta = (2*num_segments - 1) */
1288 WS
, /* sal_base = 0 */
1289 WS
, /* sal_j = 0 (point offset) */
1292 ADD
, /* s: ... sal_segment_offset (sal_segment_offset + delta) */
1313 * bci_create_segments_X
1315 * Top-level routines for calling `bci_create_segments'.
1318 unsigned char FPGM(bci_create_segments_0
) [] =
1322 bci_create_segments_0
,
1327 bci_create_segments
,
1334 unsigned char FPGM(bci_create_segments_1
) [] =
1338 bci_create_segments_1
,
1343 bci_create_segments
,
1350 unsigned char FPGM(bci_create_segments_2
) [] =
1354 bci_create_segments_2
,
1359 bci_create_segments
,
1366 unsigned char FPGM(bci_create_segments_3
) [] =
1370 bci_create_segments_3
,
1375 bci_create_segments
,
1382 unsigned char FPGM(bci_create_segments_4
) [] =
1386 bci_create_segments_4
,
1391 bci_create_segments
,
1398 unsigned char FPGM(bci_create_segments_5
) [] =
1402 bci_create_segments_5
,
1407 bci_create_segments
,
1414 unsigned char FPGM(bci_create_segments_6
) [] =
1418 bci_create_segments_6
,
1423 bci_create_segments
,
1430 unsigned char FPGM(bci_create_segments_7
) [] =
1434 bci_create_segments_7
,
1439 bci_create_segments
,
1446 unsigned char FPGM(bci_create_segments_8
) [] =
1450 bci_create_segments_8
,
1455 bci_create_segments
,
1462 unsigned char FPGM(bci_create_segments_9
) [] =
1466 bci_create_segments_9
,
1471 bci_create_segments
,
1480 * bci_create_segments_composite
1482 * The same as `bci_create_segments'.
1483 * It also decrements the composite component counter.
1485 * sal: sal_num_packed_segments
1486 * sal_segment_offset
1488 * CVT: cvtl_is_subglyph
1490 * uses: bci_decrement_component_counter
1491 * bci_create_segment
1496 unsigned char FPGM(bci_create_segments_composite
) [] =
1500 bci_create_segments_composite
,
1504 bci_decrement_component_counter
,
1507 /* only do something if we are not a subglyph */
1514 /* all our measurements are taken along the y axis */
1518 sal_num_packed_segments
,
1526 SUB
, /* delta = (2*num_segments - 1) */
1536 WS
, /* sal_base = 0 */
1537 WS
, /* sal_j = 0 (point offset) */
1540 ADD
, /* s: ... sal_segment_offset (sal_segment_offset + delta) */
1561 * bci_create_segments_composite_X
1563 * Top-level routines for calling `bci_create_segments_composite'.
1566 unsigned char FPGM(bci_create_segments_composite_0
) [] =
1570 bci_create_segments_composite_0
,
1575 bci_create_segments_composite
,
1582 unsigned char FPGM(bci_create_segments_composite_1
) [] =
1586 bci_create_segments_composite_1
,
1591 bci_create_segments_composite
,
1598 unsigned char FPGM(bci_create_segments_composite_2
) [] =
1602 bci_create_segments_composite_2
,
1607 bci_create_segments_composite
,
1614 unsigned char FPGM(bci_create_segments_composite_3
) [] =
1618 bci_create_segments_composite_3
,
1623 bci_create_segments_composite
,
1630 unsigned char FPGM(bci_create_segments_composite_4
) [] =
1634 bci_create_segments_composite_4
,
1639 bci_create_segments_composite
,
1646 unsigned char FPGM(bci_create_segments_composite_5
) [] =
1650 bci_create_segments_composite_5
,
1655 bci_create_segments_composite
,
1662 unsigned char FPGM(bci_create_segments_composite_6
) [] =
1666 bci_create_segments_composite_6
,
1671 bci_create_segments_composite
,
1678 unsigned char FPGM(bci_create_segments_composite_7
) [] =
1682 bci_create_segments_composite_7
,
1687 bci_create_segments_composite
,
1694 unsigned char FPGM(bci_create_segments_composite_8
) [] =
1698 bci_create_segments_composite_8
,
1703 bci_create_segments_composite
,
1710 unsigned char FPGM(bci_create_segments_composite_9
) [] =
1714 bci_create_segments_composite_9
,
1719 bci_create_segments_composite
,
1730 * An auxiliary function for `bci_align_segment'.
1737 unsigned char FPGM(bci_align_point
) [] =
1745 ALIGNRP
, /* align point with rp0 */
1759 * Align all points in a segment to the twilight point in rp0.
1760 * zp0 and zp1 must be set to 0 (twilight) and 1 (normal), respectively.
1764 * sal: sal_segment_offset
1766 * uses: bci_align_point
1769 unsigned char FPGM(bci_align_segment
) [] =
1776 /* we need the values of `sal_segment_offset + 2*segment_index' */
1777 /* and `sal_segment_offset + 2*segment_index + 1' */
1789 RS
, /* s: first last */
1793 CINDEX
, /* s: first last first */
1797 ADD
, /* s: first loop_count */
1802 /* clean up stack */
1811 * bci_align_segments
1813 * Align segments to the twilight point in rp0.
1814 * zp0 and zp1 must be set to 0 (twilight) and 1 (normal), respectively.
1823 * uses: bci_align_segment
1826 unsigned char FPGM(bci_align_segments
) [] =
1849 * Scale a contour using two points giving the maximum and minimum
1852 * It expects that no point on the contour is touched.
1861 unsigned char FPGM(bci_scale_contour
) [] =
1872 DO_SCALE
, /* min_pos_new = min_pos * scale */
1877 /* don't scale a single-point contour twice */
1886 DO_SCALE
, /* max_pos_new = max_pos * scale */
1903 * Scale a glyph using a list of points (two points per contour, giving
1904 * the maximum and mininum coordinates).
1906 * It expects that no point in the glyph is touched.
1908 * Note that the point numbers are sorted in ascending order;
1909 * `min_point_X' and `max_point_X' thus refer to the two extrema of a
1910 * contour without specifying which one is the minimum and maximum.
1912 * in: num_contours (N)
1921 * CVT: cvtl_is_subglyph
1923 * uses: bci_scale_contour
1926 unsigned char FPGM(bci_scale_glyph
) [] =
1933 /* only do something if we are not a subglyph */
1940 /* all our measurements are taken along the y axis */
1945 SZPS
, /* set zp0, zp1, and zp2 to normal zone 1 */
1953 SZP2
, /* set zp2 to normal zone 1 */
1966 * bci_scale_composite_glyph
1968 * The same as `bci_scale_glyph'.
1969 * It also decrements the composite component counter.
1971 * CVT: cvtl_is_subglyph
1973 * uses: bci_decrement_component_counter
1977 unsigned char FPGM(bci_scale_composite_glyph
) [] =
1981 bci_scale_composite_glyph
,
1985 bci_decrement_component_counter
,
1988 /* only do something if we are not a subglyph */
1995 /* all our measurements are taken along the y axis */
2000 SZPS
, /* set zp0, zp1, and zp2 to normal zone 1 */
2008 SZP2
, /* set zp2 to normal zone 1 */
2023 * Shift a contour by a given amount.
2025 * It expects that rp1 (pointed to by zp0) is set up properly; zp2 must
2026 * point to the normal zone 1.
2033 unsigned char FPGM(bci_shift_contour
) [] =
2041 SHC_rp1
, /* shift `contour' by (rp1_pos - rp1_orig_pos) */
2053 * bci_shift_subglyph
2055 * Shift a subglyph. To be more specific, it corrects the already applied
2056 * subglyph offset (if any) from the `glyf' table which needs to be scaled
2059 * If this function is called, a point `x' in the subglyph has been scaled
2060 * already (during the hinting of the subglyph itself), and `offset' has
2061 * been applied also:
2063 * x -> x * scale + offset (1)
2065 * However, the offset should be applied first, then the scaling:
2067 * x -> (x + offset) * scale (2)
2069 * Our job is now to transform (1) to (2); a simple calculation shows that
2070 * we have to shift all points of the subglyph by
2072 * offset * scale - offset = offset * (scale - 1)
2074 * Note that `cvtl_scale' is equal to the above `scale - 1'.
2076 * in: offset (in FUnits)
2080 * CVT: cvtl_funits_to_pixels
2088 unsigned char FPGM(bci_shift_subglyph
) [] =
2098 cvtl_funits_to_pixels
,
2099 RCVT
, /* scaling factor FUnits -> pixels */
2106 /* the autohinter always rounds offsets */
2109 CALL
, /* offset = round(offset) */
2118 DIV
, /* delta = offset * (scale - 1) */
2120 /* and round again */
2123 CALL
, /* offset = round(offset) */
2127 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
2129 /* we create twilight point 0 as a reference point, */
2130 /* setting the original position to zero (using `cvtl_temp') */
2138 MIAP_noround
, /* rp0 and rp1 now point to twilight point 0 */
2140 SWAP
, /* s: first_contour num_contours 0 delta */
2141 SHPIX
, /* rp1_pos - rp1_orig_pos = delta */
2146 SZP2
, /* set zp2 to normal zone 1 */
2155 * bci_ip_outer_align_point
2157 * Auxiliary function for `bci_action_ip_before' and
2158 * `bci_action_ip_after'.
2160 * It expects rp0 to contain the edge for alignment, zp0 set to twilight
2161 * zone, and both zp1 and zp2 set to normal zone.
2165 * sal: sal_i (edge_orig_pos)
2171 unsigned char FPGM(bci_ip_outer_align_point
) [] =
2175 bci_ip_outer_align_point
,
2179 ALIGNRP
, /* align `point' with `edge' */
2182 DO_SCALE
, /* point_orig_pos = point_orig_pos * scale */
2187 SUB
, /* s: point (point_orig_pos - edge_orig_pos) */
2196 * bci_ip_on_align_points
2198 * Auxiliary function for `bci_action_ip_on'.
2200 * in: edge (in twilight zone)
2208 unsigned char FPGM(bci_ip_on_align_points
) [] =
2212 bci_ip_on_align_points
,
2215 MDAP_noround
, /* set rp0 and rp1 to `edge' */
2226 * bci_ip_between_align_point
2228 * Auxiliary function for `bci_ip_between_align_points'.
2230 * It expects rp0 to contain the edge for alignment, zp0 set to twilight
2231 * zone, and both zp1 and zp2 set to normal zone.
2235 * sal: sal_i (edge_orig_pos)
2236 * sal_j (stretch_factor)
2242 unsigned char FPGM(bci_ip_between_align_point
) [] =
2246 bci_ip_between_align_point
,
2250 ALIGNRP
, /* align `point' with `edge' */
2253 DO_SCALE
, /* point_orig_pos = point_orig_pos * scale */
2258 SUB
, /* s: point (point_orig_pos - edge_orig_pos) */
2262 MUL
, /* s: point delta */
2271 * bci_ip_between_align_points
2273 * Auxiliary function for `bci_action_ip_between'.
2275 * in: after_edge (in twilight zone)
2276 * before_edge (in twilight zone)
2283 * sal: sal_i (before_orig_pos)
2284 * sal_j (stretch_factor)
2286 * uses: bci_ip_between_align_point
2289 unsigned char FPGM(bci_ip_between_align_points
) [] =
2293 bci_ip_between_align_points
,
2299 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
2301 DUP
, /* s: ... before after before before */
2302 MDAP_noround
, /* set rp0 and rp1 to `before' */
2304 GC_orig
, /* s: ... before after before before_orig_pos */
2308 WS
, /* sal_i = before_orig_pos */
2311 CINDEX
, /* s: ... before after before after */
2312 MD_cur
, /* a = after_pos - before_pos */
2315 MD_orig_ZP2_0
, /* b = after_orig_pos - before_orig_pos */
2321 POP
, /* avoid division by zero */
2327 WS
, /* sal_j = stretch_factor */
2330 bci_ip_between_align_point
,
2333 SZP2
, /* set zp2 to normal zone 1 */
2334 SZP1
, /* set zp1 to normal zone 1 */
2343 * bci_action_ip_before
2345 * Handle `ip_before' data to align points located before the first edge.
2347 * in: first_edge (in twilight zone)
2354 * sal: sal_i (first_edge_orig_pos)
2356 * uses: bci_ip_outer_align_point
2359 unsigned char FPGM(bci_action_ip_before
) [] =
2363 bci_action_ip_before
,
2368 SZP2
, /* set zp2 to twilight zone 0 */
2375 WS
, /* sal_i = first_edge_orig_pos */
2381 SZP2
, /* set zp2 to normal zone 1 */
2382 SZP1
, /* set zp1 to normal zone 1 */
2383 SZP0
, /* set zp0 to twilight zone 0 */
2385 MDAP_noround
, /* set rp0 and rp1 to `first_edge' */
2388 bci_ip_outer_align_point
,
2397 * bci_action_ip_after
2399 * Handle `ip_after' data to align points located after the last edge.
2401 * in: last_edge (in twilight zone)
2408 * sal: sal_i (last_edge_orig_pos)
2410 * uses: bci_ip_outer_align_point
2413 unsigned char FPGM(bci_action_ip_after
) [] =
2417 bci_action_ip_after
,
2422 SZP2
, /* set zp2 to twilight zone 0 */
2429 WS
, /* sal_i = last_edge_orig_pos */
2435 SZP2
, /* set zp2 to normal zone 1 */
2436 SZP1
, /* set zp1 to normal zone 1 */
2437 SZP0
, /* set zp0 to twilight zone 0 */
2439 MDAP_noround
, /* set rp0 and rp1 to `last_edge' */
2442 bci_ip_outer_align_point
,
2453 * Handle `ip_on' data to align points located on an edge coordinate (but
2454 * not part of an edge).
2456 * in: loop_counter (M)
2457 * edge_1 (in twilight zone)
2458 * loop_counter (N_1)
2463 * edge_2 (in twilight zone)
2464 * loop_counter (N_2)
2470 * edge_M (in twilight zone)
2471 * loop_counter (N_M)
2477 * uses: bci_ip_on_align_points
2480 unsigned char FPGM(bci_action_ip_on
) [] =
2490 SZP1
, /* set zp1 to normal zone 1 */
2491 SZP0
, /* set zp0 to twilight zone 0 */
2494 bci_ip_on_align_points
,
2503 * bci_action_ip_between
2505 * Handle `ip_between' data to align points located between two edges.
2507 * in: loop_counter (M)
2508 * before_edge_1 (in twilight zone)
2509 * after_edge_1 (in twilight zone)
2510 * loop_counter (N_1)
2515 * before_edge_2 (in twilight zone)
2516 * after_edge_2 (in twilight zone)
2517 * loop_counter (N_2)
2523 * before_edge_M (in twilight zone)
2524 * after_edge_M (in twilight zone)
2525 * loop_counter (N_M)
2531 * uses: bci_ip_between_align_points
2534 unsigned char FPGM(bci_action_ip_between
) [] =
2538 bci_action_ip_between
,
2542 bci_ip_between_align_points
,
2553 * Common code for bci_action_adjust routines.
2555 * uses: func[cvtl_stem_width_function]
2558 unsigned char FPGM(bci_adjust_common
) [] =
2567 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
2571 CINDEX
, /* s: [...] edge2 edge is_round is_serif edge2 */
2574 CINDEX
, /* s: [...] edge2 edge is_round is_serif edge2 edge */
2575 MD_orig_ZP2_0
, /* s: [...] edge2 edge is_round is_serif org_len */
2578 cvtl_stem_width_function
,
2581 NEG
, /* s: [...] edge2 edge -cur_len */
2583 ROLL
, /* s: [...] edge -cur_len edge2 */
2584 MDAP_noround
, /* set rp0 and rp1 to `edge2' */
2587 DUP
, /* s: [...] -cur_len edge edge edge */
2588 ALIGNRP
, /* align `edge' with `edge2' */
2590 SHPIX
, /* shift `edge' by -cur_len */
2600 * Handle the ADJUST_BOUND action to align an edge of a stem if the other
2601 * edge of the stem has already been moved, then moving it again if
2602 * necessary to stay bound.
2604 * in: edge2_is_serif
2606 * edge_point (in twilight zone)
2607 * edge2_point (in twilight zone)
2608 * edge[-1] (in twilight zone)
2609 * ... stuff for bci_align_segments (edge) ...
2611 * uses: bci_adjust_common
2612 * bci_align_segments
2615 unsigned char FPGM(bci_adjust_bound
) [] =
2626 SWAP
, /* s: edge edge[-1] */
2628 MDAP_noround
, /* set rp0 and rp1 to `edge[-1]' */
2633 GC_cur
, /* s: edge edge[-1]_pos edge_pos */
2634 GT
, /* edge_pos < edge[-1]_pos */
2637 ALIGNRP
, /* align `edge' to `edge[-1]' */
2640 MDAP_noround
, /* set rp0 and rp1 to `edge' */
2645 SZP1
, /* set zp1 to normal zone 1 */
2654 * bci_action_adjust_bound
2655 * bci_action_adjust_bound_serif
2656 * bci_action_adjust_bound_round
2657 * bci_action_adjust_bound_round_serif
2659 * Higher-level routines for calling `bci_adjust_bound'.
2662 unsigned char FPGM(bci_action_adjust_bound
) [] =
2666 bci_action_adjust_bound
,
2679 unsigned char FPGM(bci_action_adjust_bound_serif
) [] =
2683 bci_action_adjust_bound_serif
,
2696 unsigned char FPGM(bci_action_adjust_bound_round
) [] =
2700 bci_action_adjust_bound_round
,
2713 unsigned char FPGM(bci_action_adjust_bound_round_serif
) [] =
2717 bci_action_adjust_bound_round_serif
,
2734 * Handle the ADJUST action to align an edge of a stem if the other edge
2735 * of the stem has already been moved.
2737 * in: edge2_is_serif
2739 * edge_point (in twilight zone)
2740 * edge2_point (in twilight zone)
2741 * ... stuff for bci_align_segments (edge) ...
2743 * uses: bci_adjust_common
2744 * bci_align_segments
2747 unsigned char FPGM(bci_adjust
) [] =
2758 MDAP_noround
, /* set rp0 and rp1 to `edge' */
2763 SZP1
, /* set zp1 to normal zone 1 */
2773 * bci_action_adjust_serif
2774 * bci_action_adjust_round
2775 * bci_action_adjust_round_serif
2777 * Higher-level routines for calling `bci_adjust'.
2780 unsigned char FPGM(bci_action_adjust
) [] =
2797 unsigned char FPGM(bci_action_adjust_serif
) [] =
2801 bci_action_adjust_serif
,
2814 unsigned char FPGM(bci_action_adjust_round
) [] =
2818 bci_action_adjust_round
,
2831 unsigned char FPGM(bci_action_adjust_round_serif
) [] =
2835 bci_action_adjust_round_serif
,
2852 * Common code for bci_action_stem routines.
2859 * uses: func[cvtl_stem_width_function]
2864 #define sal_u_off sal_temp1
2866 #define sal_d_off sal_temp2
2868 #define sal_org_len sal_temp3
2870 #define sal_edge2 sal_temp3
2872 unsigned char FPGM(bci_stem_common
) [] =
2881 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
2889 DUP
, /* s: [...] edge2 edge is_round is_serif edge2 edge edge */
2890 MDAP_noround
, /* set rp0 and rp1 to `edge_point' (for ALIGNRP below) */
2892 MD_orig_ZP2_0
, /* s: [...] edge2 edge is_round is_serif org_len */
2900 cvtl_stem_width_function
,
2902 CALL
, /* s: [...] edge2 edge cur_len */
2907 LT
, /* cur_len < 96 */
2912 LTEQ
, /* cur_len <= 64 */
2930 SWAP
, /* s: [...] edge2 cur_len edge */
2935 DUP
, /* s: [...] edge2 cur_len edge edge anchor anchor */
2941 ADD
, /* s: [...] edge2 cur_len edge org_pos */
2948 ADD
, /* s: [...] edge2 cur_len edge org_center */
2953 CALL
, /* s: [...] edge2 cur_len edge org_center cur_pos1 */
2958 SUB
, /* s: ... cur_len edge cur_pos1 (org_center - cur_pos1) */
2965 ABS
, /* s: ... cur_len edge cur_pos1 (org_center - cur_pos1) delta1 */
2972 ABS
, /* s: [...] edge2 cur_len edge cur_pos1 delta1 delta2 */
2974 LT
, /* delta1 < delta2 */
2979 SUB
, /* cur_pos1 = cur_pos1 - u_off */
2985 ADD
, /* cur_pos1 = cur_pos1 + d_off */
2986 EIF
, /* s: [...] edge2 cur_len edge cur_pos1 */
2994 SUB
, /* arg = cur_pos1 - cur_len/2 */
2996 SWAP
, /* s: [...] edge2 cur_len arg edge */
3002 SWAP
, /* s: [...] edge2 cur_len edge edge arg edge */
3005 SHPIX
, /* edge = cur_pos1 - cur_len/2 */
3008 SWAP
, /* s: [...] edge2 cur_len edge */
3012 GC_cur
, /* s: [...] edge2 cur_len edge anchor_pos */
3020 ADD
, /* s: [...] edge2 cur_len edge org_pos */
3029 ADD
, /* s: [...] edge2 cur_len edge org_pos org_center */
3035 CALL
, /* cur_pos1 = ROUND(org_pos) */
3047 SUB
, /* s: [...] edge2 cur_len edge org_center cur_pos1 cur_pos2 */
3058 SUB
, /* s: ... cur_len edge cur_pos1 cur_pos2 (cur_len/2 - org_center) */
3065 ABS
, /* delta1 = ABS(cur_pos1 + cur_len / 2 - org_center) */
3071 ABS
, /* s: ... edge2 cur_len edge cur_pos1 cur_pos2 delta1 delta2 */
3072 LT
, /* delta1 < delta2 */
3074 POP
, /* arg = cur_pos1 */
3078 POP
, /* arg = cur_pos2 */
3079 EIF
, /* s: [...] edge2 cur_len edge arg */
3086 SWAP
, /* s: [...] edge2 cur_len edge edge arg edge */
3089 SHPIX
, /* edge = arg */
3090 EIF
, /* s: [...] edge2 cur_len edge */
3100 * Handle the STEM action to align two edges of a stem, then moving one
3101 * edge again if necessary to stay bound.
3103 * The code after computing `cur_len' to shift `edge' and `edge2'
3104 * is equivalent to the snippet below (part of `ta_latin_hint_edges'):
3107 * if cur_len < = 64:
3114 * org_pos = anchor + (edge_orig - anchor_orig);
3115 * org_center = org_pos + org_len / 2;
3117 * cur_pos1 = ROUND(org_center)
3118 * delta1 = ABS(org_center - (cur_pos1 - u_off))
3119 * delta2 = ABS(org_center - (cur_pos1 + d_off))
3120 * if (delta1 < delta2):
3121 * cur_pos1 = cur_pos1 - u_off
3123 * cur_pos1 = cur_pos1 + d_off
3125 * edge = cur_pos1 - cur_len / 2
3128 * org_pos = anchor + (edge_orig - anchor_orig)
3129 * org_center = org_pos + org_len / 2;
3131 * cur_pos1 = ROUND(org_pos)
3132 * delta1 = ABS(cur_pos1 + cur_len / 2 - org_center)
3133 * cur_pos2 = ROUND(org_pos + org_len) - cur_len
3134 * delta2 = ABS(cur_pos2 + cur_len / 2 - org_center)
3136 * if (delta1 < delta2):
3141 * edge2 = edge + cur_len
3143 * in: edge2_is_serif
3145 * edge_point (in twilight zone)
3146 * edge2_point (in twilight zone)
3147 * edge[-1] (in twilight zone)
3148 * ... stuff for bci_align_segments (edge) ...
3149 * ... stuff for bci_align_segments (edge2)...
3156 * uses: bci_stem_common
3157 * bci_align_segments
3160 unsigned char FPGM(bci_stem_bound
) [] =
3171 ROLL
, /* s: edge[-1] cur_len edge edge2 */
3174 ALIGNRP
, /* align `edge2' with rp0 (still `edge') */
3178 WS
, /* s: edge[-1] cur_len edge edge2 */
3180 SHPIX
, /* edge2 = edge + cur_len */
3182 SWAP
, /* s: edge edge[-1] */
3184 MDAP_noround
, /* set rp0 and rp1 to `edge[-1]' */
3189 GC_cur
, /* s: edge edge[-1]_pos edge_pos */
3190 GT
, /* edge_pos < edge[-1]_pos */
3193 ALIGNRP
, /* align `edge' to `edge[-1]' */
3196 MDAP_noround
, /* set rp0 and rp1 to `edge' */
3201 SZP1
, /* set zp1 to normal zone 1 */
3207 MDAP_noround
, /* set rp0 and rp1 to `edge2' */
3219 * bci_action_stem_bound
3220 * bci_action_stem_bound_serif
3221 * bci_action_stem_bound_round
3222 * bci_action_stem_bound_round_serif
3224 * Higher-level routines for calling `bci_stem_bound'.
3227 unsigned char FPGM(bci_action_stem_bound
) [] =
3231 bci_action_stem_bound
,
3244 unsigned char FPGM(bci_action_stem_bound_serif
) [] =
3248 bci_action_stem_bound_serif
,
3261 unsigned char FPGM(bci_action_stem_bound_round
) [] =
3265 bci_action_stem_bound_round
,
3278 unsigned char FPGM(bci_action_stem_bound_round_serif
) [] =
3282 bci_action_stem_bound_round_serif
,
3299 * Handle the STEM action to align two edges of a stem.
3301 * See `bci_stem_bound' for more details.
3303 * in: edge2_is_serif
3305 * edge_point (in twilight zone)
3306 * edge2_point (in twilight zone)
3307 * ... stuff for bci_align_segments (edge) ...
3308 * ... stuff for bci_align_segments (edge2)...
3315 * uses: bci_stem_common
3316 * bci_align_segments
3319 unsigned char FPGM(bci_stem
) [] =
3331 SWAP
, /* s: cur_len edge2 */
3334 ALIGNRP
, /* align `edge2' with rp0 (still `edge') */
3338 WS
, /* s: cur_len edge2 */
3340 SHPIX
, /* edge2 = edge + cur_len */
3345 SZP1
, /* set zp1 to normal zone 1 */
3351 MDAP_noround
, /* set rp0 and rp1 to `edge2' */
3363 * bci_action_stem_serif
3364 * bci_action_stem_round
3365 * bci_action_stem_round_serif
3367 * Higher-level routines for calling `bci_stem'.
3370 unsigned char FPGM(bci_action_stem
) [] =
3387 unsigned char FPGM(bci_action_stem_serif
) [] =
3391 bci_action_stem_serif
,
3404 unsigned char FPGM(bci_action_stem_round
) [] =
3408 bci_action_stem_round
,
3421 unsigned char FPGM(bci_action_stem_round_serif
) [] =
3425 bci_action_stem_round_serif
,
3442 * Handle the LINK action to link an edge to another one.
3446 * base_point (in twilight zone)
3447 * stem_point (in twilight zone)
3448 * ... stuff for bci_align_segments (base) ...
3450 * uses: func[cvtl_stem_width_function]
3451 * bci_align_segments
3454 unsigned char FPGM(bci_link
) [] =
3463 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
3471 DUP
, /* s: stem is_round is_serif stem base base */
3472 MDAP_noround
, /* set rp0 and rp1 to `base_point' (for ALIGNRP below) */
3474 MD_orig_ZP2_0
, /* s: stem is_round is_serif dist_orig */
3477 cvtl_stem_width_function
,
3479 CALL
, /* s: stem new_dist */
3483 ALIGNRP
, /* align `stem_point' with `base_point' */
3485 MDAP_noround
, /* set rp0 and rp1 to `stem_point' */
3487 SHPIX
, /* stem_point = base_point + new_dist */
3492 SZP1
, /* set zp1 to normal zone 1 */
3502 * bci_action_link_serif
3503 * bci_action_link_round
3504 * bci_action_link_round_serif
3506 * Higher-level routines for calling `bci_link'.
3509 unsigned char FPGM(bci_action_link
) [] =
3526 unsigned char FPGM(bci_action_link_serif
) [] =
3530 bci_action_link_serif
,
3543 unsigned char FPGM(bci_action_link_round
) [] =
3547 bci_action_link_round
,
3560 unsigned char FPGM(bci_action_link_round_serif
) [] =
3564 bci_action_link_round_serif
,
3581 * Handle the ANCHOR action to align two edges
3582 * and to set the edge anchor.
3584 * The code after computing `cur_len' to shift `edge' and `edge2'
3585 * is equivalent to the snippet below (part of `ta_latin_hint_edges'):
3588 * if cur_len < = 64:
3595 * org_center = edge_orig + org_len / 2
3596 * cur_pos1 = ROUND(org_center)
3598 * error1 = ABS(org_center - (cur_pos1 - u_off))
3599 * error2 = ABS(org_center - (cur_pos1 + d_off))
3600 * if (error1 < error2):
3601 * cur_pos1 = cur_pos1 - u_off
3603 * cur_pos1 = cur_pos1 + d_off
3605 * edge = cur_pos1 - cur_len / 2
3606 * edge2 = edge + cur_len
3609 * edge = ROUND(edge_orig)
3611 * in: edge2_is_serif
3613 * edge_point (in twilight zone)
3614 * edge2_point (in twilight zone)
3615 * ... stuff for bci_align_segments (edge) ...
3622 * uses: func[cvtl_stem_width_function]
3624 * bci_align_segments
3628 #define sal_u_off sal_temp1
3630 #define sal_d_off sal_temp2
3632 #define sal_org_len sal_temp3
3634 unsigned char FPGM(bci_anchor
) [] =
3641 /* store anchor point number in `sal_anchor' */
3646 WS
, /* sal_anchor = edge_point */
3650 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
3658 DUP
, /* s: edge2 edge is_round is_serif edge2 edge edge */
3659 MDAP_noround
, /* set rp0 and rp1 to `edge_point' (for ALIGNRP below) */
3661 MD_orig_ZP2_0
, /* s: edge2 edge is_round is_serif org_len */
3669 cvtl_stem_width_function
,
3671 CALL
, /* s: edge2 edge cur_len */
3676 LT
, /* cur_len < 96 */
3681 LTEQ
, /* cur_len <= 64 */
3699 SWAP
, /* s: edge2 cur_len edge */
3700 DUP
, /* s: edge2 cur_len edge edge */
3709 ADD
, /* s: edge2 cur_len edge org_center */
3714 CALL
, /* s: edge2 cur_len edge org_center cur_pos1 */
3719 SUB
, /* s: edge2 cur_len edge cur_pos1 (org_center - cur_pos1) */
3726 ABS
, /* s: edge2 cur_len edge cur_pos1 (org_center - cur_pos1) error1 */
3733 ABS
, /* s: edge2 cur_len edge cur_pos1 error1 error2 */
3735 LT
, /* error1 < error2 */
3740 SUB
, /* cur_pos1 = cur_pos1 - u_off */
3746 ADD
, /* cur_pos1 = cur_pos1 + d_off */
3747 EIF
, /* s: edge2 cur_len edge cur_pos1 */
3755 SUB
, /* s: edge2 cur_len edge (cur_pos1 - cur_len/2) */
3759 CINDEX
, /* s: edge2 cur_len edge (cur_pos1 - cur_len/2) edge */
3762 SHPIX
, /* edge = cur_pos1 - cur_len/2 */
3764 SWAP
, /* s: cur_len edge2 */
3766 ALIGNRP
, /* align `edge2' with rp0 (still `edge') */
3768 SHPIX
, /* edge2 = edge1 + cur_len */
3771 POP
, /* s: edge2 edge */
3779 CALL
, /* s: edge2 edge edge_pos round(edge_orig_pos) */
3782 SHPIX
, /* edge = round(edge_orig) */
3784 /* clean up stack */
3791 SZP1
, /* set zp1 to normal zone 1 */
3801 * bci_action_anchor_serif
3802 * bci_action_anchor_round
3803 * bci_action_anchor_round_serif
3805 * Higher-level routines for calling `bci_anchor'.
3808 unsigned char FPGM(bci_action_anchor
) [] =
3825 unsigned char FPGM(bci_action_anchor_serif
) [] =
3829 bci_action_anchor_serif
,
3842 unsigned char FPGM(bci_action_anchor_round
) [] =
3846 bci_action_anchor_round
,
3859 unsigned char FPGM(bci_action_anchor_round_serif
) [] =
3863 bci_action_anchor_round_serif
,
3878 * bci_action_blue_anchor
3880 * Handle the BLUE_ANCHOR action to align an edge with a blue zone
3881 * and to set the edge anchor.
3883 * in: anchor_point (in twilight zone)
3885 * edge_point (in twilight zone)
3886 * ... stuff for bci_align_segments (edge) ...
3890 * uses: bci_action_blue
3893 unsigned char FPGM(bci_action_blue_anchor
) [] =
3897 bci_action_blue_anchor
,
3900 /* store anchor point number in `sal_anchor' */
3918 * Handle the BLUE action to align an edge with a blue zone.
3921 * edge_point (in twilight zone)
3922 * ... stuff for bci_align_segments (edge) ...
3924 * uses: bci_align_segments
3927 unsigned char FPGM(bci_action_blue
) [] =
3936 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
3938 /* move `edge_point' to `blue_cvt_idx' position; */
3939 /* note that we can't use MIAP since this would modify */
3940 /* the twilight point's original coordinates also */
3944 MDAP_noround
, /* set rp0 and rp1 to `edge' */
3946 GC_cur
, /* s: new_pos edge edge_pos */
3949 SUB
, /* s: edge (new_pos - edge_pos) */
3955 SZP1
, /* set zp1 to normal zone 1 */
3966 * Common code for bci_action_serif routines.
3969 unsigned char FPGM(bci_serif_common
) [] =
3978 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
3985 MINDEX
, /* s: [...] serif serif serif serif base */
3987 MDAP_noround
, /* set rp0 and rp1 to `base_point' */
3990 ALIGNRP
, /* align `serif_point' with `base_point' */
3991 SHPIX
, /* serif = base + (serif_orig_pos - base_orig_pos) */
4001 * Move an edge if necessary to stay within a lower bound.
4006 * uses: bci_align_segments
4009 unsigned char FPGM(bci_lower_bound
) [] =
4016 SWAP
, /* s: edge bound */
4018 MDAP_noround
, /* set rp0 and rp1 to `bound' */
4023 GC_cur
, /* s: edge bound_pos edge_pos */
4024 GT
, /* edge_pos < bound_pos */
4027 ALIGNRP
, /* align `edge' to `bound' */
4030 MDAP_noround
, /* set rp0 and rp1 to `edge_point' */
4035 SZP1
, /* set zp1 to normal zone 1 */
4046 * Move an edge if necessary to stay within an upper bound.
4051 * uses: bci_align_segments
4054 unsigned char FPGM(bci_upper_bound
) [] =
4061 SWAP
, /* s: edge bound */
4063 MDAP_noround
, /* set rp0 and rp1 to `bound' */
4068 GC_cur
, /* s: edge bound_pos edge_pos */
4069 LT
, /* edge_pos > bound_pos */
4072 ALIGNRP
, /* align `edge' to `bound' */
4075 MDAP_noround
, /* set rp0 and rp1 to `edge_point' */
4080 SZP1
, /* set zp1 to normal zone 1 */
4089 * bci_upper_lower_bound
4091 * Move an edge if necessary to stay within a lower and lower bound.
4097 * uses: bci_align_segments
4100 unsigned char FPGM(bci_upper_lower_bound
) [] =
4104 bci_upper_lower_bound
,
4107 SWAP
, /* s: upper serif lower */
4109 MDAP_noround
, /* set rp0 and rp1 to `lower' */
4114 GC_cur
, /* s: upper serif lower_pos serif_pos */
4115 GT
, /* serif_pos < lower_pos */
4118 ALIGNRP
, /* align `serif' to `lower' */
4121 SWAP
, /* s: serif upper */
4123 MDAP_noround
, /* set rp0 and rp1 to `upper' */
4128 GC_cur
, /* s: serif upper_pos serif_pos */
4129 LT
, /* serif_pos > upper_pos */
4132 ALIGNRP
, /* align `serif' to `upper' */
4135 MDAP_noround
, /* set rp0 and rp1 to `serif_point' */
4140 SZP1
, /* set zp1 to normal zone 1 */
4151 * Handle the SERIF action to align a serif with its base.
4153 * in: serif_point (in twilight zone)
4154 * base_point (in twilight zone)
4155 * ... stuff for bci_align_segments (serif) ...
4157 * uses: bci_serif_common
4158 * bci_align_segments
4161 unsigned char FPGM(bci_action_serif
) [] =
4172 MDAP_noround
, /* set rp0 and rp1 to `serif_point' */
4177 SZP1
, /* set zp1 to normal zone 1 */
4186 * bci_action_serif_lower_bound
4188 * Handle the SERIF action to align a serif with its base, then moving it
4189 * again if necessary to stay within a lower bound.
4191 * in: serif_point (in twilight zone)
4192 * base_point (in twilight zone)
4193 * edge[-1] (in twilight zone)
4194 * ... stuff for bci_align_segments (serif) ...
4196 * uses: bci_serif_common
4200 unsigned char FPGM(bci_action_serif_lower_bound
) [] =
4204 bci_action_serif_lower_bound
,
4221 * bci_action_serif_upper_bound
4223 * Handle the SERIF action to align a serif with its base, then moving it
4224 * again if necessary to stay within an upper bound.
4226 * in: serif_point (in twilight zone)
4227 * base_point (in twilight zone)
4228 * edge[1] (in twilight zone)
4229 * ... stuff for bci_align_segments (serif) ...
4231 * uses: bci_serif_common
4235 unsigned char FPGM(bci_action_serif_upper_bound
) [] =
4239 bci_action_serif_upper_bound
,
4256 * bci_action_serif_upper_lower_bound
4258 * Handle the SERIF action to align a serif with its base, then moving it
4259 * again if necessary to stay within a lower and upper bound.
4261 * in: serif_point (in twilight zone)
4262 * base_point (in twilight zone)
4263 * edge[-1] (in twilight zone)
4264 * edge[1] (in twilight zone)
4265 * ... stuff for bci_align_segments (serif) ...
4267 * uses: bci_serif_common
4268 * bci_upper_lower_bound
4271 unsigned char FPGM(bci_action_serif_upper_lower_bound
) [] =
4275 bci_action_serif_upper_lower_bound
,
4280 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
4287 bci_upper_lower_bound
,
4296 * bci_serif_anchor_common
4298 * Common code for bci_action_serif_anchor routines.
4305 unsigned char FPGM(bci_serif_anchor_common
) [] =
4309 bci_serif_anchor_common
,
4314 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
4320 WS
, /* sal_anchor = edge_point */
4330 CALL
, /* s: [...] edge edge edge_pos round(edge_orig_pos) */
4333 SHPIX
, /* edge = round(edge_orig) */
4341 * bci_action_serif_anchor
4343 * Handle the SERIF_ANCHOR action to align a serif and to set the edge
4346 * in: edge_point (in twilight zone)
4347 * ... stuff for bci_align_segments (edge) ...
4349 * uses: bci_serif_anchor_common
4350 * bci_align_segments
4353 unsigned char FPGM(bci_action_serif_anchor
) [] =
4357 bci_action_serif_anchor
,
4361 bci_serif_anchor_common
,
4364 MDAP_noround
, /* set rp0 and rp1 to `edge' */
4369 SZP1
, /* set zp1 to normal zone 1 */
4378 * bci_action_serif_anchor_lower_bound
4380 * Handle the SERIF_ANCHOR action to align a serif and to set the edge
4381 * anchor, then moving it again if necessary to stay within a lower
4384 * in: edge_point (in twilight zone)
4385 * edge[-1] (in twilight zone)
4386 * ... stuff for bci_align_segments (edge) ...
4388 * uses: bci_serif_anchor_common
4392 unsigned char FPGM(bci_action_serif_anchor_lower_bound
) [] =
4396 bci_action_serif_anchor_lower_bound
,
4400 bci_serif_anchor_common
,
4413 * bci_action_serif_anchor_upper_bound
4415 * Handle the SERIF_ANCHOR action to align a serif and to set the edge
4416 * anchor, then moving it again if necessary to stay within an upper
4419 * in: edge_point (in twilight zone)
4420 * edge[1] (in twilight zone)
4421 * ... stuff for bci_align_segments (edge) ...
4423 * uses: bci_serif_anchor_common
4427 unsigned char FPGM(bci_action_serif_anchor_upper_bound
) [] =
4431 bci_action_serif_anchor_upper_bound
,
4435 bci_serif_anchor_common
,
4448 * bci_action_serif_anchor_upper_lower_bound
4450 * Handle the SERIF_ANCHOR action to align a serif and to set the edge
4451 * anchor, then moving it again if necessary to stay within a lower and
4454 * in: edge_point (in twilight zone)
4455 * edge[-1] (in twilight zone)
4456 * edge[1] (in twilight zone)
4457 * ... stuff for bci_align_segments (edge) ...
4459 * uses: bci_serif_anchor_common
4460 * bci_upper_lower_bound
4463 unsigned char FPGM(bci_action_serif_anchor_upper_lower_bound
) [] =
4467 bci_action_serif_anchor_upper_lower_bound
,
4471 bci_serif_anchor_common
,
4475 bci_upper_lower_bound
,
4484 * bci_serif_link1_common
4486 * Common code for bci_action_serif_link1 routines.
4491 unsigned char FPGM(bci_serif_link1_common
) [] =
4495 bci_serif_link1_common
,
4500 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
4504 CINDEX
, /* s: [...] after edge before after */
4507 CINDEX
, /* s: [...] after edge before after before */
4511 EQ
, /* after_orig_pos == before_orig_pos */
4512 IF
, /* s: [...] after edge before */
4513 MDAP_noround
, /* set rp0 and rp1 to `before' */
4515 ALIGNRP
, /* align `edge' with `before' */
4520 /* we have to execute `a*b/c', with b/c very near to 1: */
4521 /* to avoid overflow while retaining precision, */
4522 /* we transform this to `a + a * (b-c)/c' */
4526 CINDEX
, /* s: [...] after edge before edge */
4529 CINDEX
, /* s: [...] after edge before edge before */
4530 MD_orig_ZP2_0
, /* a = edge_orig_pos - before_orig_pos */
4535 CINDEX
, /* s: [...] after edge before a a after */
4538 CINDEX
, /* s: [...] after edge before a a after before */
4539 MD_orig_ZP2_0
, /* c = after_orig_pos - before_orig_pos */
4543 CINDEX
, /* s: [...] after edge before a a c after */
4546 CINDEX
, /* s: [...] after edge before a a c after before */
4547 MD_cur
, /* b = after_pos - before_pos */
4551 CINDEX
, /* s: [...] after edge before a a c b c */
4557 MUL
, /* (b-c) in 16.16 format */
4562 DIV
, /* s: [...] after edge before a a (b-c)/c */
4564 POP
, /* avoid division by zero */
4567 MUL
, /* a * (b-c)/c * 2^10 */
4571 DIV
, /* a * (b-c)/c */
4575 MDAP_noround
, /* set rp0 and rp1 to `before' */
4576 SWAP
, /* s: [...] after a*b/c edge */
4579 ALIGNRP
, /* align `edge' with `before' */
4581 SHPIX
, /* shift `edge' by `a*b/c' */
4583 SWAP
, /* s: [...] edge after */
4593 * bci_action_serif_link1
4595 * Handle the SERIF_LINK1 action to align a serif, depending on edges
4598 * in: before_point (in twilight zone)
4599 * edge_point (in twilight zone)
4600 * after_point (in twilight zone)
4601 * ... stuff for bci_align_segments (edge) ...
4603 * uses: bci_serif_link1_common
4604 * bci_align_segments
4607 unsigned char FPGM(bci_action_serif_link1
) [] =
4611 bci_action_serif_link1
,
4615 bci_serif_link1_common
,
4618 MDAP_noround
, /* set rp0 and rp1 to `edge' */
4623 SZP1
, /* set zp1 to normal zone 1 */
4632 * bci_action_serif_link1_lower_bound
4634 * Handle the SERIF_LINK1 action to align a serif, depending on edges
4635 * before and after. Additionally, move the serif again if necessary to
4636 * stay within a lower bound.
4638 * in: before_point (in twilight zone)
4639 * edge_point (in twilight zone)
4640 * after_point (in twilight zone)
4641 * edge[-1] (in twilight zone)
4642 * ... stuff for bci_align_segments (edge) ...
4644 * uses: bci_serif_link1_common
4648 unsigned char FPGM(bci_action_serif_link1_lower_bound
) [] =
4652 bci_action_serif_link1_lower_bound
,
4656 bci_serif_link1_common
,
4669 * bci_action_serif_link1_upper_bound
4671 * Handle the SERIF_LINK1 action to align a serif, depending on edges
4672 * before and after. Additionally, move the serif again if necessary to
4673 * stay within an upper bound.
4675 * in: before_point (in twilight zone)
4676 * edge_point (in twilight zone)
4677 * after_point (in twilight zone)
4678 * edge[1] (in twilight zone)
4679 * ... stuff for bci_align_segments (edge) ...
4681 * uses: bci_serif_link1_common
4685 unsigned char FPGM(bci_action_serif_link1_upper_bound
) [] =
4689 bci_action_serif_link1_upper_bound
,
4693 bci_serif_link1_common
,
4706 * bci_action_serif_link1_upper_lower_bound
4708 * Handle the SERIF_LINK1 action to align a serif, depending on edges
4709 * before and after. Additionally, move the serif again if necessary to
4710 * stay within a lower and upper bound.
4712 * in: before_point (in twilight zone)
4713 * edge_point (in twilight zone)
4714 * after_point (in twilight zone)
4715 * edge[-1] (in twilight zone)
4716 * edge[1] (in twilight zone)
4717 * ... stuff for bci_align_segments (edge) ...
4719 * uses: bci_serif_link1_common
4720 * bci_upper_lower_bound
4723 unsigned char FPGM(bci_action_serif_link1_upper_lower_bound
) [] =
4727 bci_action_serif_link1_upper_lower_bound
,
4731 bci_serif_link1_common
,
4735 bci_upper_lower_bound
,
4744 * bci_serif_link2_common
4746 * Common code for bci_action_serif_link2 routines.
4751 unsigned char FPGM(bci_serif_link2_common
) [] =
4755 bci_serif_link2_common
,
4760 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
4762 DUP
, /* s: [...] edge edge */
4766 DUP
, /* s: [...] edge edge anchor anchor */
4767 MDAP_noround
, /* set rp0 and rp1 to `sal_anchor' */
4778 DIV
, /* delta = (edge_orig_pos - anchor_orig_pos + 16) & ~31 */
4783 ALIGNRP
, /* align `edge' with `sal_anchor' */
4785 SHPIX
, /* shift `edge' by `delta' */
4793 * bci_action_serif_link2
4795 * Handle the SERIF_LINK2 action to align a serif relative to the anchor.
4797 * in: edge_point (in twilight zone)
4798 * ... stuff for bci_align_segments (edge) ...
4800 * uses: bci_serif_link2_common
4801 * bci_align_segments
4804 unsigned char FPGM(bci_action_serif_link2
) [] =
4808 bci_action_serif_link2
,
4812 bci_serif_link2_common
,
4815 MDAP_noround
, /* set rp0 and rp1 to `edge' */
4820 SZP1
, /* set zp1 to normal zone 1 */
4829 * bci_action_serif_link2_lower_bound
4831 * Handle the SERIF_LINK2 action to align a serif relative to the anchor.
4832 * Additionally, move the serif again if necessary to stay within a lower
4835 * in: edge_point (in twilight zone)
4836 * edge[-1] (in twilight zone)
4837 * ... stuff for bci_align_segments (edge) ...
4839 * uses: bci_serif_link2_common
4843 unsigned char FPGM(bci_action_serif_link2_lower_bound
) [] =
4847 bci_action_serif_link2_lower_bound
,
4851 bci_serif_link2_common
,
4864 * bci_action_serif_link2_upper_bound
4866 * Handle the SERIF_LINK2 action to align a serif relative to the anchor.
4867 * Additionally, move the serif again if necessary to stay within an upper
4870 * in: edge_point (in twilight zone)
4871 * edge[1] (in twilight zone)
4872 * ... stuff for bci_align_segments (edge) ...
4874 * uses: bci_serif_link2_common
4878 unsigned char FPGM(bci_action_serif_link2_upper_bound
) [] =
4882 bci_action_serif_link2_upper_bound
,
4886 bci_serif_link2_common
,
4899 * bci_action_serif_link2_upper_lower_bound
4901 * Handle the SERIF_LINK2 action to align a serif relative to the anchor.
4902 * Additionally, move the serif again if necessary to stay within a lower
4905 * in: edge_point (in twilight zone)
4906 * edge[-1] (in twilight zone)
4907 * edge[1] (in twilight zone)
4908 * ... stuff for bci_align_segments (edge) ...
4910 * uses: bci_serif_link2_common
4911 * bci_upper_lower_bound
4914 unsigned char FPGM(bci_action_serif_link2_upper_lower_bound
) [] =
4918 bci_action_serif_link2_upper_lower_bound
,
4922 bci_serif_link2_common
,
4926 bci_upper_lower_bound
,
4937 * This is the top-level glyph hinting function which parses the arguments
4938 * on the stack and calls subroutines.
4940 * in: action_0_func_idx
4946 * CVT: cvtl_is_subglyph
4948 * uses: bci_action_ip_before
4949 * bci_action_ip_after
4951 * bci_action_ip_between
4953 * bci_action_adjust_bound
4954 * bci_action_adjust_bound_serif
4955 * bci_action_adjust_bound_round
4956 * bci_action_adjust_bound_round_serif
4958 * bci_action_stem_bound
4959 * bci_action_stem_bound_serif
4960 * bci_action_stem_bound_round
4961 * bci_action_stem_bound_round_serif
4964 * bci_action_link_serif
4965 * bci_action_link_round
4966 * bci_action_link_round_serif
4969 * bci_action_anchor_serif
4970 * bci_action_anchor_round
4971 * bci_action_anchor_round_serif
4973 * bci_action_blue_anchor
4976 * bci_action_adjust_serif
4977 * bci_action_adjust_round
4978 * bci_action_adjust_round_serif
4981 * bci_action_stem_serif
4982 * bci_action_stem_round
4983 * bci_action_stem_round_serif
4988 * bci_action_serif_lower_bound
4989 * bci_action_serif_upper_bound
4990 * bci_action_serif_upper_lower_bound
4992 * bci_action_serif_anchor
4993 * bci_action_serif_anchor_lower_bound
4994 * bci_action_serif_anchor_upper_bound
4995 * bci_action_serif_anchor_upper_lower_bound
4997 * bci_action_serif_link1
4998 * bci_action_serif_link1_lower_bound
4999 * bci_action_serif_link1_upper_bound
5000 * bci_action_serif_link1_upper_lower_bound
5002 * bci_action_serif_link2
5003 * bci_action_serif_link2_lower_bound
5004 * bci_action_serif_link2_upper_bound
5005 * bci_action_serif_link2_upper_lower_bound
5008 unsigned char FPGM(bci_hint_glyph
) [] =
5016 /* loop until all data on stack is used */
5025 JROT
, /* goto start_loop */
5029 SZP2
, /* set zp2 to normal zone 1 */
5037 #define COPY_FPGM(func_name) \
5038 memcpy(buf_p, fpgm_ ## func_name, \
5039 sizeof (fpgm_ ## func_name)); \
5040 buf_p += sizeof (fpgm_ ## func_name) \
5043 TA_table_build_fpgm(FT_Byte
** fpgm
,
5053 /* for compatibility with dumb bytecode interpreters or analyzers, */
5054 /* FDEFs are stored in ascending index order, without holes -- */
5055 /* note that some FDEFs are not always needed */
5056 /* (depending on options of `TTFautohint'), */
5057 /* but implementing dynamic FDEF indices would be a lot of work */
5059 buf_len
= sizeof (FPGM(bci_round
))
5060 + sizeof (FPGM(bci_smooth_stem_width_a
))
5062 + sizeof (FPGM(bci_smooth_stem_width_b
))
5064 + sizeof (FPGM(bci_smooth_stem_width_c
))
5065 + sizeof (FPGM(bci_get_best_width
))
5066 + sizeof (FPGM(bci_strong_stem_width_a
))
5068 + sizeof (FPGM(bci_strong_stem_width_b
))
5069 + sizeof (FPGM(bci_loop_do
))
5070 + sizeof (FPGM(bci_loop
))
5071 + sizeof (FPGM(bci_cvt_rescale
))
5072 + sizeof (FPGM(bci_blue_round_a
))
5074 + sizeof (FPGM(bci_blue_round_b
))
5075 + sizeof (FPGM(bci_decrement_component_counter
))
5076 + sizeof (FPGM(bci_get_point_extrema
))
5077 + sizeof (FPGM(bci_nibbles
))
5078 + sizeof (FPGM(bci_number_set_is_element
))
5079 + sizeof (FPGM(bci_number_set_is_element2
))
5081 + sizeof (FPGM(bci_create_segment
))
5082 + sizeof (FPGM(bci_create_segments
))
5084 + sizeof (FPGM(bci_create_segments_0
))
5085 + sizeof (FPGM(bci_create_segments_1
))
5086 + sizeof (FPGM(bci_create_segments_2
))
5087 + sizeof (FPGM(bci_create_segments_3
))
5088 + sizeof (FPGM(bci_create_segments_4
))
5089 + sizeof (FPGM(bci_create_segments_5
))
5090 + sizeof (FPGM(bci_create_segments_6
))
5091 + sizeof (FPGM(bci_create_segments_7
))
5092 + sizeof (FPGM(bci_create_segments_8
))
5093 + sizeof (FPGM(bci_create_segments_9
))
5095 + sizeof (FPGM(bci_create_segments_composite
))
5097 + sizeof (FPGM(bci_create_segments_composite_0
))
5098 + sizeof (FPGM(bci_create_segments_composite_1
))
5099 + sizeof (FPGM(bci_create_segments_composite_2
))
5100 + sizeof (FPGM(bci_create_segments_composite_3
))
5101 + sizeof (FPGM(bci_create_segments_composite_4
))
5102 + sizeof (FPGM(bci_create_segments_composite_5
))
5103 + sizeof (FPGM(bci_create_segments_composite_6
))
5104 + sizeof (FPGM(bci_create_segments_composite_7
))
5105 + sizeof (FPGM(bci_create_segments_composite_8
))
5106 + sizeof (FPGM(bci_create_segments_composite_9
))
5108 + sizeof (FPGM(bci_align_point
))
5109 + sizeof (FPGM(bci_align_segment
))
5110 + sizeof (FPGM(bci_align_segments
))
5112 + sizeof (FPGM(bci_scale_contour
))
5113 + sizeof (FPGM(bci_scale_glyph
))
5114 + sizeof (FPGM(bci_scale_composite_glyph
))
5115 + sizeof (FPGM(bci_shift_contour
))
5116 + sizeof (FPGM(bci_shift_subglyph
))
5118 + sizeof (FPGM(bci_ip_outer_align_point
))
5119 + sizeof (FPGM(bci_ip_on_align_points
))
5120 + sizeof (FPGM(bci_ip_between_align_point
))
5121 + sizeof (FPGM(bci_ip_between_align_points
))
5123 + sizeof (FPGM(bci_adjust_common
))
5124 + sizeof (FPGM(bci_stem_common
))
5125 + sizeof (FPGM(bci_serif_common
))
5126 + sizeof (FPGM(bci_serif_anchor_common
))
5127 + sizeof (FPGM(bci_serif_link1_common
))
5128 + sizeof (FPGM(bci_serif_link2_common
))
5130 + sizeof (FPGM(bci_lower_bound
))
5131 + sizeof (FPGM(bci_upper_bound
))
5132 + sizeof (FPGM(bci_upper_lower_bound
))
5134 + sizeof (FPGM(bci_adjust_bound
))
5135 + sizeof (FPGM(bci_stem_bound
))
5136 + sizeof (FPGM(bci_link
))
5137 + sizeof (FPGM(bci_anchor
))
5138 + sizeof (FPGM(bci_adjust
))
5139 + sizeof (FPGM(bci_stem
))
5141 + sizeof (FPGM(bci_action_ip_before
))
5142 + sizeof (FPGM(bci_action_ip_after
))
5143 + sizeof (FPGM(bci_action_ip_on
))
5144 + sizeof (FPGM(bci_action_ip_between
))
5146 + sizeof (FPGM(bci_action_blue
))
5147 + sizeof (FPGM(bci_action_blue_anchor
))
5149 + sizeof (FPGM(bci_action_anchor
))
5150 + sizeof (FPGM(bci_action_anchor_serif
))
5151 + sizeof (FPGM(bci_action_anchor_round
))
5152 + sizeof (FPGM(bci_action_anchor_round_serif
))
5154 + sizeof (FPGM(bci_action_adjust
))
5155 + sizeof (FPGM(bci_action_adjust_serif
))
5156 + sizeof (FPGM(bci_action_adjust_round
))
5157 + sizeof (FPGM(bci_action_adjust_round_serif
))
5158 + sizeof (FPGM(bci_action_adjust_bound
))
5159 + sizeof (FPGM(bci_action_adjust_bound_serif
))
5160 + sizeof (FPGM(bci_action_adjust_bound_round
))
5161 + sizeof (FPGM(bci_action_adjust_bound_round_serif
))
5163 + sizeof (FPGM(bci_action_link
))
5164 + sizeof (FPGM(bci_action_link_serif
))
5165 + sizeof (FPGM(bci_action_link_round
))
5166 + sizeof (FPGM(bci_action_link_round_serif
))
5168 + sizeof (FPGM(bci_action_stem
))
5169 + sizeof (FPGM(bci_action_stem_serif
))
5170 + sizeof (FPGM(bci_action_stem_round
))
5171 + sizeof (FPGM(bci_action_stem_round_serif
))
5172 + sizeof (FPGM(bci_action_stem_bound
))
5173 + sizeof (FPGM(bci_action_stem_bound_serif
))
5174 + sizeof (FPGM(bci_action_stem_bound_round
))
5175 + sizeof (FPGM(bci_action_stem_bound_round_serif
))
5177 + sizeof (FPGM(bci_action_serif
))
5178 + sizeof (FPGM(bci_action_serif_lower_bound
))
5179 + sizeof (FPGM(bci_action_serif_upper_bound
))
5180 + sizeof (FPGM(bci_action_serif_upper_lower_bound
))
5182 + sizeof (FPGM(bci_action_serif_anchor
))
5183 + sizeof (FPGM(bci_action_serif_anchor_lower_bound
))
5184 + sizeof (FPGM(bci_action_serif_anchor_upper_bound
))
5185 + sizeof (FPGM(bci_action_serif_anchor_upper_lower_bound
))
5187 + sizeof (FPGM(bci_action_serif_link1
))
5188 + sizeof (FPGM(bci_action_serif_link1_lower_bound
))
5189 + sizeof (FPGM(bci_action_serif_link1_upper_bound
))
5190 + sizeof (FPGM(bci_action_serif_link1_upper_lower_bound
))
5192 + sizeof (FPGM(bci_action_serif_link2
))
5193 + sizeof (FPGM(bci_action_serif_link2_lower_bound
))
5194 + sizeof (FPGM(bci_action_serif_link2_upper_bound
))
5195 + sizeof (FPGM(bci_action_serif_link2_upper_lower_bound
))
5197 + sizeof (FPGM(bci_hint_glyph
));
5199 /* buffer length must be a multiple of four */
5200 len
= (buf_len
+ 3) & ~3;
5201 buf
= (FT_Byte
*)malloc(len
);
5203 return FT_Err_Out_Of_Memory
;
5205 /* pad end of buffer with zeros */
5206 buf
[len
- 1] = 0x00;
5207 buf
[len
- 2] = 0x00;
5208 buf
[len
- 3] = 0x00;
5210 /* copy font program into buffer and fill in the missing variables */
5213 COPY_FPGM(bci_round
);
5214 COPY_FPGM(bci_smooth_stem_width_a
);
5215 *(buf_p
++) = (unsigned char)CVT_VERT_WIDTHS_OFFSET(font
);
5216 COPY_FPGM(bci_smooth_stem_width_b
);
5217 *(buf_p
++) = (unsigned char)CVT_VERT_WIDTHS_OFFSET(font
);
5218 COPY_FPGM(bci_smooth_stem_width_c
);
5219 COPY_FPGM(bci_get_best_width
);
5220 COPY_FPGM(bci_strong_stem_width_a
);
5221 *(buf_p
++) = (unsigned char)CVT_VERT_WIDTHS_OFFSET(font
);
5222 *(buf_p
++) = (unsigned char)CVT_VERT_WIDTHS_SIZE(font
);
5223 COPY_FPGM(bci_strong_stem_width_b
);
5224 COPY_FPGM(bci_loop_do
);
5225 COPY_FPGM(bci_loop
);
5226 COPY_FPGM(bci_cvt_rescale
);
5227 COPY_FPGM(bci_blue_round_a
);
5228 *(buf_p
++) = (unsigned char)CVT_BLUES_SIZE(font
);
5229 COPY_FPGM(bci_blue_round_b
);
5230 COPY_FPGM(bci_decrement_component_counter
);
5231 COPY_FPGM(bci_get_point_extrema
);
5232 COPY_FPGM(bci_nibbles
);
5233 COPY_FPGM(bci_number_set_is_element
);
5234 COPY_FPGM(bci_number_set_is_element2
);
5236 COPY_FPGM(bci_create_segment
);
5237 COPY_FPGM(bci_create_segments
);
5239 COPY_FPGM(bci_create_segments_0
);
5240 COPY_FPGM(bci_create_segments_1
);
5241 COPY_FPGM(bci_create_segments_2
);
5242 COPY_FPGM(bci_create_segments_3
);
5243 COPY_FPGM(bci_create_segments_4
);
5244 COPY_FPGM(bci_create_segments_5
);
5245 COPY_FPGM(bci_create_segments_6
);
5246 COPY_FPGM(bci_create_segments_7
);
5247 COPY_FPGM(bci_create_segments_8
);
5248 COPY_FPGM(bci_create_segments_9
);
5250 COPY_FPGM(bci_create_segments_composite
);
5252 COPY_FPGM(bci_create_segments_composite_0
);
5253 COPY_FPGM(bci_create_segments_composite_1
);
5254 COPY_FPGM(bci_create_segments_composite_2
);
5255 COPY_FPGM(bci_create_segments_composite_3
);
5256 COPY_FPGM(bci_create_segments_composite_4
);
5257 COPY_FPGM(bci_create_segments_composite_5
);
5258 COPY_FPGM(bci_create_segments_composite_6
);
5259 COPY_FPGM(bci_create_segments_composite_7
);
5260 COPY_FPGM(bci_create_segments_composite_8
);
5261 COPY_FPGM(bci_create_segments_composite_9
);
5263 COPY_FPGM(bci_align_point
);
5264 COPY_FPGM(bci_align_segment
);
5265 COPY_FPGM(bci_align_segments
);
5267 COPY_FPGM(bci_scale_contour
);
5268 COPY_FPGM(bci_scale_glyph
);
5269 COPY_FPGM(bci_scale_composite_glyph
);
5270 COPY_FPGM(bci_shift_contour
);
5271 COPY_FPGM(bci_shift_subglyph
);
5273 COPY_FPGM(bci_ip_outer_align_point
);
5274 COPY_FPGM(bci_ip_on_align_points
);
5275 COPY_FPGM(bci_ip_between_align_point
);
5276 COPY_FPGM(bci_ip_between_align_points
);
5278 COPY_FPGM(bci_adjust_common
);
5279 COPY_FPGM(bci_stem_common
);
5280 COPY_FPGM(bci_serif_common
);
5281 COPY_FPGM(bci_serif_anchor_common
);
5282 COPY_FPGM(bci_serif_link1_common
);
5283 COPY_FPGM(bci_serif_link2_common
);
5285 COPY_FPGM(bci_lower_bound
);
5286 COPY_FPGM(bci_upper_bound
);
5287 COPY_FPGM(bci_upper_lower_bound
);
5289 COPY_FPGM(bci_adjust_bound
);
5290 COPY_FPGM(bci_stem_bound
);
5291 COPY_FPGM(bci_link
);
5292 COPY_FPGM(bci_anchor
);
5293 COPY_FPGM(bci_adjust
);
5294 COPY_FPGM(bci_stem
);
5296 COPY_FPGM(bci_action_ip_before
);
5297 COPY_FPGM(bci_action_ip_after
);
5298 COPY_FPGM(bci_action_ip_on
);
5299 COPY_FPGM(bci_action_ip_between
);
5301 COPY_FPGM(bci_action_blue
);
5302 COPY_FPGM(bci_action_blue_anchor
);
5304 COPY_FPGM(bci_action_anchor
);
5305 COPY_FPGM(bci_action_anchor_serif
);
5306 COPY_FPGM(bci_action_anchor_round
);
5307 COPY_FPGM(bci_action_anchor_round_serif
);
5309 COPY_FPGM(bci_action_adjust
);
5310 COPY_FPGM(bci_action_adjust_serif
);
5311 COPY_FPGM(bci_action_adjust_round
);
5312 COPY_FPGM(bci_action_adjust_round_serif
);
5313 COPY_FPGM(bci_action_adjust_bound
);
5314 COPY_FPGM(bci_action_adjust_bound_serif
);
5315 COPY_FPGM(bci_action_adjust_bound_round
);
5316 COPY_FPGM(bci_action_adjust_bound_round_serif
);
5318 COPY_FPGM(bci_action_link
);
5319 COPY_FPGM(bci_action_link_serif
);
5320 COPY_FPGM(bci_action_link_round
);
5321 COPY_FPGM(bci_action_link_round_serif
);
5323 COPY_FPGM(bci_action_stem
);
5324 COPY_FPGM(bci_action_stem_serif
);
5325 COPY_FPGM(bci_action_stem_round
);
5326 COPY_FPGM(bci_action_stem_round_serif
);
5327 COPY_FPGM(bci_action_stem_bound
);
5328 COPY_FPGM(bci_action_stem_bound_serif
);
5329 COPY_FPGM(bci_action_stem_bound_round
);
5330 COPY_FPGM(bci_action_stem_bound_round_serif
);
5332 COPY_FPGM(bci_action_serif
);
5333 COPY_FPGM(bci_action_serif_lower_bound
);
5334 COPY_FPGM(bci_action_serif_upper_bound
);
5335 COPY_FPGM(bci_action_serif_upper_lower_bound
);
5337 COPY_FPGM(bci_action_serif_anchor
);
5338 COPY_FPGM(bci_action_serif_anchor_lower_bound
);
5339 COPY_FPGM(bci_action_serif_anchor_upper_bound
);
5340 COPY_FPGM(bci_action_serif_anchor_upper_lower_bound
);
5342 COPY_FPGM(bci_action_serif_link1
);
5343 COPY_FPGM(bci_action_serif_link1_lower_bound
);
5344 COPY_FPGM(bci_action_serif_link1_upper_bound
);
5345 COPY_FPGM(bci_action_serif_link1_upper_lower_bound
);
5347 COPY_FPGM(bci_action_serif_link2
);
5348 COPY_FPGM(bci_action_serif_link2_lower_bound
);
5349 COPY_FPGM(bci_action_serif_link2_upper_bound
);
5350 COPY_FPGM(bci_action_serif_link2_upper_lower_bound
);
5352 COPY_FPGM(bci_hint_glyph
);
5355 *fpgm_len
= buf_len
;
5362 TA_sfnt_build_fpgm_table(SFNT
* sfnt
,
5365 FT_Error error
= FT_Err_Ok
;
5367 SFNT_Table
* glyf_table
= &font
->tables
[sfnt
->glyf_idx
];
5368 glyf_Data
* data
= (glyf_Data
*)glyf_table
->data
;
5374 error
= TA_sfnt_add_table_info(sfnt
);
5378 /* `glyf', `cvt', `fpgm', and `prep' are always used in parallel */
5379 if (glyf_table
->processed
)
5381 sfnt
->table_infos
[sfnt
->num_table_infos
- 1] = data
->fpgm_idx
;
5385 error
= TA_table_build_fpgm(&fpgm_buf
, &fpgm_len
, font
);
5389 if (fpgm_len
> sfnt
->max_instructions
)
5390 sfnt
->max_instructions
= fpgm_len
;
5392 /* in case of success, `fpgm_buf' gets linked */
5393 /* and is eventually freed in `TA_font_unload' */
5394 error
= TA_font_add_table(font
,
5395 &sfnt
->table_infos
[sfnt
->num_table_infos
- 1],
5396 TTAG_fpgm
, fpgm_len
, fpgm_buf
);
5400 data
->fpgm_idx
= sfnt
->table_infos
[sfnt
->num_table_infos
- 1];
5406 /* end of tafpgm.c */