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
) [] =
107 * bci_compute_stem_width
109 * This is the equivalent to the following code from function
110 * `ta_latin_compute_stem_width':
118 * else if base_is_round:
124 * delta = ABS(dist - std_width)
135 * delta = delta - dist
138 * dist = dist + delta
139 * else if delta < 32:
141 * else if delta < 54:
144 * dist = dist + delta
160 * CVT: cvtl_is_extra_light
164 unsigned char FPGM(bci_compute_stem_width_a
) [] =
168 bci_compute_stem_width
,
172 ABS
, /* s: base_is_round stem_is_serif width dist */
177 LT
, /* dist < 3*64 */
181 MINDEX
, /* s: base_is_round width dist (dist<3*64) stem_is_serif */
182 AND
, /* stem_is_serif && dist < 3*64 */
187 OR
, /* (stem_is_serif && dist < 3*64) || is_extra_light */
189 IF
, /* s: base_is_round width dist */
195 ROLL
, /* s: width dist base_is_round */
196 IF
, /* s: width dist */
201 IF
, /* s: width dist */
212 IF
, /* s: width dist */
219 DUP
, /* s: width dist dist */
224 /* %c, index of std_width */
226 unsigned char FPGM(bci_compute_stem_width_b
) [] =
231 ABS
, /* s: width dist delta */
236 IF
, /* s: width dist */
242 /* %c, index of std_width */
244 unsigned char FPGM(bci_compute_stem_width_c
) [] =
247 RCVT
, /* dist = std_width */
259 DUP
, /* s: width dist dist */
262 LT
, /* dist < 3*64 */
264 DUP
, /* s: width delta dist */
265 FLOOR
, /* dist = FLOOR(dist) */
266 DUP
, /* s: width delta dist dist */
268 ROLL
, /* s: width dist delta dist */
269 SUB
, /* delta = delta - dist */
271 DUP
, /* s: width dist delta delta */
275 IF
, /* s: width dist delta */
276 ADD
, /* dist = dist + delta */
287 ADD
, /* dist = dist + 10 */
298 ADD
, /* dist = dist + 54 */
301 ADD
, /* dist = dist + delta */
310 CALL
, /* dist = round(dist) */
315 SWAP
, /* s: dist width */
320 NEG
, /* dist = -dist */
332 * Take a range and a function number and apply the function to all
333 * elements of the range.
339 * sal: sal_i (counter initialized with `start')
341 * sal_func (`func_num')
344 unsigned char FPGM(bci_loop
) [] =
354 WS
, /* sal_func = func_num */
358 WS
, /* sal_limit = end */
362 WS
, /* sal_i = start */
371 LTEQ
, /* start <= end */
382 ADD
, /* start = start + 1 */
388 JMPR
, /* goto start_loop */
399 * Rescale CVT value by `cvtl_scale' (in 16.16 format).
401 * The scaling factor `cvtl_scale' isn't stored as `b/c' but as `(b-c)/c';
402 * consequently, the calculation `a * b/c' is done as `a + delta' with
403 * `delta = a * (b-c)/c'. This avoids overflow.
405 * sal: sal_i (CVT index)
411 unsigned char FPGM(bci_cvt_rescale
) [] =
434 * Round a blue ref value and adjust its corresponding shoot value.
436 * sal: sal_i (CVT index)
440 unsigned char FPGM(bci_blue_round_a
) [] =
451 RCVT
, /* s: ref_idx ref */
457 SWAP
, /* s: ref_idx round(ref) ref */
465 unsigned char FPGM(bci_blue_round_b
) [] =
470 ADD
, /* s: ref_idx round(ref) ref shoot_idx */
472 RCVT
, /* s: ref_idx round(ref) ref shoot_idx shoot */
474 ROLL
, /* s: ref_idx round(ref) shoot_idx shoot ref */
476 SUB
, /* s: ref_idx round(ref) shoot_idx dist */
478 ABS
, /* s: ref_idx round(ref) shoot_idx dist delta */
503 SWAP
, /* s: ref_idx round(ref) shoot_idx delta dist */
508 NEG
, /* delta = -delta */
515 SUB
, /* s: ref_idx round(ref) shoot_idx (round(ref) - delta) */
526 * bci_decrement_component_counter
528 * An auxiliary function for composite glyphs.
530 * CVT: cvtl_is_subglyph
533 unsigned char FPGM(bci_decrement_component_counter
) [] =
537 bci_decrement_component_counter
,
540 /* decrement `cvtl_is_subglyph' counter */
556 * bci_get_point_extrema
558 * An auxiliary function for `bci_create_segment'.
567 unsigned char FPGM(bci_get_point_extrema
) [] =
571 bci_get_point_extrema
,
580 /* check whether `point' is a new minimum */
583 RS
, /* s: point point point point_min */
585 /* if distance is negative, we have a new minimum */
589 IF
, /* s: point point */
597 /* check whether `point' is a new maximum */
600 RS
, /* s: point point point_max */
602 /* if distance is positive, we have a new maximum */
622 * Pop a byte with two delta arguments in its nibbles and push the
623 * expanded arguments separately as two bytes.
625 * in: 16 * (end - start) + (start - base)
630 * sal: sal_base (set to `end' at return)
634 unsigned char FPGM(bci_nibbles
) [] =
644 DIV
, /* s: in hnibble */
649 MUL
, /* s: in hnibble (hnibble * 16) */
652 SUB
, /* s: hnibble lnibble */
657 ADD
, /* s: hnibble start */
660 ADD
, /* s: start end */
666 WS
, /* sal_base = end */
678 * Store start and end point of a segment in the storage area,
679 * then construct a point in the twilight zone to represent it.
681 * This function is used by `bci_create_segment_points'.
685 * [last (if wrap-around segment)]
686 * [first (if wrap-around segment)]
688 * uses: bci_get_point_extrema
691 * sal: sal_i (start of current segment)
692 * sal_j (current twilight point)
696 * sal_num_packed_segments
702 * If `sal_num_packed_segments' is > 0, the start/end pair is stored as
703 * delta values in nibbles (without a wrap-around segment).
706 unsigned char FPGM(bci_create_segment
) [] =
715 sal_num_packed_segments
,
720 sal_num_packed_segments
,
721 sal_num_packed_segments
,
726 WS
, /* sal_num_packed_segments = sal_num_packed_segments - 1 */
739 WS
, /* sal[sal_i] = start */
741 /* increase `sal_i'; together with the outer loop, this makes sal_i += 2 */
747 ADD
, /* sal_i = sal_i + 1 */
750 /* initialize inner loop(s) */
755 WS
, /* sal_point_min = start */
760 WS
, /* sal_point_max = start */
764 SZPS
, /* set zp0, zp1, and zp2 to normal zone 1 */
770 CINDEX
, /* s: start end end start */
771 LT
, /* start > end */
773 /* we have a wrap-around segment with two more arguments */
774 /* to give the last and first point of the contour, respectively; */
775 /* our job is to store a segment `start'-`last', */
776 /* and to get extrema for the two segments */
777 /* `start'-`last' and `first'-`end' */
779 /* s: first last start end */
786 WS
, /* sal[sal_i] = last */
789 ROLL
, /* s: first end last start */
792 SWAP
, /* s: first end start last start */
793 SUB
, /* s: first end start loop_count */
796 bci_get_point_extrema
,
801 SWAP
, /* s: end first */
806 ROLL
, /* s: (first - 1) (first - 1) end */
808 SUB
, /* s: (first - 1) loop_count */
811 bci_get_point_extrema
,
816 ELSE
, /* s: start end */
823 WS
, /* sal[sal_i] = end */
828 SUB
, /* s: start loop_count */
831 bci_get_point_extrema
,
837 /* the twilight point representing a segment */
838 /* is in the middle between the minimum and maximum */
850 DIV
, /* s: middle_pos */
852 DO_SCALE
, /* middle_pos = middle_pos * scale */
854 /* write it to temporary CVT location */
858 SZP0
, /* set zp0 to twilight zone 0 */
862 /* create twilight point with index `sal_j' */
875 ADD
, /* twilight_point = twilight_point + 1 */
884 * bci_create_segments
886 * This is the top-level entry function.
888 * It pops point ranges from the stack to define segments, computes
889 * twilight points to represent segments, and finally calls
890 * `bci_hint_glyph' to handle the rest.
892 * in: num_packed_segments
896 * [contour_last 0 (if wrap-around segment)]
897 * [contour_first 0 (if wrap-around segment)]
900 * [contour_last 0 (if wrap-around segment)]
901 * [contour_first 0 (if wrap-around segment)]
903 * segment_start_(N-1)
905 * [contour_last (N-1) (if wrap-around segment)]
906 * [contour_first (N-1) (if wrap-around segment)]
907 * ... stuff for bci_hint_glyph ...
909 * uses: bci_create_segment
911 * sal: sal_i (start of current segment)
912 * sal_j (current twilight point)
913 * sal_num_packed_segments
914 * sal_base (the base for delta values in nibbles)
916 * CVT: cvtl_is_subglyph
918 * If `num_packed_segments' is set to p, the first p start/end pairs are
919 * stored as delta values in nibbles, with the `start' delta in the lower
920 * nibble (and there are no wrap-around segments). For example, if the
921 * first three pairs are 1/3, 5/8, and 12/13, the topmost three bytes on the
922 * stack are 0x21, 0x32, and 0x14.
926 unsigned char FPGM(bci_create_segments
) [] =
933 /* only do something if we are not a subglyph */
940 /* all our measurements are taken along the y axis */
944 sal_num_packed_segments
,
952 SUB
, /* delta = (2*num_segments - 1) */
962 WS
, /* sal_base = 0 */
963 WS
, /* sal_j = 0 (point offset) */
966 ADD
, /* s: ... sal_segment_offset (sal_segment_offset + delta) */
968 /* `bci_create_segment_point' also increases the loop counter by 1; */
969 /* this effectively means we have a loop step of 2 */
989 * bci_create_segments_X
991 * Top-level routines for calling `bci_create_segments'.
994 unsigned char FPGM(bci_create_segments_0
) [] =
998 bci_create_segments_0
,
1003 bci_create_segments
,
1010 unsigned char FPGM(bci_create_segments_1
) [] =
1014 bci_create_segments_1
,
1019 bci_create_segments
,
1026 unsigned char FPGM(bci_create_segments_2
) [] =
1030 bci_create_segments_2
,
1035 bci_create_segments
,
1042 unsigned char FPGM(bci_create_segments_3
) [] =
1046 bci_create_segments_3
,
1051 bci_create_segments
,
1058 unsigned char FPGM(bci_create_segments_4
) [] =
1062 bci_create_segments_4
,
1067 bci_create_segments
,
1074 unsigned char FPGM(bci_create_segments_5
) [] =
1078 bci_create_segments_5
,
1083 bci_create_segments
,
1090 unsigned char FPGM(bci_create_segments_6
) [] =
1094 bci_create_segments_6
,
1099 bci_create_segments
,
1106 unsigned char FPGM(bci_create_segments_7
) [] =
1110 bci_create_segments_7
,
1115 bci_create_segments
,
1122 unsigned char FPGM(bci_create_segments_8
) [] =
1126 bci_create_segments_8
,
1131 bci_create_segments
,
1138 unsigned char FPGM(bci_create_segments_9
) [] =
1142 bci_create_segments_9
,
1147 bci_create_segments
,
1156 * bci_create_segments_composite
1158 * The same as `bci_create_segments'.
1159 * It also decrements the composite component counter.
1161 * uses: bci_decrement_composite_counter
1163 * CVT: cvtl_is_subglyph
1166 unsigned char FPGM(bci_create_segments_composite
) [] =
1170 bci_create_segments_composite
,
1174 bci_decrement_component_counter
,
1177 /* only do something if we are not a subglyph */
1184 /* all our measurements are taken along the y axis */
1188 sal_num_packed_segments
,
1196 SUB
, /* delta = (2*num_segments - 1) */
1206 WS
, /* sal_base = 0 */
1207 WS
, /* sal_j = 0 (point offset) */
1210 ADD
, /* s: ... sal_segment_offset (sal_segment_offset + delta) */
1212 /* `bci_create_segment_point' also increases the loop counter by 1; */
1213 /* this effectively means we have a loop step of 2 */
1233 * bci_create_segments_composite_X
1235 * Top-level routines for calling `bci_create_segments_composite'.
1238 unsigned char FPGM(bci_create_segments_composite_0
) [] =
1242 bci_create_segments_composite_0
,
1247 bci_create_segments_composite
,
1254 unsigned char FPGM(bci_create_segments_composite_1
) [] =
1258 bci_create_segments_composite_1
,
1263 bci_create_segments_composite
,
1270 unsigned char FPGM(bci_create_segments_composite_2
) [] =
1274 bci_create_segments_composite_2
,
1279 bci_create_segments_composite
,
1286 unsigned char FPGM(bci_create_segments_composite_3
) [] =
1290 bci_create_segments_composite_3
,
1295 bci_create_segments_composite
,
1302 unsigned char FPGM(bci_create_segments_composite_4
) [] =
1306 bci_create_segments_composite_4
,
1311 bci_create_segments_composite
,
1318 unsigned char FPGM(bci_create_segments_composite_5
) [] =
1322 bci_create_segments_composite_5
,
1327 bci_create_segments_composite
,
1334 unsigned char FPGM(bci_create_segments_composite_6
) [] =
1338 bci_create_segments_composite_6
,
1343 bci_create_segments_composite
,
1350 unsigned char FPGM(bci_create_segments_composite_7
) [] =
1354 bci_create_segments_composite_7
,
1359 bci_create_segments_composite
,
1366 unsigned char FPGM(bci_create_segments_composite_8
) [] =
1370 bci_create_segments_composite_8
,
1375 bci_create_segments_composite
,
1382 unsigned char FPGM(bci_create_segments_composite_9
) [] =
1386 bci_create_segments_composite_9
,
1391 bci_create_segments_composite
,
1402 * Align all points in a segment to the twilight point in rp0.
1403 * zp0 and zp1 must be set to 0 (twilight) and 1 (normal), respectively.
1408 unsigned char FPGM(bci_align_segment
) [] =
1415 /* we need the values of `sal_segment_offset + 2*segment_index' */
1416 /* and `sal_segment_offset + 2*segment_index + 1' */
1428 RS
, /* s: first last */
1433 CINDEX
, /* s: first last first */
1436 CINDEX
, /* s: first last first last */
1437 LTEQ
, /* first <= end */
1438 IF
, /* s: first last */
1440 DUP
, /* s: last first first */
1441 ALIGNRP
, /* align point with index `first' with rp0 */
1445 ADD
, /* first = first + 1 */
1446 SWAP
, /* s: first last */
1451 JMPR
, /* goto start_loop */
1464 * bci_align_segments
1466 * Align segments to the twilight point in rp0.
1467 * zp0 and zp1 must be set to 0 (twilight) and 1 (normal), respectively.
1476 * uses: handle_segment
1480 unsigned char FPGM(bci_align_segments
) [] =
1503 * Scale a contour using two points giving the maximum and minimum
1506 * It expects that no point on the contour is touched.
1515 unsigned char FPGM(bci_scale_contour
) [] =
1526 DO_SCALE
, /* min_pos_new = min_pos * scale */
1531 /* don't scale a single-point contour twice */
1540 DO_SCALE
, /* max_pos_new = max_pos * scale */
1557 * Scale a glyph using a list of points (two points per contour, giving
1558 * the maximum and mininum coordinates).
1560 * It expects that no point in the glyph is touched.
1562 * Note that the point numbers are sorted in ascending order;
1563 * `min_point_X' and `max_point_X' thus refer to the two extrema of a
1564 * contour without specifying which one is the minimum and maximum.
1566 * in: num_contours (N)
1575 * uses: bci_scale_contour
1577 * CVT: cvtl_is_subglyph
1580 unsigned char FPGM(bci_scale_glyph
) [] =
1587 /* only do something if we are not a subglyph */
1594 /* all our measurements are taken along the y axis */
1599 SZPS
, /* set zp0, zp1, and zp2 to normal zone 1 */
1607 SZP2
, /* set zp2 to normal zone 1 */
1620 * bci_scale_composite_glyph
1622 * The same as `bci_scale_composite_glyph'.
1623 * It also decrements the composite component counter.
1625 * uses: bci_decrement_component_counter
1627 * CVT: cvtl_is_subglyph
1630 unsigned char FPGM(bci_scale_composite_glyph
) [] =
1634 bci_scale_composite_glyph
,
1638 bci_decrement_component_counter
,
1641 /* only do something if we are not a subglyph */
1648 /* all our measurements are taken along the y axis */
1653 SZPS
, /* set zp0, zp1, and zp2 to normal zone 1 */
1661 SZP2
, /* set zp2 to normal zone 1 */
1676 * Shift a contour by a given amount.
1678 * It expects that rp1 (pointed to by zp0) is set up properly; zp2 must
1679 * point to the normal zone 1.
1685 unsigned char FPGM(bci_shift_contour
) [] =
1693 SHC_rp1
, /* shift `contour' by (rp1_pos - rp1_orig_pos) */
1705 * bci_shift_subglyph
1707 * Shift a subglyph. To be more specific, it corrects the already applied
1708 * subglyph offset (if any) from the `glyf' table which needs to be scaled
1711 * If this function is called, a point `x' in the subglyph has been scaled
1712 * already (during the hinting of the subglyph itself), and `offset' has
1713 * been applied also:
1715 * x -> x * scale + offset (1)
1717 * However, the offset should be applied first, then the scaling:
1719 * x -> (x + offset) * scale (2)
1721 * Our job is now to transform (1) to (2); a simple calculation shows that
1722 * we have to shift all points of the subglyph by
1724 * offset * scale - offset = offset * (scale - 1)
1726 * Note that `cvtl_scale' is equal to the above `scale - 1'.
1728 * in: offset (in FUnits)
1732 * CVT: cvtl_funits_to_pixels
1737 unsigned char FPGM(bci_shift_subglyph
) [] =
1747 cvtl_funits_to_pixels
,
1748 RCVT
, /* scaling factor FUnits -> pixels */
1755 /* the autohinter always rounds offsets */
1758 CALL
, /* offset = round(offset) */
1767 DIV
, /* delta = offset * (scale - 1) */
1769 /* and round again */
1772 CALL
, /* offset = round(offset) */
1776 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
1778 /* we create twilight point 0 as a reference point, */
1779 /* setting the original position to zero (using `cvtl_temp') */
1787 MIAP_noround
, /* rp0 and rp1 now point to twilight point 0 */
1789 SWAP
, /* s: first_contour num_contours 0 delta */
1790 SHPIX
, /* rp1_pos - rp1_orig_pos = delta */
1795 SZP2
, /* set zp2 to normal zone 1 */
1804 * bci_ip_outer_align_point
1806 * Auxiliary function for `bci_action_ip_before' and
1807 * `bci_action_ip_after'.
1809 * It expects rp0 to contain the edge for alignment, zp0 set to twilight
1810 * zone, and both zp1 and zp2 set to normal zone.
1814 * sal: sal_i (edge_orig_pos)
1820 unsigned char FPGM(bci_ip_outer_align_point
) [] =
1824 bci_ip_outer_align_point
,
1828 ALIGNRP
, /* align `point' with `edge' */
1831 DO_SCALE
, /* point_orig_pos = point_orig_pos * scale */
1836 SUB
, /* s: point (point_orig_pos - edge_orig_pos) */
1845 * bci_ip_on_align_points
1847 * Auxiliary function for `bci_action_ip_on'.
1849 * in: edge (in twilight zone)
1857 unsigned char FPGM(bci_ip_on_align_points
) [] =
1861 bci_ip_on_align_points
,
1864 MDAP_noround
, /* set rp0 and rp1 to `edge' */
1875 * bci_ip_between_align_point
1877 * Auxiliary function for `bci_ip_between_align_points'.
1879 * It expects rp0 to contain the edge for alignment, zp0 set to twilight
1880 * zone, and both zp1 and zp2 set to normal zone.
1884 * sal: sal_i (edge_orig_pos)
1885 * sal_j (stretch_factor)
1891 unsigned char FPGM(bci_ip_between_align_point
) [] =
1895 bci_ip_between_align_point
,
1899 ALIGNRP
, /* align `point' with `edge' */
1902 DO_SCALE
, /* point_orig_pos = point_orig_pos * scale */
1907 SUB
, /* s: point (point_orig_pos - edge_orig_pos) */
1911 MUL
, /* s: point delta */
1920 * bci_ip_between_align_points
1922 * Auxiliary function for `bci_action_ip_between'.
1924 * in: after_edge (in twilight zone)
1925 * before_edge (in twilight zone)
1932 * sal: sal_i (before_orig_pos)
1933 * sal_j (stretch_factor)
1935 * uses: bci_ip_between_align_point
1938 unsigned char FPGM(bci_ip_between_align_points
) [] =
1942 bci_ip_between_align_points
,
1948 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
1950 DUP
, /* s: ... before after before before */
1951 MDAP_noround
, /* set rp0 and rp1 to `before' */
1953 GC_orig
, /* s: ... before after before before_orig_pos */
1957 WS
, /* sal_i = before_orig_pos */
1960 CINDEX
, /* s: ... before after before after */
1961 MD_cur
, /* b = after_pos - before_pos */
1964 MD_orig_ZP2_0
, /* a = after_orig_pos - before_orig_pos */
1969 WS
, /* sal_j = stretch_factor */
1972 bci_ip_between_align_point
,
1975 SZP2
, /* set zp2 to normal zone 1 */
1976 SZP1
, /* set zp1 to normal zone 1 */
1985 * bci_action_ip_before
1987 * Handle `ip_before' data to align points located before the first edge.
1989 * in: first_edge (in twilight zone)
1996 * sal: sal_i (first_edge_orig_pos)
1998 * uses: bci_ip_outer_align_point
2001 unsigned char FPGM(bci_action_ip_before
) [] =
2005 bci_action_ip_before
,
2010 SZP2
, /* set zp2 to twilight zone 0 */
2017 WS
, /* sal_i = first_edge_orig_pos */
2023 SZP2
, /* set zp2 to normal zone 1 */
2024 SZP1
, /* set zp1 to normal zone 1 */
2025 SZP0
, /* set zp0 to twilight zone 0 */
2027 MDAP_noround
, /* set rp0 and rp1 to `first_edge' */
2030 bci_ip_outer_align_point
,
2039 * bci_action_ip_after
2041 * Handle `ip_after' data to align points located after the last edge.
2043 * in: last_edge (in twilight zone)
2050 * sal: sal_i (last_edge_orig_pos)
2052 * uses: bci_ip_outer_align_point
2055 unsigned char FPGM(bci_action_ip_after
) [] =
2059 bci_action_ip_after
,
2064 SZP2
, /* set zp2 to twilight zone 0 */
2071 WS
, /* sal_i = last_edge_orig_pos */
2077 SZP2
, /* set zp2 to normal zone 1 */
2078 SZP1
, /* set zp1 to normal zone 1 */
2079 SZP0
, /* set zp0 to twilight zone 0 */
2081 MDAP_noround
, /* set rp0 and rp1 to `last_edge' */
2084 bci_ip_outer_align_point
,
2095 * Handle `ip_on' data to align points located on an edge coordinate (but
2096 * not part of an edge).
2098 * in: loop_counter (M)
2099 * edge_1 (in twilight zone)
2100 * loop_counter (N_1)
2105 * edge_2 (in twilight zone)
2106 * loop_counter (N_2)
2112 * edge_M (in twilight zone)
2113 * loop_counter (N_M)
2119 * uses: bci_ip_on_align_points
2122 unsigned char FPGM(bci_action_ip_on
) [] =
2132 SZP1
, /* set zp1 to normal zone 1 */
2133 SZP0
, /* set zp0 to twilight zone 0 */
2136 bci_ip_on_align_points
,
2145 * bci_action_ip_between
2147 * Handle `ip_between' data to align points located between two edges.
2149 * in: loop_counter (M)
2150 * before_edge_1 (in twilight zone)
2151 * after_edge_1 (in twilight zone)
2152 * loop_counter (N_1)
2157 * before_edge_2 (in twilight zone)
2158 * after_edge_2 (in twilight zone)
2159 * loop_counter (N_2)
2165 * before_edge_M (in twilight zone)
2166 * after_edge_M (in twilight zone)
2167 * loop_counter (N_M)
2173 * uses: bci_ip_between_align_points
2176 unsigned char FPGM(bci_action_ip_between
) [] =
2180 bci_action_ip_between
,
2184 bci_ip_between_align_points
,
2195 * Common code for bci_action_adjust routines.
2198 unsigned char FPGM(bci_adjust_common
) [] =
2207 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
2211 CINDEX
, /* s: [...] edge2 edge is_round is_serif edge2 */
2214 CINDEX
, /* s: [...] edge2 edge is_round is_serif edge2 edge */
2215 MD_orig_ZP2_0
, /* s: [...] edge2 edge is_round is_serif org_len */
2218 bci_compute_stem_width
,
2220 NEG
, /* s: [...] edge2 edge -cur_len */
2222 ROLL
, /* s: [...] edge -cur_len edge2 */
2223 MDAP_noround
, /* set rp0 and rp1 to `edge2' */
2226 DUP
, /* s: [...] -cur_len edge edge edge */
2227 ALIGNRP
, /* align `edge' with `edge2' */
2229 SHPIX
, /* shift `edge' by -cur_len */
2239 * Handle the ADJUST_BOUND action to align an edge of a stem if the other
2240 * edge of the stem has already been moved, then moving it again if
2241 * necessary to stay bound.
2243 * in: edge2_is_serif
2245 * edge_point (in twilight zone)
2246 * edge2_point (in twilight zone)
2247 * edge[-1] (in twilight zone)
2248 * ... stuff for bci_align_segments (edge) ...
2250 * uses: bci_adjust_common
2253 unsigned char FPGM(bci_adjust_bound
) [] =
2264 SWAP
, /* s: edge edge[-1] */
2266 MDAP_noround
, /* set rp0 and rp1 to `edge[-1]' */
2271 GC_cur
, /* s: edge edge[-1]_pos edge_pos */
2272 GT
, /* edge_pos < edge[-1]_pos */
2275 ALIGNRP
, /* align `edge' to `edge[-1]' */
2278 MDAP_noround
, /* set rp0 and rp1 to `edge' */
2283 SZP1
, /* set zp1 to normal zone 1 */
2292 * bci_action_adjust_bound
2293 * bci_action_adjust_bound_serif
2294 * bci_action_adjust_bound_round
2295 * bci_action_adjust_bound_round_serif
2297 * Higher-level routines for calling `bci_adjust_bound'.
2300 unsigned char FPGM(bci_action_adjust_bound
) [] =
2304 bci_action_adjust_bound
,
2317 unsigned char FPGM(bci_action_adjust_bound_serif
) [] =
2321 bci_action_adjust_bound_serif
,
2334 unsigned char FPGM(bci_action_adjust_bound_round
) [] =
2338 bci_action_adjust_bound_round
,
2351 unsigned char FPGM(bci_action_adjust_bound_round_serif
) [] =
2355 bci_action_adjust_bound_round_serif
,
2372 * Handle the ADJUST action to align an edge of a stem if the other edge
2373 * of the stem has already been moved.
2375 * in: edge2_is_serif
2377 * edge_point (in twilight zone)
2378 * edge2_point (in twilight zone)
2379 * ... stuff for bci_align_segments (edge) ...
2381 * uses: bci_adjust_common
2384 unsigned char FPGM(bci_adjust
) [] =
2395 MDAP_noround
, /* set rp0 and rp1 to `edge' */
2400 SZP1
, /* set zp1 to normal zone 1 */
2410 * bci_action_adjust_serif
2411 * bci_action_adjust_round
2412 * bci_action_adjust_round_serif
2414 * Higher-level routines for calling `bci_adjust'.
2417 unsigned char FPGM(bci_action_adjust
) [] =
2434 unsigned char FPGM(bci_action_adjust_serif
) [] =
2438 bci_action_adjust_serif
,
2451 unsigned char FPGM(bci_action_adjust_round
) [] =
2455 bci_action_adjust_round
,
2468 unsigned char FPGM(bci_action_adjust_round_serif
) [] =
2472 bci_action_adjust_round_serif
,
2489 * Common code for bci_action_stem routines.
2493 #define sal_u_off sal_temp1
2495 #define sal_d_off sal_temp2
2497 #define sal_org_len sal_temp3
2499 #define sal_edge2 sal_temp3
2501 unsigned char FPGM(bci_stem_common
) [] =
2510 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
2518 DUP
, /* s: [...] edge2 edge is_round is_serif edge2 edge edge */
2519 MDAP_noround
, /* set rp0 and rp1 to `edge_point' (for ALIGNRP below) */
2521 MD_orig_ZP2_0
, /* s: [...] edge2 edge is_round is_serif org_len */
2529 bci_compute_stem_width
,
2530 CALL
, /* s: [...] edge2 edge cur_len */
2535 LT
, /* cur_len < 96 */
2540 LTEQ
, /* cur_len <= 64 */
2558 SWAP
, /* s: [...] edge2 cur_len edge */
2563 DUP
, /* s: [...] edge2 cur_len edge edge anchor anchor */
2569 ADD
, /* s: [...] edge2 cur_len edge org_pos */
2576 ADD
, /* s: [...] edge2 cur_len edge org_center */
2581 CALL
, /* s: [...] edge2 cur_len edge org_center cur_pos1 */
2586 SUB
, /* s: ... cur_len edge cur_pos1 (org_center - cur_pos1) */
2593 ABS
, /* s: ... cur_len edge cur_pos1 (org_center - cur_pos1) delta1 */
2600 ABS
, /* s: [...] edge2 cur_len edge cur_pos1 delta1 delta2 */
2602 LT
, /* delta1 < delta2 */
2607 SUB
, /* cur_pos1 = cur_pos1 - u_off */
2613 ADD
, /* cur_pos1 = cur_pos1 + d_off */
2614 EIF
, /* s: [...] edge2 cur_len edge cur_pos1 */
2622 SUB
, /* arg = cur_pos1 - cur_len/2 */
2624 SWAP
, /* s: [...] edge2 cur_len arg edge */
2630 SWAP
, /* s: [...] edge2 cur_len edge edge arg edge */
2633 SHPIX
, /* edge = cur_pos1 - cur_len/2 */
2636 SWAP
, /* s: [...] edge2 cur_len edge */
2640 GC_cur
, /* s: [...] edge2 cur_len edge anchor_pos */
2648 ADD
, /* s: [...] edge2 cur_len edge org_pos */
2657 ADD
, /* s: [...] edge2 cur_len edge org_pos org_center */
2663 CALL
, /* cur_pos1 = ROUND(org_pos) */
2675 SUB
, /* s: [...] edge2 cur_len edge org_center cur_pos1 cur_pos2 */
2686 SUB
, /* s: ... cur_len edge cur_pos1 cur_pos2 (cur_len/2 - org_center) */
2693 ABS
, /* delta1 = ABS(cur_pos1 + cur_len / 2 - org_center) */
2699 ABS
, /* s: ... edge2 cur_len edge cur_pos1 cur_pos2 delta1 delta2 */
2700 LT
, /* delta1 < delta2 */
2702 POP
, /* arg = cur_pos1 */
2706 POP
, /* arg = cur_pos2 */
2707 EIF
, /* s: [...] edge2 cur_len edge arg */
2714 SWAP
, /* s: [...] edge2 cur_len edge edge arg edge */
2717 SHPIX
, /* edge = arg */
2718 EIF
, /* s: [...] edge2 cur_len edge */
2728 * Handle the STEM action to align two edges of a stem, then moving one
2729 * edge again if necessary to stay bound.
2731 * The code after computing `cur_len' to shift `edge' and `edge2'
2732 * is equivalent to the snippet below (part of `ta_latin_hint_edges'):
2735 * if cur_len < = 64:
2742 * org_pos = anchor + (edge_orig - anchor_orig);
2743 * org_center = org_pos + org_len / 2;
2745 * cur_pos1 = ROUND(org_center)
2746 * delta1 = ABS(org_center - (cur_pos1 - u_off))
2747 * delta2 = ABS(org_center - (cur_pos1 + d_off))
2748 * if (delta1 < delta2):
2749 * cur_pos1 = cur_pos1 - u_off
2751 * cur_pos1 = cur_pos1 + d_off
2753 * edge = cur_pos1 - cur_len / 2
2756 * org_pos = anchor + (edge_orig - anchor_orig)
2757 * org_center = org_pos + org_len / 2;
2759 * cur_pos1 = ROUND(org_pos)
2760 * delta1 = ABS(cur_pos1 + cur_len / 2 - org_center)
2761 * cur_pos2 = ROUND(org_pos + org_len) - cur_len
2762 * delta2 = ABS(cur_pos2 + cur_len / 2 - org_center)
2764 * if (delta1 < delta2):
2769 * edge2 = edge + cur_len
2771 * in: edge2_is_serif
2773 * edge_point (in twilight zone)
2774 * edge2_point (in twilight zone)
2775 * edge[-1] (in twilight zone)
2776 * ... stuff for bci_align_segments (edge) ...
2777 * ... stuff for bci_align_segments (edge2)...
2784 * uses: bci_stem_common
2787 unsigned char FPGM(bci_stem_bound
) [] =
2798 ROLL
, /* s: edge[-1] cur_len edge edge2 */
2801 ALIGNRP
, /* align `edge2' with rp0 (still `edge') */
2805 WS
, /* s: edge[-1] cur_len edge edge2 */
2807 SHPIX
, /* edge2 = edge + cur_len */
2809 SWAP
, /* s: edge edge[-1] */
2811 MDAP_noround
, /* set rp0 and rp1 to `edge[-1]' */
2816 GC_cur
, /* s: edge edge[-1]_pos edge_pos */
2817 GT
, /* edge_pos < edge[-1]_pos */
2820 ALIGNRP
, /* align `edge' to `edge[-1]' */
2823 MDAP_noround
, /* set rp0 and rp1 to `edge' */
2828 SZP1
, /* set zp1 to normal zone 1 */
2834 MDAP_noround
, /* set rp0 and rp1 to `edge2' */
2846 * bci_action_stem_bound
2847 * bci_action_stem_bound_serif
2848 * bci_action_stem_bound_round
2849 * bci_action_stem_bound_round_serif
2851 * Higher-level routines for calling `bci_stem_bound'.
2854 unsigned char FPGM(bci_action_stem_bound
) [] =
2858 bci_action_stem_bound
,
2871 unsigned char FPGM(bci_action_stem_bound_serif
) [] =
2875 bci_action_stem_bound_serif
,
2888 unsigned char FPGM(bci_action_stem_bound_round
) [] =
2892 bci_action_stem_bound_round
,
2905 unsigned char FPGM(bci_action_stem_bound_round_serif
) [] =
2909 bci_action_stem_bound_round_serif
,
2926 * Handle the STEM action to align two edges of a stem.
2928 * See `bci_stem_bound' for more details.
2930 * in: edge2_is_serif
2932 * edge_point (in twilight zone)
2933 * edge2_point (in twilight zone)
2934 * ... stuff for bci_align_segments (edge) ...
2935 * ... stuff for bci_align_segments (edge2)...
2942 * uses: bci_stem_common
2945 unsigned char FPGM(bci_stem
) [] =
2957 SWAP
, /* s: cur_len edge2 */
2960 ALIGNRP
, /* align `edge2' with rp0 (still `edge') */
2964 WS
, /* s: cur_len edge2 */
2966 SHPIX
, /* edge2 = edge + cur_len */
2971 SZP1
, /* set zp1 to normal zone 1 */
2977 MDAP_noround
, /* set rp0 and rp1 to `edge2' */
2989 * bci_action_stem_serif
2990 * bci_action_stem_round
2991 * bci_action_stem_round_serif
2993 * Higher-level routines for calling `bci_stem'.
2996 unsigned char FPGM(bci_action_stem
) [] =
3013 unsigned char FPGM(bci_action_stem_serif
) [] =
3017 bci_action_stem_serif
,
3030 unsigned char FPGM(bci_action_stem_round
) [] =
3034 bci_action_stem_round
,
3047 unsigned char FPGM(bci_action_stem_round_serif
) [] =
3051 bci_action_stem_round_serif
,
3068 * Handle the LINK action to link an edge to another one.
3072 * base_point (in twilight zone)
3073 * stem_point (in twilight zone)
3074 * ... stuff for bci_align_segments (base) ...
3077 unsigned char FPGM(bci_link
) [] =
3086 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
3094 DUP
, /* s: stem is_round is_serif stem base base */
3095 MDAP_noround
, /* set rp0 and rp1 to `base_point' (for ALIGNRP below) */
3097 MD_orig_ZP2_0
, /* s: stem is_round is_serif dist_orig */
3100 bci_compute_stem_width
,
3101 CALL
, /* s: stem new_dist */
3105 ALIGNRP
, /* align `stem_point' with `base_point' */
3107 MDAP_noround
, /* set rp0 and rp1 to `stem_point' */
3109 SHPIX
, /* stem_point = base_point + new_dist */
3114 SZP1
, /* set zp1 to normal zone 1 */
3124 * bci_action_link_serif
3125 * bci_action_link_round
3126 * bci_action_link_round_serif
3128 * Higher-level routines for calling `bci_link'.
3131 unsigned char FPGM(bci_action_link
) [] =
3148 unsigned char FPGM(bci_action_link_serif
) [] =
3152 bci_action_link_serif
,
3165 unsigned char FPGM(bci_action_link_round
) [] =
3169 bci_action_link_round
,
3182 unsigned char FPGM(bci_action_link_round_serif
) [] =
3186 bci_action_link_round_serif
,
3203 * Handle the ANCHOR action to align two edges
3204 * and to set the edge anchor.
3206 * The code after computing `cur_len' to shift `edge' and `edge2'
3207 * is equivalent to the snippet below (part of `ta_latin_hint_edges'):
3210 * if cur_len < = 64:
3217 * org_center = edge_orig + org_len / 2
3218 * cur_pos1 = ROUND(org_center)
3220 * error1 = ABS(org_center - (cur_pos1 - u_off))
3221 * error2 = ABS(org_center - (cur_pos1 + d_off))
3222 * if (error1 < error2):
3223 * cur_pos1 = cur_pos1 - u_off
3225 * cur_pos1 = cur_pos1 + d_off
3227 * edge = cur_pos1 - cur_len / 2
3228 * edge2 = edge + cur_len
3231 * edge = ROUND(edge_orig)
3233 * in: edge2_is_serif
3235 * edge_point (in twilight zone)
3236 * edge2_point (in twilight zone)
3237 * ... stuff for bci_align_segments (edge) ...
3246 #define sal_u_off sal_temp1
3248 #define sal_d_off sal_temp2
3250 #define sal_org_len sal_temp3
3252 unsigned char FPGM(bci_anchor
) [] =
3259 /* store anchor point number in `sal_anchor' */
3264 WS
, /* sal_anchor = edge_point */
3268 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
3276 DUP
, /* s: edge2 edge is_round is_serif edge2 edge edge */
3277 MDAP_noround
, /* set rp0 and rp1 to `edge_point' (for ALIGNRP below) */
3279 MD_orig_ZP2_0
, /* s: edge2 edge is_round is_serif org_len */
3287 bci_compute_stem_width
,
3288 CALL
, /* s: edge2 edge cur_len */
3293 LT
, /* cur_len < 96 */
3298 LTEQ
, /* cur_len <= 64 */
3316 SWAP
, /* s: edge2 cur_len edge */
3317 DUP
, /* s: edge2 cur_len edge edge */
3326 ADD
, /* s: edge2 cur_len edge org_center */
3331 CALL
, /* s: edge2 cur_len edge org_center cur_pos1 */
3336 SUB
, /* s: edge2 cur_len edge cur_pos1 (org_center - cur_pos1) */
3343 ABS
, /* s: edge2 cur_len edge cur_pos1 (org_center - cur_pos1) error1 */
3350 ABS
, /* s: edge2 cur_len edge cur_pos1 error1 error2 */
3352 LT
, /* error1 < error2 */
3357 SUB
, /* cur_pos1 = cur_pos1 - u_off */
3363 ADD
, /* cur_pos1 = cur_pos1 + d_off */
3364 EIF
, /* s: edge2 cur_len edge cur_pos1 */
3372 SUB
, /* s: edge2 cur_len edge (cur_pos1 - cur_len/2) */
3376 CINDEX
, /* s: edge2 cur_len edge (cur_pos1 - cur_len/2) edge */
3379 SHPIX
, /* edge = cur_pos1 - cur_len/2 */
3381 SWAP
, /* s: cur_len edge2 */
3383 ALIGNRP
, /* align `edge2' with rp0 (still `edge') */
3385 SHPIX
, /* edge2 = edge1 + cur_len */
3388 POP
, /* s: edge2 edge */
3396 CALL
, /* s: edge2 edge edge_pos round(edge_orig_pos) */
3399 SHPIX
, /* edge = round(edge_orig) */
3401 /* clean up stack */
3408 SZP1
, /* set zp1 to normal zone 1 */
3418 * bci_action_anchor_serif
3419 * bci_action_anchor_round
3420 * bci_action_anchor_round_serif
3422 * Higher-level routines for calling `bci_anchor'.
3425 unsigned char FPGM(bci_action_anchor
) [] =
3442 unsigned char FPGM(bci_action_anchor_serif
) [] =
3446 bci_action_anchor_serif
,
3459 unsigned char FPGM(bci_action_anchor_round
) [] =
3463 bci_action_anchor_round
,
3476 unsigned char FPGM(bci_action_anchor_round_serif
) [] =
3480 bci_action_anchor_round_serif
,
3495 * bci_action_blue_anchor
3497 * Handle the BLUE_ANCHOR action to align an edge with a blue zone
3498 * and to set the edge anchor.
3500 * in: anchor_point (in twilight zone)
3502 * edge_point (in twilight zone)
3503 * ... stuff for bci_align_segments (edge) ...
3507 * uses: bci_action_blue
3510 unsigned char FPGM(bci_action_blue_anchor
) [] =
3514 bci_action_blue_anchor
,
3517 /* store anchor point number in `sal_anchor' */
3535 * Handle the BLUE action to align an edge with a blue zone.
3538 * edge_point (in twilight zone)
3539 * ... stuff for bci_align_segments (edge) ...
3542 unsigned char FPGM(bci_action_blue
) [] =
3551 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
3553 /* move `edge_point' to `blue_cvt_idx' position; */
3554 /* note that we can't use MIAP since this would modify */
3555 /* the twilight point's original coordinates also */
3559 MDAP_noround
, /* set rp0 and rp1 to `edge' */
3561 GC_cur
, /* s: new_pos edge edge_pos */
3564 SUB
, /* s: edge (new_pos - edge_pos) */
3570 SZP1
, /* set zp1 to normal zone 1 */
3581 * Common code for bci_action_serif routines.
3584 unsigned char FPGM(bci_serif_common
) [] =
3593 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
3600 MINDEX
, /* s: [...] serif serif serif serif base */
3602 MDAP_noround
, /* set rp0 and rp1 to `base_point' */
3605 ALIGNRP
, /* align `serif_point' with `base_point' */
3606 SHPIX
, /* serif = base + (serif_orig_pos - base_orig_pos) */
3616 * Move an edge if necessary to stay within a lower bound.
3622 unsigned char FPGM(bci_lower_bound
) [] =
3629 SWAP
, /* s: edge bound */
3631 MDAP_noround
, /* set rp0 and rp1 to `bound' */
3636 GC_cur
, /* s: edge bound_pos edge_pos */
3637 GT
, /* edge_pos < bound_pos */
3640 ALIGNRP
, /* align `edge' to `bound' */
3643 MDAP_noround
, /* set rp0 and rp1 to `edge_point' */
3648 SZP1
, /* set zp1 to normal zone 1 */
3659 * Move an edge if necessary to stay within an upper bound.
3665 unsigned char FPGM(bci_upper_bound
) [] =
3672 SWAP
, /* s: edge bound */
3674 MDAP_noround
, /* set rp0 and rp1 to `bound' */
3679 GC_cur
, /* s: edge bound_pos edge_pos */
3680 LT
, /* edge_pos > bound_pos */
3683 ALIGNRP
, /* align `edge' to `bound' */
3686 MDAP_noround
, /* set rp0 and rp1 to `edge_point' */
3691 SZP1
, /* set zp1 to normal zone 1 */
3700 * bci_lower_upper_bound
3702 * Move an edge if necessary to stay within a lower and lower bound.
3709 unsigned char FPGM(bci_lower_upper_bound
) [] =
3713 bci_lower_upper_bound
,
3716 SWAP
, /* s: upper serif lower */
3718 MDAP_noround
, /* set rp0 and rp1 to `lower' */
3723 GC_cur
, /* s: upper serif lower_pos serif_pos */
3724 GT
, /* serif_pos < lower_pos */
3727 ALIGNRP
, /* align `serif' to `lower' */
3730 SWAP
, /* s: serif upper */
3732 MDAP_noround
, /* set rp0 and rp1 to `upper' */
3737 GC_cur
, /* s: serif upper_pos serif_pos */
3738 LT
, /* serif_pos > upper_pos */
3741 ALIGNRP
, /* align `serif' to `upper' */
3744 MDAP_noround
, /* set rp0 and rp1 to `serif_point' */
3749 SZP1
, /* set zp1 to normal zone 1 */
3760 * Handle the SERIF action to align a serif with its base.
3762 * in: serif_point (in twilight zone)
3763 * base_point (in twilight zone)
3764 * ... stuff for bci_align_segments (serif) ...
3766 * uses: bci_serif_common
3769 unsigned char FPGM(bci_action_serif
) [] =
3780 MDAP_noround
, /* set rp0 and rp1 to `serif_point' */
3785 SZP1
, /* set zp1 to normal zone 1 */
3794 * bci_action_serif_lower_bound
3796 * Handle the SERIF action to align a serif with its base, then moving it
3797 * again if necessary to stay within a lower bound.
3799 * in: serif_point (in twilight zone)
3800 * base_point (in twilight zone)
3801 * edge[-1] (in twilight zone)
3802 * ... stuff for bci_align_segments (serif) ...
3804 * uses: bci_serif_common
3808 unsigned char FPGM(bci_action_serif_lower_bound
) [] =
3812 bci_action_serif_lower_bound
,
3829 * bci_action_serif_upper_bound
3831 * Handle the SERIF action to align a serif with its base, then moving it
3832 * again if necessary to stay within an upper bound.
3834 * in: serif_point (in twilight zone)
3835 * base_point (in twilight zone)
3836 * edge[1] (in twilight zone)
3837 * ... stuff for bci_align_segments (serif) ...
3839 * uses: bci_serif_common
3843 unsigned char FPGM(bci_action_serif_upper_bound
) [] =
3847 bci_action_serif_upper_bound
,
3864 * bci_action_serif_lower_upper_bound
3866 * Handle the SERIF action to align a serif with its base, then moving it
3867 * again if necessary to stay within a lower and upper bound.
3869 * in: serif_point (in twilight zone)
3870 * base_point (in twilight zone)
3871 * edge[-1] (in twilight zone)
3872 * edge[1] (in twilight zone)
3873 * ... stuff for bci_align_segments (serif) ...
3875 * uses: bci_serif_common
3876 * bci_lower_upper_bound
3879 unsigned char FPGM(bci_action_serif_lower_upper_bound
) [] =
3883 bci_action_serif_lower_upper_bound
,
3888 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
3895 bci_lower_upper_bound
,
3904 * bci_serif_anchor_common
3906 * Common code for bci_action_serif_anchor routines.
3909 unsigned char FPGM(bci_serif_anchor_common
) [] =
3913 bci_serif_anchor_common
,
3918 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
3924 WS
, /* sal_anchor = edge_point */
3934 CALL
, /* s: [...] edge edge edge_pos round(edge_orig_pos) */
3937 SHPIX
, /* edge = round(edge_orig) */
3945 * bci_action_serif_anchor
3947 * Handle the SERIF_ANCHOR action to align a serif and to set the edge
3950 * in: edge_point (in twilight zone)
3951 * ... stuff for bci_align_segments (edge) ...
3953 * uses: bci_serif_anchor_common
3956 unsigned char FPGM(bci_action_serif_anchor
) [] =
3960 bci_action_serif_anchor
,
3964 bci_serif_anchor_common
,
3967 MDAP_noround
, /* set rp0 and rp1 to `edge' */
3972 SZP1
, /* set zp1 to normal zone 1 */
3981 * bci_action_serif_anchor_lower_bound
3983 * Handle the SERIF_ANCHOR action to align a serif and to set the edge
3984 * anchor, then moving it again if necessary to stay within a lower
3987 * in: edge_point (in twilight zone)
3988 * edge[-1] (in twilight zone)
3989 * ... stuff for bci_align_segments (edge) ...
3991 * uses: bci_serif_anchor_common
3995 unsigned char FPGM(bci_action_serif_anchor_lower_bound
) [] =
3999 bci_action_serif_anchor_lower_bound
,
4003 bci_serif_anchor_common
,
4016 * bci_action_serif_anchor_upper_bound
4018 * Handle the SERIF_ANCHOR action to align a serif and to set the edge
4019 * anchor, then moving it again if necessary to stay within an upper
4022 * in: edge_point (in twilight zone)
4023 * edge[1] (in twilight zone)
4024 * ... stuff for bci_align_segments (edge) ...
4026 * uses: bci_serif_anchor_common
4030 unsigned char FPGM(bci_action_serif_anchor_upper_bound
) [] =
4034 bci_action_serif_anchor_upper_bound
,
4038 bci_serif_anchor_common
,
4051 * bci_action_serif_anchor_lower_upper_bound
4053 * Handle the SERIF_ANCHOR action to align a serif and to set the edge
4054 * anchor, then moving it again if necessary to stay within a lower and
4057 * in: edge_point (in twilight zone)
4058 * edge[-1] (in twilight zone)
4059 * edge[1] (in twilight zone)
4060 * ... stuff for bci_align_segments (edge) ...
4062 * uses: bci_serif_anchor_common
4063 * bci_lower_upper_bound
4066 unsigned char FPGM(bci_action_serif_anchor_lower_upper_bound
) [] =
4070 bci_action_serif_anchor_lower_upper_bound
,
4074 bci_serif_anchor_common
,
4078 bci_lower_upper_bound
,
4087 * bci_serif_link1_common
4089 * Common code for bci_action_serif_link1 routines.
4092 unsigned char FPGM(bci_serif_link1_common
) [] =
4096 bci_serif_link1_common
,
4101 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
4105 CINDEX
, /* s: [...] after edge before after */
4108 CINDEX
, /* s: [...] after edge before after before */
4112 EQ
, /* after_orig_pos == before_orig_pos */
4113 IF
, /* s: [...] after edge before */
4114 MDAP_noround
, /* set rp0 and rp1 to `before' */
4116 ALIGNRP
, /* align `edge' with `before' */
4121 /* we have to execute `a*b/c', with b/c very near to 1: */
4122 /* to avoid overflow while retaining precision, */
4123 /* we transform this to `a + a * (b-c)/c' */
4127 CINDEX
, /* s: [...] after edge before edge */
4130 CINDEX
, /* s: [...] after edge before edge before */
4131 MD_orig_ZP2_0
, /* a = edge_orig_pos - before_orig_pos */
4136 CINDEX
, /* s: [...] after edge before a a after */
4139 CINDEX
, /* s: [...] after edge before a a after before */
4140 MD_orig_ZP2_0
, /* c = after_orig_pos - before_orig_pos */
4144 CINDEX
, /* s: [...] after edge before a a c after */
4147 CINDEX
, /* s: [...] after edge before a a c after before */
4148 MD_cur
, /* b = after_pos - before_pos */
4152 CINDEX
, /* s: [...] after edge before a a c b c */
4158 MUL
, /* (b-c) in 16.16 format */
4160 DIV
, /* s: [...] after edge before a a (b-c)/c */
4162 MUL
, /* a * (b-c)/c * 2^10 */
4166 DIV
, /* a * (b-c)/c */
4170 MDAP_noround
, /* set rp0 and rp1 to `before' */
4171 SWAP
, /* s: [...] after a*b/c edge */
4174 ALIGNRP
, /* align `edge' with `before' */
4176 SHPIX
, /* shift `edge' by `a*b/c' */
4178 SWAP
, /* s: [...] edge after */
4188 * bci_action_serif_link1
4190 * Handle the SERIF_LINK1 action to align a serif, depending on edges
4193 * in: before_point (in twilight zone)
4194 * edge_point (in twilight zone)
4195 * after_point (in twilight zone)
4196 * ... stuff for bci_align_segments (edge) ...
4198 * uses: bci_serif_link1_common
4201 unsigned char FPGM(bci_action_serif_link1
) [] =
4205 bci_action_serif_link1
,
4209 bci_serif_link1_common
,
4212 MDAP_noround
, /* set rp0 and rp1 to `edge' */
4217 SZP1
, /* set zp1 to normal zone 1 */
4226 * bci_action_serif_link1_lower_bound
4228 * Handle the SERIF_LINK1 action to align a serif, depending on edges
4229 * before and after. Additionally, move the serif again if necessary to
4230 * stay within a lower bound.
4232 * in: before_point (in twilight zone)
4233 * edge_point (in twilight zone)
4234 * after_point (in twilight zone)
4235 * edge[-1] (in twilight zone)
4236 * ... stuff for bci_align_segments (edge) ...
4238 * uses: bci_serif_link1_common
4242 unsigned char FPGM(bci_action_serif_link1_lower_bound
) [] =
4246 bci_action_serif_link1_lower_bound
,
4250 bci_serif_link1_common
,
4263 * bci_action_serif_link1_upper_bound
4265 * Handle the SERIF_LINK1 action to align a serif, depending on edges
4266 * before and after. Additionally, move the serif again if necessary to
4267 * stay within an upper bound.
4269 * in: before_point (in twilight zone)
4270 * edge_point (in twilight zone)
4271 * after_point (in twilight zone)
4272 * edge[1] (in twilight zone)
4273 * ... stuff for bci_align_segments (edge) ...
4275 * uses: bci_serif_link1_common
4279 unsigned char FPGM(bci_action_serif_link1_upper_bound
) [] =
4283 bci_action_serif_link1_upper_bound
,
4287 bci_serif_link1_common
,
4300 * bci_action_serif_link1_lower_upper_bound
4302 * Handle the SERIF_LINK1 action to align a serif, depending on edges
4303 * before and after. Additionally, move the serif again if necessary to
4304 * stay within a lower and upper bound.
4306 * in: before_point (in twilight zone)
4307 * edge_point (in twilight zone)
4308 * after_point (in twilight zone)
4309 * edge[-1] (in twilight zone)
4310 * edge[1] (in twilight zone)
4311 * ... stuff for bci_align_segments (edge) ...
4313 * uses: bci_serif_link1_common
4314 * bci_lower_upper_bound
4317 unsigned char FPGM(bci_action_serif_link1_lower_upper_bound
) [] =
4321 bci_action_serif_link1_lower_upper_bound
,
4325 bci_serif_link1_common
,
4329 bci_lower_upper_bound
,
4338 * bci_serif_link2_common
4340 * Common code for bci_action_serif_link2 routines.
4343 unsigned char FPGM(bci_serif_link2_common
) [] =
4347 bci_serif_link2_common
,
4352 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
4354 DUP
, /* s: [...] edge edge */
4358 DUP
, /* s: [...] edge edge anchor anchor */
4359 MDAP_noround
, /* set rp0 and rp1 to `sal_anchor' */
4370 DIV
, /* delta = (edge_orig_pos - anchor_orig_pos + 16) & ~31 */
4375 ALIGNRP
, /* align `edge' with `sal_anchor' */
4377 SHPIX
, /* shift `edge' by `delta' */
4385 * bci_action_serif_link2
4387 * Handle the SERIF_LINK2 action to align a serif relative to the anchor.
4389 * in: edge_point (in twilight zone)
4390 * ... stuff for bci_align_segments (edge) ...
4392 * uses: bci_serif_link2_common
4395 unsigned char FPGM(bci_action_serif_link2
) [] =
4399 bci_action_serif_link2
,
4403 bci_serif_link2_common
,
4406 MDAP_noround
, /* set rp0 and rp1 to `edge' */
4411 SZP1
, /* set zp1 to normal zone 1 */
4420 * bci_action_serif_link2_lower_bound
4422 * Handle the SERIF_LINK2 action to align a serif relative to the anchor.
4423 * Additionally, move the serif again if necessary to stay within a lower
4426 * in: edge_point (in twilight zone)
4427 * edge[-1] (in twilight zone)
4428 * ... stuff for bci_align_segments (edge) ...
4430 * uses: bci_serif_link2_common
4434 unsigned char FPGM(bci_action_serif_link2_lower_bound
) [] =
4438 bci_action_serif_link2_lower_bound
,
4442 bci_serif_link2_common
,
4455 * bci_action_serif_link2_upper_bound
4457 * Handle the SERIF_LINK2 action to align a serif relative to the anchor.
4458 * Additionally, move the serif again if necessary to stay within an upper
4461 * in: edge_point (in twilight zone)
4462 * edge[1] (in twilight zone)
4463 * ... stuff for bci_align_segments (edge) ...
4465 * uses: bci_serif_link2_common
4469 unsigned char FPGM(bci_action_serif_link2_upper_bound
) [] =
4473 bci_action_serif_link2_upper_bound
,
4477 bci_serif_link2_common
,
4490 * bci_action_serif_link2_lower_upper_bound
4492 * Handle the SERIF_LINK2 action to align a serif relative to the anchor.
4493 * Additionally, move the serif again if necessary to stay within a lower
4496 * in: edge_point (in twilight zone)
4497 * edge[-1] (in twilight zone)
4498 * edge[1] (in twilight zone)
4499 * ... stuff for bci_align_segments (edge) ...
4501 * uses: bci_serif_link2_common
4502 * bci_lower_upper_bound
4505 unsigned char FPGM(bci_action_serif_link2_lower_upper_bound
) [] =
4509 bci_action_serif_link2_lower_upper_bound
,
4513 bci_serif_link2_common
,
4517 bci_lower_upper_bound
,
4528 * This is the top-level glyph hinting function which parses the arguments
4529 * on the stack and calls subroutines.
4531 * in: action_0_func_idx
4537 * uses: bci_action_ip_before
4538 * bci_action_ip_after
4540 * bci_action_ip_between
4542 * bci_action_adjust_bound
4543 * bci_action_adjust_bound_serif
4544 * bci_action_adjust_bound_round
4545 * bci_action_adjust_bound_round_serif
4547 * bci_action_stem_bound
4548 * bci_action_stem_bound_serif
4549 * bci_action_stem_bound_round
4550 * bci_action_stem_bound_round_serif
4553 * bci_action_link_serif
4554 * bci_action_link_round
4555 * bci_action_link_round_serif
4558 * bci_action_anchor_serif
4559 * bci_action_anchor_round
4560 * bci_action_anchor_round_serif
4562 * bci_action_blue_anchor
4565 * bci_action_adjust_serif
4566 * bci_action_adjust_round
4567 * bci_action_adjust_round_serif
4570 * bci_action_stem_serif
4571 * bci_action_stem_round
4572 * bci_action_stem_round_serif
4577 * bci_action_serif_lower_bound
4578 * bci_action_serif_upper_bound
4579 * bci_action_serif_lower_upper_bound
4581 * bci_action_serif_anchor
4582 * bci_action_serif_anchor_lower_bound
4583 * bci_action_serif_anchor_upper_bound
4584 * bci_action_serif_anchor_lower_upper_bound
4586 * bci_action_serif_link1
4587 * bci_action_serif_link1_lower_bound
4588 * bci_action_serif_link1_upper_bound
4589 * bci_action_serif_link1_lower_upper_bound
4591 * bci_action_serif_link2
4592 * bci_action_serif_link2_lower_bound
4593 * bci_action_serif_link2_upper_bound
4594 * bci_action_serif_link2_lower_upper_bound
4596 * CVT: cvtl_is_subglyph
4599 unsigned char FPGM(bci_hint_glyph
) [] =
4607 /* loop until all data on stack is used */
4616 JROT
, /* goto start_loop */
4620 SZP2
, /* set zp2 to normal zone 1 */
4628 #define COPY_FPGM(func_name) \
4629 memcpy(buf_p, fpgm_ ## func_name, \
4630 sizeof (fpgm_ ## func_name)); \
4631 buf_p += sizeof (fpgm_ ## func_name) \
4634 TA_table_build_fpgm(FT_Byte
** fpgm
,
4644 buf_len
= sizeof (FPGM(bci_round
))
4645 + sizeof (FPGM(bci_compute_stem_width_a
))
4647 + sizeof (FPGM(bci_compute_stem_width_b
))
4649 + sizeof (FPGM(bci_compute_stem_width_c
))
4650 + sizeof (FPGM(bci_loop
))
4651 + sizeof (FPGM(bci_cvt_rescale
))
4652 + sizeof (FPGM(bci_blue_round_a
))
4654 + sizeof (FPGM(bci_blue_round_b
))
4655 + sizeof (FPGM(bci_decrement_component_counter
))
4656 + sizeof (FPGM(bci_get_point_extrema
))
4657 + sizeof (FPGM(bci_nibbles
))
4659 + sizeof (FPGM(bci_create_segment
))
4660 + sizeof (FPGM(bci_create_segments
))
4661 + sizeof (FPGM(bci_create_segments_0
))
4662 + sizeof (FPGM(bci_create_segments_1
))
4663 + sizeof (FPGM(bci_create_segments_2
))
4664 + sizeof (FPGM(bci_create_segments_3
))
4665 + sizeof (FPGM(bci_create_segments_4
))
4666 + sizeof (FPGM(bci_create_segments_5
))
4667 + sizeof (FPGM(bci_create_segments_6
))
4668 + sizeof (FPGM(bci_create_segments_7
))
4669 + sizeof (FPGM(bci_create_segments_8
))
4670 + sizeof (FPGM(bci_create_segments_9
))
4671 + sizeof (FPGM(bci_create_segments_composite
))
4672 + sizeof (FPGM(bci_create_segments_composite_0
))
4673 + sizeof (FPGM(bci_create_segments_composite_1
))
4674 + sizeof (FPGM(bci_create_segments_composite_2
))
4675 + sizeof (FPGM(bci_create_segments_composite_3
))
4676 + sizeof (FPGM(bci_create_segments_composite_4
))
4677 + sizeof (FPGM(bci_create_segments_composite_5
))
4678 + sizeof (FPGM(bci_create_segments_composite_6
))
4679 + sizeof (FPGM(bci_create_segments_composite_7
))
4680 + sizeof (FPGM(bci_create_segments_composite_8
))
4681 + sizeof (FPGM(bci_create_segments_composite_9
))
4682 + sizeof (FPGM(bci_align_segment
))
4683 + sizeof (FPGM(bci_align_segments
))
4685 + sizeof (FPGM(bci_scale_contour
))
4686 + sizeof (FPGM(bci_scale_glyph
))
4687 + sizeof (FPGM(bci_scale_composite_glyph
))
4688 + sizeof (FPGM(bci_shift_contour
))
4689 + sizeof (FPGM(bci_shift_subglyph
))
4691 + sizeof (FPGM(bci_ip_outer_align_point
))
4692 + sizeof (FPGM(bci_ip_on_align_points
))
4693 + sizeof (FPGM(bci_ip_between_align_point
))
4694 + sizeof (FPGM(bci_ip_between_align_points
))
4696 + sizeof (FPGM(bci_adjust_common
))
4697 + sizeof (FPGM(bci_stem_common
))
4698 + sizeof (FPGM(bci_serif_common
))
4699 + sizeof (FPGM(bci_serif_anchor_common
))
4700 + sizeof (FPGM(bci_serif_link1_common
))
4701 + sizeof (FPGM(bci_serif_link2_common
))
4703 + sizeof (FPGM(bci_lower_bound
))
4704 + sizeof (FPGM(bci_upper_bound
))
4705 + sizeof (FPGM(bci_lower_upper_bound
))
4707 + sizeof (FPGM(bci_action_ip_before
))
4708 + sizeof (FPGM(bci_action_ip_after
))
4709 + sizeof (FPGM(bci_action_ip_on
))
4710 + sizeof (FPGM(bci_action_ip_between
))
4712 + sizeof (FPGM(bci_adjust_bound
))
4713 + sizeof (FPGM(bci_action_adjust_bound
))
4714 + sizeof (FPGM(bci_action_adjust_bound_serif
))
4715 + sizeof (FPGM(bci_action_adjust_bound_round
))
4716 + sizeof (FPGM(bci_action_adjust_bound_round_serif
))
4717 + sizeof (FPGM(bci_stem_bound
))
4718 + sizeof (FPGM(bci_action_stem_bound
))
4719 + sizeof (FPGM(bci_action_stem_bound_serif
))
4720 + sizeof (FPGM(bci_action_stem_bound_round
))
4721 + sizeof (FPGM(bci_action_stem_bound_round_serif
))
4722 + sizeof (FPGM(bci_link
))
4723 + sizeof (FPGM(bci_action_link
))
4724 + sizeof (FPGM(bci_action_link_serif
))
4725 + sizeof (FPGM(bci_action_link_round
))
4726 + sizeof (FPGM(bci_action_link_round_serif
))
4727 + sizeof (FPGM(bci_anchor
))
4728 + sizeof (FPGM(bci_action_anchor
))
4729 + sizeof (FPGM(bci_action_anchor_serif
))
4730 + sizeof (FPGM(bci_action_anchor_round
))
4731 + sizeof (FPGM(bci_action_anchor_round_serif
))
4732 + sizeof (FPGM(bci_action_blue_anchor
))
4733 + sizeof (FPGM(bci_adjust
))
4734 + sizeof (FPGM(bci_action_adjust
))
4735 + sizeof (FPGM(bci_action_adjust_serif
))
4736 + sizeof (FPGM(bci_action_adjust_round
))
4737 + sizeof (FPGM(bci_action_adjust_round_serif
))
4738 + sizeof (FPGM(bci_stem
))
4739 + sizeof (FPGM(bci_action_stem
))
4740 + sizeof (FPGM(bci_action_stem_serif
))
4741 + sizeof (FPGM(bci_action_stem_round
))
4742 + sizeof (FPGM(bci_action_stem_round_serif
))
4743 + sizeof (FPGM(bci_action_blue
))
4744 + sizeof (FPGM(bci_action_serif
))
4745 + sizeof (FPGM(bci_action_serif_lower_bound
))
4746 + sizeof (FPGM(bci_action_serif_upper_bound
))
4747 + sizeof (FPGM(bci_action_serif_lower_upper_bound
))
4748 + sizeof (FPGM(bci_action_serif_anchor
))
4749 + sizeof (FPGM(bci_action_serif_anchor_lower_bound
))
4750 + sizeof (FPGM(bci_action_serif_anchor_upper_bound
))
4751 + sizeof (FPGM(bci_action_serif_anchor_lower_upper_bound
))
4752 + sizeof (FPGM(bci_action_serif_link1
))
4753 + sizeof (FPGM(bci_action_serif_link1_lower_bound
))
4754 + sizeof (FPGM(bci_action_serif_link1_upper_bound
))
4755 + sizeof (FPGM(bci_action_serif_link1_lower_upper_bound
))
4756 + sizeof (FPGM(bci_action_serif_link2
))
4757 + sizeof (FPGM(bci_action_serif_link2_lower_bound
))
4758 + sizeof (FPGM(bci_action_serif_link2_upper_bound
))
4759 + sizeof (FPGM(bci_action_serif_link2_lower_upper_bound
))
4761 + sizeof (FPGM(bci_hint_glyph
));
4763 /* buffer length must be a multiple of four */
4764 len
= (buf_len
+ 3) & ~3;
4765 buf
= (FT_Byte
*)malloc(len
);
4767 return FT_Err_Out_Of_Memory
;
4769 /* pad end of buffer with zeros */
4770 buf
[len
- 1] = 0x00;
4771 buf
[len
- 2] = 0x00;
4772 buf
[len
- 3] = 0x00;
4774 /* copy font program into buffer and fill in the missing variables */
4777 COPY_FPGM(bci_round
);
4778 COPY_FPGM(bci_compute_stem_width_a
);
4779 *(buf_p
++) = (unsigned char)CVT_VERT_WIDTHS_OFFSET(font
);
4780 COPY_FPGM(bci_compute_stem_width_b
);
4781 *(buf_p
++) = (unsigned char)CVT_VERT_WIDTHS_OFFSET(font
);
4782 COPY_FPGM(bci_compute_stem_width_c
);
4783 COPY_FPGM(bci_loop
);
4784 COPY_FPGM(bci_cvt_rescale
);
4785 COPY_FPGM(bci_blue_round_a
);
4786 *(buf_p
++) = (unsigned char)CVT_BLUES_SIZE(font
);
4787 COPY_FPGM(bci_blue_round_b
);
4788 COPY_FPGM(bci_decrement_component_counter
);
4789 COPY_FPGM(bci_get_point_extrema
);
4790 COPY_FPGM(bci_nibbles
);
4792 COPY_FPGM(bci_create_segment
);
4793 COPY_FPGM(bci_create_segments
);
4794 COPY_FPGM(bci_create_segments_0
);
4795 COPY_FPGM(bci_create_segments_1
);
4796 COPY_FPGM(bci_create_segments_2
);
4797 COPY_FPGM(bci_create_segments_3
);
4798 COPY_FPGM(bci_create_segments_4
);
4799 COPY_FPGM(bci_create_segments_5
);
4800 COPY_FPGM(bci_create_segments_6
);
4801 COPY_FPGM(bci_create_segments_7
);
4802 COPY_FPGM(bci_create_segments_8
);
4803 COPY_FPGM(bci_create_segments_9
);
4804 COPY_FPGM(bci_create_segments_composite
);
4805 COPY_FPGM(bci_create_segments_composite_0
);
4806 COPY_FPGM(bci_create_segments_composite_1
);
4807 COPY_FPGM(bci_create_segments_composite_2
);
4808 COPY_FPGM(bci_create_segments_composite_3
);
4809 COPY_FPGM(bci_create_segments_composite_4
);
4810 COPY_FPGM(bci_create_segments_composite_5
);
4811 COPY_FPGM(bci_create_segments_composite_6
);
4812 COPY_FPGM(bci_create_segments_composite_7
);
4813 COPY_FPGM(bci_create_segments_composite_8
);
4814 COPY_FPGM(bci_create_segments_composite_9
);
4815 COPY_FPGM(bci_align_segment
);
4816 COPY_FPGM(bci_align_segments
);
4818 COPY_FPGM(bci_scale_contour
);
4819 COPY_FPGM(bci_scale_glyph
);
4820 COPY_FPGM(bci_scale_composite_glyph
);
4821 COPY_FPGM(bci_shift_contour
);
4822 COPY_FPGM(bci_shift_subglyph
);
4824 COPY_FPGM(bci_ip_outer_align_point
);
4825 COPY_FPGM(bci_ip_on_align_points
);
4826 COPY_FPGM(bci_ip_between_align_point
);
4827 COPY_FPGM(bci_ip_between_align_points
);
4829 COPY_FPGM(bci_adjust_common
);
4830 COPY_FPGM(bci_stem_common
);
4831 COPY_FPGM(bci_serif_common
);
4832 COPY_FPGM(bci_serif_anchor_common
);
4833 COPY_FPGM(bci_serif_link1_common
);
4834 COPY_FPGM(bci_serif_link2_common
);
4836 COPY_FPGM(bci_lower_bound
);
4837 COPY_FPGM(bci_upper_bound
);
4838 COPY_FPGM(bci_lower_upper_bound
);
4840 COPY_FPGM(bci_action_ip_before
);
4841 COPY_FPGM(bci_action_ip_after
);
4842 COPY_FPGM(bci_action_ip_on
);
4843 COPY_FPGM(bci_action_ip_between
);
4845 COPY_FPGM(bci_adjust_bound
);
4846 COPY_FPGM(bci_action_adjust_bound
);
4847 COPY_FPGM(bci_action_adjust_bound_serif
);
4848 COPY_FPGM(bci_action_adjust_bound_round
);
4849 COPY_FPGM(bci_action_adjust_bound_round_serif
);
4850 COPY_FPGM(bci_stem_bound
);
4851 COPY_FPGM(bci_action_stem_bound
);
4852 COPY_FPGM(bci_action_stem_bound_serif
);
4853 COPY_FPGM(bci_action_stem_bound_round
);
4854 COPY_FPGM(bci_action_stem_bound_round_serif
);
4855 COPY_FPGM(bci_link
);
4856 COPY_FPGM(bci_action_link
);
4857 COPY_FPGM(bci_action_link_serif
);
4858 COPY_FPGM(bci_action_link_round
);
4859 COPY_FPGM(bci_action_link_round_serif
);
4860 COPY_FPGM(bci_anchor
);
4861 COPY_FPGM(bci_action_anchor
);
4862 COPY_FPGM(bci_action_anchor_serif
);
4863 COPY_FPGM(bci_action_anchor_round
);
4864 COPY_FPGM(bci_action_anchor_round_serif
);
4865 COPY_FPGM(bci_action_blue_anchor
);
4866 COPY_FPGM(bci_adjust
);
4867 COPY_FPGM(bci_action_adjust
);
4868 COPY_FPGM(bci_action_adjust_serif
);
4869 COPY_FPGM(bci_action_adjust_round
);
4870 COPY_FPGM(bci_action_adjust_round_serif
);
4871 COPY_FPGM(bci_stem
);
4872 COPY_FPGM(bci_action_stem
);
4873 COPY_FPGM(bci_action_stem_serif
);
4874 COPY_FPGM(bci_action_stem_round
);
4875 COPY_FPGM(bci_action_stem_round_serif
);
4876 COPY_FPGM(bci_action_blue
);
4877 COPY_FPGM(bci_action_serif
);
4878 COPY_FPGM(bci_action_serif_lower_bound
);
4879 COPY_FPGM(bci_action_serif_upper_bound
);
4880 COPY_FPGM(bci_action_serif_lower_upper_bound
);
4881 COPY_FPGM(bci_action_serif_anchor
);
4882 COPY_FPGM(bci_action_serif_anchor_lower_bound
);
4883 COPY_FPGM(bci_action_serif_anchor_upper_bound
);
4884 COPY_FPGM(bci_action_serif_anchor_lower_upper_bound
);
4885 COPY_FPGM(bci_action_serif_link1
);
4886 COPY_FPGM(bci_action_serif_link1_lower_bound
);
4887 COPY_FPGM(bci_action_serif_link1_upper_bound
);
4888 COPY_FPGM(bci_action_serif_link1_lower_upper_bound
);
4889 COPY_FPGM(bci_action_serif_link2
);
4890 COPY_FPGM(bci_action_serif_link2_lower_bound
);
4891 COPY_FPGM(bci_action_serif_link2_upper_bound
);
4892 COPY_FPGM(bci_action_serif_link2_lower_upper_bound
);
4894 COPY_FPGM(bci_hint_glyph
);
4897 *fpgm_len
= buf_len
;
4904 TA_sfnt_build_fpgm_table(SFNT
* sfnt
,
4913 error
= TA_sfnt_add_table_info(sfnt
);
4917 error
= TA_table_build_fpgm(&fpgm_buf
, &fpgm_len
, font
);
4921 if (fpgm_len
> sfnt
->max_instructions
)
4922 sfnt
->max_instructions
= fpgm_len
;
4924 /* in case of success, `fpgm_buf' gets linked */
4925 /* and is eventually freed in `TA_font_unload' */
4926 error
= TA_font_add_table(font
,
4927 &sfnt
->table_infos
[sfnt
->num_table_infos
- 1],
4928 TTAG_fpgm
, fpgm_len
, fpgm_buf
);
4938 /* end of tafpgm.c */