4 * Copyright (C) 2011-2017 by Werner Lemberg.
6 * This file is part of the ttfautohint library, and may only be used,
7 * modified, and distributed under the terms given in `COPYING'. By
8 * continuing to use, modify, or distribute this file you indicate that you
9 * have read `COPYING' and understand and accept it fully.
11 * The file `COPYING' mentioned in the previous paragraph is distributed
12 * with the ttfautohint library.
19 /* we need the following macro */
20 /* so that `func_name' doesn't get replaced with its #defined value */
21 /* (as defined in `tabytecode.h') */
23 #define FPGM(func_name) fpgm_ ## func_name
27 * Due to a bug in FreeType up to and including version 2.4.7,
28 * it is not possible to use MD_orig with twilight points.
29 * We circumvent this by using GC_orig.
31 #define MD_orig_fixed \
38 #define MD_orig_ZP2_0 \
42 #define MD_orig_ZP2_1 \
54 * Older versions of Monotype's `iType' bytecode interpreter have a serious
55 * bug: The DIV instruction rounds the result, while the correct operation
56 * is truncation. (Note, however, that MUL always rounds the result.)
57 * Since many printers contain this rasterizer without any possibility to
58 * update to a non-buggy version, we have to work around the problem.
60 * DIV and MUL work on 26.6 numbers which means that the numerator gets
61 * multiplied by 64 before the division, and the product gets divided by 64
62 * after the multiplication, respectively. For example, to divide 2 by 3,
70 * The correct formula to divide two values in 26.6 format with truncation
75 * while older `iType' versions incorrectly apply rounding by using
79 * Doing our 2/3 division, we have a=2 and b=3*64, so we get
81 * (2*64 + (3*64)/2) / (3*64) = 1
83 * instead of the correct result 0.
85 * The solution to the rounding issue is to use a 26.6 value as an
86 * intermediate result so that we can truncate to the nearest integer (in
87 * 26.6 format) with the FLOOR operator before converting back to a plain
88 * integer (in 32.0 format).
90 * For the common divisions by 2 and 2^10 we define macros.
92 #define DIV_POS_BY_2 \
95 DIV, /* multiply by 64, then divide by 2 */ \
99 MUL /* multiply by 1, then divide by 64 */
112 ADD, /* add 1 if value is negative */ \
119 #define DIV_BY_1024 \
139 /* a convenience shorthand for scaling; see `bci_cvt_rescale' for details */
145 MUL, /* delta * 2^10 */ \
146 DIV_BY_1024, /* delta */ \
150 /* in the comments below, the top of the stack (`s:') */
151 /* is the rightmost element; the stack is shown */
152 /* after the instruction on the same line has been executed */
158 * Optimize the alignment of the top of small letters to the pixel grid.
160 * This function gets used in the `prep' table.
162 * in: blue_idx (CVT index for the style's top of small letters blue zone)
164 * sal: sal_i (CVT index of the style's scaling value;
165 * gets incremented by 1 after execution)
168 static const unsigned char FPGM(bci_align_x_height_a
) [] =
175 /* only get CVT value for non-zero index */
184 DUP
, /* s: blue blue blue */
188 /* if (font->increase_x_height) */
191 static const unsigned char FPGM(bci_align_x_height_b1a
) [] =
194 /* apply much `stronger' rounding up of x height for */
195 /* 6 <= PPEM <= increase_x_height */
201 /* %d, x height increase limit */
203 static const unsigned char FPGM(bci_align_x_height_b1b
) [] =
214 52, /* threshold = 52 */
218 40, /* threshold = 40 */
222 FLOOR
, /* fitted = FLOOR(blue + threshold) */
228 /* if (!font->increase_x_height) */
231 static const unsigned char FPGM(bci_align_x_height_b2
) [] =
237 FLOOR
, /* fitted = FLOOR(blue + 40) */
243 static const unsigned char FPGM(bci_align_x_height_c
) [] =
246 DUP
, /* s: blue blue fitted fitted */
249 IF
, /* s: blue fitted */
253 SUB
, /* s: blue (fitted-blue) */
260 MUL
, /* (fitted-blue) in 16.16 format */
262 DIV
, /* factor = ((fitted-blue) / blue) in 16.16 format */
274 RS
, /* s: factor idx */
283 ADD
, /* sal_i = sal_i + 1 */
294 * Round a 26.6 number. Contrary to the ROUND bytecode instruction, no
295 * engine specific corrections are applied.
302 static const unsigned char FPGM(bci_round
) [] =
320 * bci_smooth_stem_width
322 * This is the equivalent to the following code from function
323 * `ta_latin_compute_stem_width':
331 * else if base_is_round:
337 * delta = |dist - std_width|
348 * delta = delta - dist
351 * dist = dist + delta
352 * else if delta < 32:
354 * else if delta < 54:
357 * dist = dist + delta
361 * if width * base_delta > 0:
363 * bdelta = base_delta
365 * bdelta = (base_delta * (30 - ppem)) / 20
369 * dist = ROUND(dist - bdelta)
376 * If `cvtl_ignore_std_width' is set, we simply set `std_width'
385 * sal: sal_vwidth_data_offset
389 * cvtl_ignore_std_width
394 static const unsigned char FPGM(bci_smooth_stem_width
) [] =
398 bci_smooth_stem_width
,
402 ABS
, /* s: base_is_round stem_is_serif width dist */
407 LT
, /* dist < 3*64 */
411 MINDEX
, /* s: base_is_round width dist (dist<3*64) stem_is_serif */
412 AND
, /* stem_is_serif && dist < 3*64 */
417 sal_vwidth_data_offset
,
419 RCVT
, /* first indirection */
420 MUL
, /* divide by 64 */
421 RCVT
, /* second indirection */
424 cvtl_ignore_std_width
,
427 POP
, /* s: ... dist (stem_is_serif && dist < 3*64) 40 */
430 CINDEX
, /* standard_width = dist */
433 GT
, /* standard_width < 40 */
434 OR
, /* (stem_is_serif && dist < 3*64) || standard_width < 40 */
436 IF
, /* s: base_is_round width dist */
442 ROLL
, /* s: width dist base_is_round */
443 IF
, /* s: width dist */
448 IF
, /* s: width dist */
459 IF
, /* s: width dist */
466 DUP
, /* s: width dist dist */
469 sal_vwidth_data_offset
,
471 RCVT
, /* first indirection */
472 MUL
, /* divide by 64 */
473 RCVT
, /* second indirection */
475 ABS
, /* s: width dist delta */
480 IF
, /* s: width dist */
484 sal_vwidth_data_offset
,
486 RCVT
, /* first indirection */
487 MUL
, /* divide by 64 */
488 RCVT
, /* second indirection; dist = std_width */
500 DUP
, /* s: width dist dist */
503 LT
, /* dist < 3*64 */
505 DUP
, /* s: width delta dist */
506 FLOOR
, /* dist = FLOOR(dist) */
507 DUP
, /* s: width delta dist dist */
509 ROLL
, /* s: width dist delta dist */
510 SUB
, /* delta = delta - dist */
512 DUP
, /* s: width dist delta delta */
516 IF
, /* s: width dist delta */
517 ADD
, /* dist = dist + delta */
528 ADD
, /* dist = dist + 10 */
539 ADD
, /* dist = dist + 54 */
542 ADD
, /* dist = dist + delta */
551 CINDEX
, /* s: width dist width */
555 MUL
, /* s: width dist width*base_delta */
558 GT
, /* width * base_delta > 0 */
561 0, /* s: width dist bdelta */
571 RS
, /* bdelta = base_delta */
587 MUL
, /* (30 - ppem) in 26.6 format */
591 MUL
, /* base_delta * (30 - ppem) */
595 DIV
, /* bdelta = (base_delta * (30 - ppem)) / 20 */
599 ABS
, /* bdelta = |bdelta| */
600 SUB
, /* dist = dist - bdelta */
605 CALL
, /* dist = round(dist) */
610 SWAP
, /* s: dist width */
615 NEG
, /* dist = -dist */
627 * An auxiliary function for `bci_strong_stem_width'.
629 * in: n (initialized with CVT index for first vertical width)
641 static const unsigned char FPGM(bci_get_best_width
) [] =
649 RCVT
, /* s: dist n w */
653 CINDEX
, /* s: dist n w w dist */
655 ABS
, /* s: dist n w d */
659 RS
, /* s: dist n w d d best */
669 WS
, /* reference = w */
686 * bci_strong_stem_width
688 * This is the equivalent to the following code (function
689 * `ta_latin_snap_width' and some lines from
690 * `ta_latin_compute_stem_width'):
696 * for n in 0 .. num_widths:
704 * if dist >= reference:
705 * if dist < ROUND(reference) + 48:
708 * if dist > ROUND(reference) - 48:
720 * If `cvtl_ignore_std_width' is set, we leave `reference = width'.
723 * stem_is_serif (unused)
724 * base_is_round (unused)
730 * sal_vwidth_data_offset
733 * cvtl_ignore_std_width
735 * uses: bci_get_best_width
739 static const unsigned char FPGM(bci_strong_stem_width_a
) [] =
743 bci_strong_stem_width
,
751 ABS
, /* s: width dist */
756 WS
, /* sal_best = 98 */
762 WS
, /* sal_ref = width */
765 cvtl_ignore_std_width
,
773 sal_vwidth_data_offset
,
776 MUL
, /* divide by 64; first index of vertical widths */
778 /* s: width dist vw_idx */
781 sal_vwidth_data_offset
,
787 /* %c, number of used styles */
789 static const unsigned char FPGM(bci_strong_stem_width_b
) [] =
793 RCVT
, /* number of vertical widths */
794 MUL
, /* divide by 64 */
796 /* s: width dist vw_idx loop_count */
801 POP
, /* s: width dist */
806 RS
, /* s: width dist dist reference */
813 CALL
, /* s: width dist reference dist dist ROUND(reference) */
817 CINDEX
, /* s: width dist reference dist dist ROUND(reference) 48 reference */
820 MINDEX
, /* s: width dist reference dist ROUND(reference) 48 reference dist */
822 LTEQ
, /* reference <= dist */
823 IF
, /* s: width dist reference dist ROUND(reference) 48 */
825 LT
, /* dist < ROUND(reference) + 48 */
829 GT
, /* dist > ROUND(reference) - 48 */
833 SWAP
, /* s: width reference=new_dist dist */
836 EIF
, /* !cvtl_ignore_std_width */
838 DUP
, /* s: width dist dist */
841 GTEQ
, /* dist >= 64 */
845 CALL
, /* dist = ROUND(dist) */
853 SWAP
, /* s: dist width */
858 NEG
, /* dist = -dist */
869 * An auxiliary function for `bci_loop'.
871 * sal: sal_i (gets incremented by 2 after execution)
874 * uses: func[sal_func]
877 static const unsigned char FPGM(bci_loop_do
) [] =
894 ADD
, /* sal_i = sal_i + 2 */
905 * Take a range `start'..`end' and a function number and apply the
906 * associated function to the range elements `start', `start+2',
913 * sal: sal_i (counter initialized with `start')
914 * sal_func (`func_num')
919 static const unsigned char FPGM(bci_loop
) [] =
929 WS
, /* sal_func = func_num */
936 WS
, /* sal_i = start */
942 ADD
, /* number of loops ((end - start) / 2 + 1) */
956 * Rescale CVT value by `sal_scale' (in 16.16 format).
958 * The scaling factor `sal_scale' isn't stored as `b/c' but as `(b-c)/c';
959 * consequently, the calculation `a * b/c' is done as `a + delta' with
960 * `delta = a * (b-c)/c'. This avoids overflow.
969 static const unsigned char FPGM(bci_cvt_rescale
) [] =
992 * bci_cvt_rescale_range
994 * Rescale a range of CVT values with `bci_cvt_rescale', using a custom
997 * This function gets used in the `prep' table.
1002 * sal: sal_i (CVT index of the style's scaling value;
1003 * gets incremented by 1 after execution)
1006 * uses: bci_cvt_rescale
1009 static const unsigned char FPGM(bci_cvt_rescale_range
) [] =
1013 bci_cvt_rescale_range
,
1016 /* store scaling value in `sal_scale' */
1023 WS
, /* s: cvt_start_idx num_cvt bci_cvt_rescale */
1026 /* clean up stack */
1034 ADD
, /* sal_i = sal_i + 1 */
1043 * bci_vwidth_data_store
1045 * Store a vertical width array value.
1047 * This function gets used in the `prep' table.
1051 * sal: sal_i (CVT index of the style's vwidth data;
1052 * gets incremented by 1 after execution)
1055 static const unsigned char FPGM(bci_vwidth_data_store
) [] =
1059 bci_vwidth_data_store
,
1073 ADD
, /* sal_i = sal_i + 1 */
1082 * bci_smooth_blue_round
1084 * Round a blue ref value and adjust its corresponding shoot value.
1086 * This is the equivalent to the following code (function
1087 * `ta_latin_metrics_scale_dim'):
1095 * else if delta < 48:
1105 * sal: sal_i (number of blue zones)
1112 static const unsigned char FPGM(bci_smooth_blue_round
) [] =
1116 bci_smooth_blue_round
,
1121 RCVT
, /* s: ref_idx ref_idx ref */
1127 SWAP
, /* s: ref_idx ref_idx round(ref) ref */
1135 ADD
, /* s: ref_idx ref_idx round(ref) ref shoot_idx */
1137 RCVT
, /* s: ref_idx ref_idx round(ref) ref shoot_idx shoot */
1139 ROLL
, /* s: ref_idx ref_idx round(ref) shoot_idx shoot ref */
1141 SUB
, /* s: ref_idx ref_idx round(ref) shoot_idx dist */
1143 ABS
, /* s: ref_idx ref_idx round(ref) shoot_idx dist delta */
1148 LT
, /* delta < 32 */
1157 LT
, /* delta < 48 */
1160 32, /* delta = 32 */
1164 64, /* delta = 64 */
1168 SWAP
, /* s: ref_idx ref_idx round(ref) shoot_idx delta dist */
1173 NEG
, /* delta = -delta */
1180 SUB
, /* s: ref_idx ref_idx round(ref) shoot_idx (round(ref) - delta) */
1187 ADD
, /* s: (ref_idx + 1) */
1195 * bci_strong_blue_round
1197 * Round a blue ref value and adjust its corresponding shoot value.
1199 * This is the equivalent to the following code:
1213 * It doesn't have corresponding code in talatin.c; however, some tests
1214 * have shown that the `smooth' code works just fine for this case also.
1218 * sal: sal_i (number of blue zones)
1225 static const unsigned char FPGM(bci_strong_blue_round
) [] =
1229 bci_strong_blue_round
,
1234 RCVT
, /* s: ref_idx ref_idx ref */
1240 SWAP
, /* s: ref_idx ref_idx round(ref) ref */
1248 ADD
, /* s: ref_idx ref_idx round(ref) ref shoot_idx */
1250 RCVT
, /* s: ref_idx ref_idx round(ref) ref shoot_idx shoot */
1252 ROLL
, /* s: ref_idx ref_idx round(ref) shoot_idx shoot ref */
1254 SUB
, /* s: ref_idx ref_idx round(ref) shoot_idx dist */
1256 ABS
, /* s: ref_idx ref_idx round(ref) shoot_idx dist delta */
1260 LT
, /* delta < 36 */
1263 0, /* delta = 0 (set overshoot to zero if < 0.56 pixel units) */
1267 64, /* delta = 64 (one pixel unit) */
1270 SWAP
, /* s: ref_idx ref_idx round(ref) shoot_idx delta dist */
1275 NEG
, /* delta = -delta */
1282 SUB
, /* s: ref_idx ref_idx round(ref) shoot_idx (round(ref) - delta) */
1289 ADD
, /* s: (ref_idx + 1) */
1297 * bci_blue_round_range
1299 * Round a range of blue zones (both reference and shoot values).
1301 * This function gets used in the `prep' table.
1303 * in: num_blue_zones
1306 * sal: sal_i (holds a copy of `num_blue_zones' for blue rounding function)
1308 * uses: bci_smooth_blue_round
1309 * bci_strong_blue_round
1312 static const unsigned char FPGM(bci_blue_round_range
) [] =
1316 bci_blue_round_range
,
1325 /* select blue rounding function based on flag in CVT */
1327 bci_strong_blue_round
,
1328 bci_smooth_blue_round
,
1329 cvtl_use_strong_functions
,
1340 /* clean up stack */
1349 * bci_decrement_component_counter
1351 * An auxiliary function for composite glyphs.
1353 * CVT: cvtl_is_subglyph
1356 static const unsigned char FPGM(bci_decrement_component_counter
) [] =
1360 bci_decrement_component_counter
,
1363 /* decrement `cvtl_is_subglyph' counter */
1379 * bci_get_point_extrema
1381 * An auxiliary function for `bci_create_segment'.
1387 * sal: sal_point_min
1391 static const unsigned char FPGM(bci_get_point_extrema
) [] =
1395 bci_get_point_extrema
,
1404 /* check whether `point' is a new minimum */
1407 RS
, /* s: point point point point_min */
1409 /* if distance is negative, we have a new minimum */
1413 IF
, /* s: point point */
1421 /* check whether `point' is a new maximum */
1424 RS
, /* s: point point point_max */
1426 /* if distance is positive, we have a new maximum */
1446 * Pop a byte with two delta arguments in its nibbles and push the
1447 * expanded arguments separately as two bytes.
1449 * in: 16 * (end - start) + (start - base)
1454 * sal: sal_base (set to `end' at return)
1458 static const unsigned char FPGM(bci_nibbles
) [] =
1465 PUSHB_1
, /* cf. DIV_POS_BY_2 macro */
1471 MUL
, /* s: in hnibble */
1476 MUL
, /* s: in hnibble (hnibble * 16) */
1479 SUB
, /* s: hnibble lnibble */
1484 ADD
, /* s: hnibble start */
1487 ADD
, /* s: start end */
1493 WS
, /* sal_base = end */
1503 * bci_number_set_is_element
1505 * Pop values from stack until it is empty. If one of them is equal to
1506 * the current PPEM value, set `cvtl_is_element' to 100 (and to 0
1513 * CVT: cvtl_is_element
1516 static const unsigned char FPGM(bci_number_set_is_element
) [] =
1520 bci_number_set_is_element
,
1538 JROT
, /* goto start_loop if stack depth != 0 */
1546 * bci_number_set_is_element2
1548 * Pop value ranges from stack until it is empty. If one of them contains
1549 * the current PPEM value, set `cvtl_is_element' to 100 (and to 0
1552 * in: ppem_range_1_start
1554 * ppem_range_2_start
1558 * CVT: cvtl_is_element
1561 static const unsigned char FPGM(bci_number_set_is_element2
) [] =
1565 bci_number_set_is_element2
,
1589 JROT
, /* goto start_loop if stack depth != 0 */
1597 * bci_create_segment
1599 * Store start and end point of a segment in the storage area,
1600 * then construct a point in the twilight zone to represent it.
1602 * This function is used by `bci_create_segments'.
1606 * [last (if wrap-around segment)]
1607 * [first (if wrap-around segment)]
1609 * sal: sal_i (start of current segment)
1610 * sal_j (current twilight point)
1614 * sal_num_packed_segments
1619 * uses: bci_get_point_extrema
1622 * If `sal_num_packed_segments' is > 0, the start/end pair is stored as
1623 * delta values in nibbles (without a wrap-around segment).
1626 static const unsigned char FPGM(bci_create_segment
) [] =
1635 sal_num_packed_segments
,
1640 sal_num_packed_segments
,
1641 sal_num_packed_segments
,
1646 WS
, /* sal_num_packed_segments = sal_num_packed_segments - 1 */
1659 WS
, /* sal[sal_i] = start */
1661 /* initialize inner loop(s) */
1666 WS
, /* sal_point_min = start */
1671 WS
, /* sal_point_max = start */
1675 SZPS
, /* set zp0, zp1, and zp2 to normal zone 1 */
1681 CINDEX
, /* s: start end end start */
1682 LT
, /* start > end */
1684 /* we have a wrap-around segment with two more arguments */
1685 /* to give the last and first point of the contour, respectively; */
1686 /* our job is to store a segment `start'-`last', */
1687 /* and to get extrema for the two segments */
1688 /* `start'-`last' and `first'-`end' */
1690 /* s: first last start end */
1699 WS
, /* sal[sal_i + 1] = last */
1702 ROLL
, /* s: first end last start */
1705 SWAP
, /* s: first end start last start */
1706 SUB
, /* s: first end start loop_count */
1709 bci_get_point_extrema
,
1711 /* clean up stack */
1714 SWAP
, /* s: end first */
1719 ROLL
, /* s: (first - 1) (first - 1) end */
1721 SUB
, /* s: (first - 1) loop_count */
1724 bci_get_point_extrema
,
1726 /* clean up stack */
1729 ELSE
, /* s: start end */
1738 WS
, /* sal[sal_i + 1] = end */
1743 SUB
, /* s: start loop_count */
1746 bci_get_point_extrema
,
1748 /* clean up stack */
1752 /* the twilight point representing a segment */
1753 /* is in the middle between the minimum and maximum */
1763 DIV_BY_2
, /* s: middle_pos */
1765 DO_SCALE
, /* middle_pos = middle_pos * scale */
1767 /* write it to temporary CVT location */
1771 SZP0
, /* set zp0 to twilight zone 0 */
1775 /* create twilight point with index `sal_j' */
1788 ADD
, /* twilight_point = twilight_point + 1 */
1797 * bci_create_segments
1799 * This is the top-level entry function.
1801 * It pops point ranges from the stack to define segments, computes
1802 * twilight points to represent segments, and finally calls
1803 * `bci_hint_glyph' to handle the rest.
1805 * The second argument (`data_offset') addresses three CVT arrays in
1809 * the current style's scaling value (stored in `sal_scale')
1811 * data_offset + num_used_styles:
1812 * offset to the current style's vwidth index array (this value gets
1813 * stored in `sal_vwidth_data_offset')
1815 * data_offset + 2*num_used_styles:
1816 * offset to the current style's vwidth size
1818 * This addressing scheme ensures that (a) we only need a single argument,
1819 * and (b) this argument supports up to (256-cvtl_max_runtime) styles,
1820 * which should be sufficient for a long time.
1822 * in: num_packed_segments
1827 * [contour_last 0 (if wrap-around segment)]
1828 * [contour_first 0 (if wrap-around segment)]
1831 * [contour_last 0 (if wrap-around segment)]
1832 * [contour_first 0 (if wrap-around segment)]
1834 * segment_start_(N-1)
1836 * [contour_last (N-1) (if wrap-around segment)]
1837 * [contour_first (N-1) (if wrap-around segment)]
1838 * ... stuff for bci_hint_glyph ...
1840 * sal: sal_i (start of current segment)
1841 * sal_j (current twilight point)
1842 * sal_num_packed_segments
1843 * sal_base (the base for delta values in nibbles)
1844 * sal_vwidth_data_offset
1847 * CVT: cvtl_is_subglyph
1849 * uses: bci_create_segment
1853 * If `num_packed_segments' is set to p, the first p start/end pairs are
1854 * stored as delta values in nibbles, with the `start' delta in the lower
1855 * nibble (and there are no wrap-around segments). For example, if the
1856 * first three pairs are 1/3, 5/8, and 12/13, the topmost three bytes on the
1857 * stack are 0x21, 0x32, and 0x14.
1861 static const unsigned char FPGM(bci_create_segments_a
) [] =
1865 bci_create_segments
,
1868 /* all our measurements are taken along the y axis */
1871 /* only do something if we are not a subglyph */
1879 sal_num_packed_segments
,
1886 sal_scale
, /* sal_scale = CVT(data_offset) */
1891 sal_vwidth_data_offset
,
1897 /* %c, number of used styles */
1899 static const unsigned char FPGM(bci_create_segments_b
) [] =
1903 WS
, /* sal_vwidth_data_offset = data_offset + num_used_styles */
1909 SUB
, /* delta = (2*num_segments - 1) */
1919 WS
, /* sal_base = 0 */
1920 WS
, /* sal_j = 0 (point offset) */
1923 ADD
, /* s: ... sal_segment_offset (sal_segment_offset + delta) */
1936 /* used if we have delta exceptions */
1938 static const unsigned char FPGM(bci_create_segments_c
) [] =
1947 static const unsigned char FPGM(bci_create_segments_d
) [] =
1960 * bci_create_segments_X
1962 * Top-level routines for calling `bci_create_segments'.
1965 static const unsigned char FPGM(bci_create_segments_0
) [] =
1969 bci_create_segments_0
,
1974 bci_create_segments
,
1981 static const unsigned char FPGM(bci_create_segments_1
) [] =
1985 bci_create_segments_1
,
1990 bci_create_segments
,
1997 static const unsigned char FPGM(bci_create_segments_2
) [] =
2001 bci_create_segments_2
,
2006 bci_create_segments
,
2013 static const unsigned char FPGM(bci_create_segments_3
) [] =
2017 bci_create_segments_3
,
2022 bci_create_segments
,
2029 static const unsigned char FPGM(bci_create_segments_4
) [] =
2033 bci_create_segments_4
,
2038 bci_create_segments
,
2045 static const unsigned char FPGM(bci_create_segments_5
) [] =
2049 bci_create_segments_5
,
2054 bci_create_segments
,
2061 static const unsigned char FPGM(bci_create_segments_6
) [] =
2065 bci_create_segments_6
,
2070 bci_create_segments
,
2077 static const unsigned char FPGM(bci_create_segments_7
) [] =
2081 bci_create_segments_7
,
2086 bci_create_segments
,
2093 static const unsigned char FPGM(bci_create_segments_8
) [] =
2097 bci_create_segments_8
,
2102 bci_create_segments
,
2109 static const unsigned char FPGM(bci_create_segments_9
) [] =
2113 bci_create_segments_9
,
2118 bci_create_segments
,
2129 * Wrapper functions around DELTAP[123] that touch the affected points
2130 * before applying the delta. This is necessary for ClearType.
2132 * While DELTAP[123] implicitly do a loop, we have to process the
2133 * arguments sequentially by calling `bci_deltaX' with LOOPCALL.
2139 static const unsigned char FPGM(bci_deltap1
) [] =
2147 DUP
, /* s: point arg arg */
2148 PUSHB_1
, /* cf. DIV_POS_BY_2 macro */
2154 MUL
, /* s: point arg hnibble(arg) */
2156 CONTROL_DELTA_PPEM_MIN
,
2157 ADD
, /* s: point arg ppem(arg) */
2163 MDAP_noround
, /* touch `point' */
2167 DELTAP1
, /* process one `(point,arg)' pair */
2177 static const unsigned char FPGM(bci_deltap2
) [] =
2185 DUP
, /* s: point arg arg */
2186 PUSHB_1
, /* cf. DIV_POS_BY_2 macro */
2192 MUL
, /* s: point arg hnibble(arg) */
2194 CONTROL_DELTA_PPEM_MIN
+ 16,
2195 ADD
, /* s: point arg ppem(arg) */
2201 MDAP_noround
, /* touch `point' */
2205 DELTAP2
, /* process one `(point,arg)' pair */
2215 static const unsigned char FPGM(bci_deltap3
) [] =
2223 DUP
, /* s: point arg arg */
2224 PUSHB_1
, /* cf. DIV_POS_BY_2 macro */
2230 MUL
, /* s: point arg hnibble(arg) */
2232 CONTROL_DELTA_PPEM_MIN
+ 32,
2233 ADD
, /* s: point arg ppem(arg) */
2239 MDAP_noround
, /* touch `point' */
2243 DELTAP3
, /* process one `(point,arg)' pair */
2255 * bci_create_segments_composite
2257 * The same as `bci_create_segments'.
2258 * It also decrements the composite component counter.
2260 * sal: sal_num_packed_segments
2261 * sal_segment_offset
2262 * sal_vwidth_data_offset
2264 * CVT: cvtl_is_subglyph
2266 * uses: bci_decrement_component_counter
2267 * bci_create_segment
2272 static const unsigned char FPGM(bci_create_segments_composite_a
) [] =
2276 bci_create_segments_composite
,
2279 /* all our measurements are taken along the y axis */
2283 bci_decrement_component_counter
,
2286 /* only do something if we are not a subglyph */
2294 sal_num_packed_segments
,
2301 sal_scale
, /* sal_scale = CVT(data_offset) */
2306 sal_vwidth_data_offset
,
2312 /* %c, number of used styles */
2314 static const unsigned char FPGM(bci_create_segments_composite_b
) [] =
2318 WS
, /* sal_vwidth_data_offset = data_offset + num_used_styles */
2324 SUB
, /* delta = (2*num_segments - 1) */
2334 WS
, /* sal_base = 0 */
2335 WS
, /* sal_j = 0 (point offset) */
2338 ADD
, /* s: ... sal_segment_offset (sal_segment_offset + delta) */
2351 /* used if we have delta exceptions */
2353 static const unsigned char FPGM(bci_create_segments_composite_c
) [] =
2362 static const unsigned char FPGM(bci_create_segments_composite_d
) [] =
2375 * bci_create_segments_composite_X
2377 * Top-level routines for calling `bci_create_segments_composite'.
2380 static const unsigned char FPGM(bci_create_segments_composite_0
) [] =
2384 bci_create_segments_composite_0
,
2389 bci_create_segments_composite
,
2396 static const unsigned char FPGM(bci_create_segments_composite_1
) [] =
2400 bci_create_segments_composite_1
,
2405 bci_create_segments_composite
,
2412 static const unsigned char FPGM(bci_create_segments_composite_2
) [] =
2416 bci_create_segments_composite_2
,
2421 bci_create_segments_composite
,
2428 static const unsigned char FPGM(bci_create_segments_composite_3
) [] =
2432 bci_create_segments_composite_3
,
2437 bci_create_segments_composite
,
2444 static const unsigned char FPGM(bci_create_segments_composite_4
) [] =
2448 bci_create_segments_composite_4
,
2453 bci_create_segments_composite
,
2460 static const unsigned char FPGM(bci_create_segments_composite_5
) [] =
2464 bci_create_segments_composite_5
,
2469 bci_create_segments_composite
,
2476 static const unsigned char FPGM(bci_create_segments_composite_6
) [] =
2480 bci_create_segments_composite_6
,
2485 bci_create_segments_composite
,
2492 static const unsigned char FPGM(bci_create_segments_composite_7
) [] =
2496 bci_create_segments_composite_7
,
2501 bci_create_segments_composite
,
2508 static const unsigned char FPGM(bci_create_segments_composite_8
) [] =
2512 bci_create_segments_composite_8
,
2517 bci_create_segments_composite
,
2524 static const unsigned char FPGM(bci_create_segments_composite_9
) [] =
2528 bci_create_segments_composite_9
,
2533 bci_create_segments_composite
,
2544 * An auxiliary function for `bci_align_segment'.
2551 static const unsigned char FPGM(bci_align_point
) [] =
2559 ALIGNRP
, /* align point with rp0 */
2573 * Align all points in a segment to the twilight point in rp0.
2574 * zp0 and zp1 must be set to 0 (twilight) and 1 (normal), respectively.
2578 * sal: sal_segment_offset
2580 * uses: bci_align_point
2583 static const unsigned char FPGM(bci_align_segment
) [] =
2590 /* we need the values of `sal_segment_offset + 2*segment_index' */
2591 /* and `sal_segment_offset + 2*segment_index + 1' */
2603 RS
, /* s: first last */
2607 CINDEX
, /* s: first last first */
2611 ADD
, /* s: first loop_count */
2616 /* clean up stack */
2625 * bci_align_segments
2627 * Align segments to the twilight point in rp0.
2628 * zp0 and zp1 must be set to 0 (twilight) and 1 (normal), respectively.
2637 * uses: bci_align_segment
2640 static const unsigned char FPGM(bci_align_segments
) [] =
2663 * Scale a contour using two points giving the maximum and minimum
2666 * It expects that no point on the contour is touched.
2674 static const unsigned char FPGM(bci_scale_contour
) [] =
2685 DO_SCALE
, /* min_pos_new = min_pos * scale */
2690 /* don't scale a single-point contour twice */
2699 DO_SCALE
, /* max_pos_new = max_pos * scale */
2716 * Scale a glyph using a list of points (two points per contour, giving
2717 * the maximum and mininum coordinates).
2719 * It expects that no point in the glyph is touched.
2721 * Note that the point numbers are sorted in ascending order;
2722 * `min_point_X' and `max_point_X' thus refer to the two extrema of a
2723 * contour without specifying which one is the minimum and maximum.
2725 * in: num_contours (N)
2734 * CVT: cvtl_is_subglyph
2739 * uses: bci_scale_contour
2742 static const unsigned char FPGM(bci_scale_glyph_a
) [] =
2749 /* all our measurements are taken along the y axis */
2752 /* only do something if we are not a subglyph */
2759 /* use fallback scaling value */
2765 /* %c, fallback scaling index */
2767 static const unsigned char FPGM(bci_scale_glyph_b
) [] =
2775 SZPS
, /* set zp0, zp1, and zp2 to normal zone 1 */
2784 SZP2
, /* set zp2 to normal zone 1 */
2800 * bci_scale_composite_glyph
2802 * The same as `bci_scale_glyph'.
2803 * It also decrements the composite component counter.
2805 * CVT: cvtl_is_subglyph
2810 * uses: bci_decrement_component_counter
2814 static const unsigned char FPGM(bci_scale_composite_glyph_a
) [] =
2818 bci_scale_composite_glyph
,
2821 /* all our measurements are taken along the y axis */
2825 bci_decrement_component_counter
,
2828 /* only do something if we are not a subglyph */
2835 /* use fallback scaling value */
2841 /* %c, fallback scaling index */
2843 static const unsigned char FPGM(bci_scale_composite_glyph_b
) [] =
2851 SZPS
, /* set zp0, zp1, and zp2 to normal zone 1 */
2860 SZP2
, /* set zp2 to normal zone 1 */
2878 * Shift a contour by a given amount.
2880 * It expects that rp1 (pointed to by zp0) is set up properly; zp2 must
2881 * point to the normal zone 1.
2888 static const unsigned char FPGM(bci_shift_contour
) [] =
2896 SHC_rp1
, /* shift `contour' by (rp1_pos - rp1_orig_pos) */
2908 * bci_shift_subglyph
2910 * Shift a subglyph. To be more specific, it corrects the already applied
2911 * subglyph offset (if any) from the `glyf' table which needs to be scaled
2914 * If this function is called, a point `x' in the subglyph has been scaled
2915 * already (during the hinting of the subglyph itself), and `offset' has
2916 * been applied also:
2918 * x -> x * scale + offset (1)
2920 * However, the offset should be applied first, then the scaling:
2922 * x -> (x + offset) * scale (2)
2924 * Our job is now to transform (1) to (2); a simple calculation shows that
2925 * we have to shift all points of the subglyph by
2927 * offset * scale - offset = offset * (scale - 1)
2929 * Note that `sal_scale' is equal to the above `scale - 1'.
2931 * in: offset (in FUnits)
2935 * CVT: cvtl_funits_to_pixels
2943 static const unsigned char FPGM(bci_shift_subglyph_a
) [] =
2950 /* all our measurements are taken along the y axis */
2953 /* use fallback scaling value */
2959 /* %c, fallback scaling index */
2961 static const unsigned char FPGM(bci_shift_subglyph_b
) [] =
2968 cvtl_funits_to_pixels
,
2969 RCVT
, /* scaling factor FUnits -> pixels */
2973 /* the autohinter always rounds offsets */
2976 CALL
, /* offset = round(offset) */
2982 DIV_BY_1024
, /* delta = offset * (scale - 1) */
2984 /* and round again */
2987 CALL
, /* offset = round(offset) */
2991 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
2993 /* we create twilight point 0 as a reference point, */
2994 /* setting the original position to zero (using `cvtl_temp') */
3002 MIAP_noround
, /* rp0 and rp1 now point to twilight point 0 */
3004 SWAP
, /* s: first_contour num_contours 0 delta */
3005 SHPIX
, /* rp1_pos - rp1_orig_pos = delta */
3010 SZP2
, /* set zp2 to normal zone 1 */
3012 /* clean up stack */
3017 /* used if we have delta exceptions */
3019 static const unsigned char FPGM(bci_shift_subglyph_c
) [] =
3028 static const unsigned char FPGM(bci_shift_subglyph_d
) [] =
3037 * bci_ip_outer_align_point
3039 * Auxiliary function for `bci_action_ip_before' and
3040 * `bci_action_ip_after'.
3042 * It expects rp0 to contain the edge for alignment, zp0 set to twilight
3043 * zone, and both zp1 and zp2 set to normal zone.
3047 * sal: sal_i (edge_orig_pos)
3051 static const unsigned char FPGM(bci_ip_outer_align_point
) [] =
3055 bci_ip_outer_align_point
,
3059 ALIGNRP
, /* align `point' with `edge' */
3062 DO_SCALE
, /* point_orig_pos = point_orig_pos * scale */
3067 SUB
, /* s: point (point_orig_pos - edge_orig_pos) */
3076 * bci_ip_on_align_points
3078 * Auxiliary function for `bci_action_ip_on'.
3080 * in: edge (in twilight zone)
3088 static const unsigned char FPGM(bci_ip_on_align_points
) [] =
3092 bci_ip_on_align_points
,
3095 MDAP_noround
, /* set rp0 and rp1 to `edge' */
3106 * bci_ip_between_align_point
3108 * Auxiliary function for `bci_ip_between_align_points'.
3110 * It expects rp0 to contain the edge for alignment, zp0 set to twilight
3111 * zone, and both zp1 and zp2 set to normal zone.
3115 * sal: sal_i (edge_orig_pos)
3116 * sal_j (stretch_factor)
3120 static const unsigned char FPGM(bci_ip_between_align_point
) [] =
3124 bci_ip_between_align_point
,
3128 ALIGNRP
, /* align `point' with `edge' */
3131 DO_SCALE
, /* point_orig_pos = point_orig_pos * scale */
3136 SUB
, /* s: point (point_orig_pos - edge_orig_pos) */
3140 MUL
, /* s: point delta */
3149 * bci_ip_between_align_points
3151 * Auxiliary function for `bci_action_ip_between'.
3153 * in: after_edge (in twilight zone)
3154 * before_edge (in twilight zone)
3161 * sal: sal_i (before_orig_pos)
3162 * sal_j (stretch_factor)
3164 * uses: bci_ip_between_align_point
3167 static const unsigned char FPGM(bci_ip_between_align_points
) [] =
3171 bci_ip_between_align_points
,
3177 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
3179 DUP
, /* s: ... before after before before */
3180 MDAP_noround
, /* set rp0 and rp1 to `before' */
3182 GC_orig
, /* s: ... before after before before_orig_pos */
3186 WS
, /* sal_i = before_orig_pos */
3189 CINDEX
, /* s: ... before after before after */
3190 MD_cur
, /* a = after_pos - before_pos */
3193 MD_orig_ZP2_0
, /* b = after_orig_pos - before_orig_pos */
3199 POP
, /* avoid division by zero */
3205 WS
, /* sal_j = stretch_factor */
3208 bci_ip_between_align_point
,
3211 SZP2
, /* set zp2 to normal zone 1 */
3212 SZP1
, /* set zp1 to normal zone 1 */
3221 * bci_action_ip_before
3223 * Handle `ip_before' data to align points located before the first edge.
3225 * in: first_edge (in twilight zone)
3232 * sal: sal_i (first_edge_orig_pos)
3234 * uses: bci_ip_outer_align_point
3237 static const unsigned char FPGM(bci_action_ip_before
) [] =
3241 bci_action_ip_before
,
3246 SZP2
, /* set zp2 to twilight zone 0 */
3253 WS
, /* sal_i = first_edge_orig_pos */
3259 SZP2
, /* set zp2 to normal zone 1 */
3260 SZP1
, /* set zp1 to normal zone 1 */
3261 SZP0
, /* set zp0 to twilight zone 0 */
3263 MDAP_noround
, /* set rp0 and rp1 to `first_edge' */
3266 bci_ip_outer_align_point
,
3275 * bci_action_ip_after
3277 * Handle `ip_after' data to align points located after the last edge.
3279 * in: last_edge (in twilight zone)
3286 * sal: sal_i (last_edge_orig_pos)
3288 * uses: bci_ip_outer_align_point
3291 static const unsigned char FPGM(bci_action_ip_after
) [] =
3295 bci_action_ip_after
,
3300 SZP2
, /* set zp2 to twilight zone 0 */
3307 WS
, /* sal_i = last_edge_orig_pos */
3313 SZP2
, /* set zp2 to normal zone 1 */
3314 SZP1
, /* set zp1 to normal zone 1 */
3315 SZP0
, /* set zp0 to twilight zone 0 */
3317 MDAP_noround
, /* set rp0 and rp1 to `last_edge' */
3320 bci_ip_outer_align_point
,
3331 * Handle `ip_on' data to align points located on an edge coordinate (but
3332 * not part of an edge).
3334 * in: loop_counter (M)
3335 * edge_1 (in twilight zone)
3336 * loop_counter (N_1)
3341 * edge_2 (in twilight zone)
3342 * loop_counter (N_2)
3348 * edge_M (in twilight zone)
3349 * loop_counter (N_M)
3355 * uses: bci_ip_on_align_points
3358 static const unsigned char FPGM(bci_action_ip_on
) [] =
3368 SZP1
, /* set zp1 to normal zone 1 */
3369 SZP0
, /* set zp0 to twilight zone 0 */
3372 bci_ip_on_align_points
,
3381 * bci_action_ip_between
3383 * Handle `ip_between' data to align points located between two edges.
3385 * in: loop_counter (M)
3386 * before_edge_1 (in twilight zone)
3387 * after_edge_1 (in twilight zone)
3388 * loop_counter (N_1)
3393 * before_edge_2 (in twilight zone)
3394 * after_edge_2 (in twilight zone)
3395 * loop_counter (N_2)
3401 * before_edge_M (in twilight zone)
3402 * after_edge_M (in twilight zone)
3403 * loop_counter (N_M)
3409 * uses: bci_ip_between_align_points
3412 static const unsigned char FPGM(bci_action_ip_between
) [] =
3416 bci_action_ip_between
,
3420 bci_ip_between_align_points
,
3431 * Common code for bci_action_adjust routines.
3433 * in: top_to_bottom_hinting
3439 * out: edge (adjusted)
3441 * sal: sal_top_to_bottom_hinting
3444 * uses: func[sal_stem_width_function]
3447 static const unsigned char FPGM(bci_adjust_common
) [] =
3456 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
3458 sal_top_to_bottom_hinting
,
3464 CINDEX
, /* s: [...] edge2 edge is_round is_serif edge2 */
3467 CINDEX
, /* s: [...] edge2 edge is_round is_serif edge2 edge */
3468 MD_orig_ZP2_0
, /* s: [...] edge2 edge is_round is_serif org_len */
3471 sal_base_delta
, /* no base_delta needed here */
3476 sal_stem_width_function
,
3479 NEG
, /* s: [...] edge2 edge -cur_len */
3481 ROLL
, /* s: [...] edge -cur_len edge2 */
3482 MDAP_noround
, /* set rp0 and rp1 to `edge2' */
3485 DUP
, /* s: [...] -cur_len edge edge edge */
3486 ALIGNRP
, /* align `edge' with `edge2' */
3488 SHPIX
, /* shift `edge' by -cur_len */
3498 * Handle the ADJUST + BOUND actions to align an edge of a stem if the
3499 * other edge of the stem has already been moved, then moving it again if
3500 * necessary to stay bound.
3502 * in: top_to_bottom_hinting
3505 * edge_point (in twilight zone)
3506 * edge2_point (in twilight zone)
3507 * edge[-1] (in twilight zone)
3508 * ... stuff for bci_align_segments (edge) ...
3510 * sal: sal_top_to_bottom_hinting
3512 * uses: bci_adjust_common
3513 * bci_align_segments
3516 static const unsigned char FPGM(bci_adjust_bound
) [] =
3527 SWAP
, /* s: edge edge[-1] */
3529 MDAP_noround
, /* set rp0 and rp1 to `edge[-1]' */
3534 GC_cur
, /* s: edge edge[-1]_pos edge_pos */
3536 sal_top_to_bottom_hinting
,
3539 LT
, /* edge_pos > edge[-1]_pos */
3541 GT
, /* edge_pos < edge[-1]_pos */
3545 ALIGNRP
, /* align `edge' to `edge[-1]' */
3548 MDAP_noround
, /* set rp0 and rp1 to `edge' */
3553 SZP1
, /* set zp1 to normal zone 1 */
3562 * bci_action_adjust_bound
3563 * bci_action_adjust_bound_serif
3564 * bci_action_adjust_bound_round
3565 * bci_action_adjust_bound_round_serif
3566 * bci_action_adjust_down_bound
3567 * bci_action_adjust_down_bound_serif
3568 * bci_action_adjust_down_bound_round
3569 * bci_action_adjust_down_bound_round_serif
3571 * Higher-level routines for calling `bci_adjust_bound'.
3574 static const unsigned char FPGM(bci_action_adjust_bound
) [] =
3578 bci_action_adjust_bound
,
3592 static const unsigned char FPGM(bci_action_adjust_bound_serif
) [] =
3596 bci_action_adjust_bound_serif
,
3610 static const unsigned char FPGM(bci_action_adjust_bound_round
) [] =
3614 bci_action_adjust_bound_round
,
3628 static const unsigned char FPGM(bci_action_adjust_bound_round_serif
) [] =
3632 bci_action_adjust_bound_round_serif
,
3646 static const unsigned char FPGM(bci_action_adjust_down_bound
) [] =
3650 bci_action_adjust_down_bound
,
3664 static const unsigned char FPGM(bci_action_adjust_down_bound_serif
) [] =
3668 bci_action_adjust_down_bound_serif
,
3682 static const unsigned char FPGM(bci_action_adjust_down_bound_round
) [] =
3686 bci_action_adjust_down_bound_round
,
3700 static const unsigned char FPGM(bci_action_adjust_down_bound_round_serif
) [] =
3704 bci_action_adjust_down_bound_round_serif
,
3722 * Handle the ADJUST action to align an edge of a stem if the other edge
3723 * of the stem has already been moved.
3725 * in: edge2_is_serif
3727 * edge_point (in twilight zone)
3728 * edge2_point (in twilight zone)
3729 * ... stuff for bci_align_segments (edge) ...
3731 * uses: bci_adjust_common
3732 * bci_align_segments
3735 static const unsigned char FPGM(bci_adjust
) [] =
3747 MDAP_noround
, /* set rp0 and rp1 to `edge' */
3752 SZP1
, /* set zp1 to normal zone 1 */
3762 * bci_action_adjust_serif
3763 * bci_action_adjust_round
3764 * bci_action_adjust_round_serif
3766 * Higher-level routines for calling `bci_adjust'.
3769 static const unsigned char FPGM(bci_action_adjust
) [] =
3786 static const unsigned char FPGM(bci_action_adjust_serif
) [] =
3790 bci_action_adjust_serif
,
3803 static const unsigned char FPGM(bci_action_adjust_round
) [] =
3807 bci_action_adjust_round
,
3820 static const unsigned char FPGM(bci_action_adjust_round_serif
) [] =
3824 bci_action_adjust_round_serif
,
3841 * Common code for bci_action_stem routines.
3843 * in: top_to_bottom_hinting
3857 * sal_top_to_bottom_hinting
3860 * uses: func[sal_stem_width_function]
3865 #define sal_u_off sal_temp1
3867 #define sal_d_off sal_temp2
3869 #define sal_org_len sal_temp3
3871 #define sal_edge2 sal_temp3
3873 static const unsigned char FPGM(bci_stem_common
) [] =
3882 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
3885 sal_top_to_bottom_hinting
,
3895 DUP
, /* s: [...] edge2 edge is_round is_serif edge2 edge edge */
3896 MDAP_noround
, /* set rp0 and rp1 to `edge_point' (for ALIGNRP below) */
3898 MD_orig_ZP2_0
, /* s: [...] edge2 edge is_round is_serif org_len */
3906 sal_base_delta
, /* no base_delta needed here */
3911 sal_stem_width_function
,
3913 CALL
, /* s: [...] edge2 edge cur_len */
3918 LT
, /* cur_len < 96 */
3923 LTEQ
, /* cur_len <= 64 */
3941 SWAP
, /* s: [...] edge2 cur_len edge */
3946 DUP
, /* s: [...] edge2 cur_len edge edge anchor anchor */
3952 ADD
, /* s: [...] edge2 cur_len edge org_pos */
3957 ADD
, /* s: [...] edge2 cur_len edge org_center */
3962 CALL
, /* s: [...] edge2 cur_len edge org_center cur_pos1 */
3967 SUB
, /* s: ... cur_len edge cur_pos1 (org_center - cur_pos1) */
3974 ABS
, /* s: ... cur_len edge cur_pos1 (org_center - cur_pos1) delta1 */
3981 ABS
, /* s: [...] edge2 cur_len edge cur_pos1 delta1 delta2 */
3983 LT
, /* delta1 < delta2 */
3988 SUB
, /* cur_pos1 = cur_pos1 - u_off */
3994 ADD
, /* cur_pos1 = cur_pos1 + d_off */
3995 EIF
, /* s: [...] edge2 cur_len edge cur_pos1 */
4001 SUB
, /* arg = cur_pos1 - cur_len/2 */
4003 SWAP
, /* s: [...] edge2 cur_len arg edge */
4009 SWAP
, /* s: [...] edge2 cur_len edge edge arg edge */
4012 SHPIX
, /* edge = cur_pos1 - cur_len/2 */
4015 SWAP
, /* s: [...] edge2 cur_len edge */
4019 GC_cur
, /* s: [...] edge2 cur_len edge anchor_pos */
4027 ADD
, /* s: [...] edge2 cur_len edge org_pos */
4034 ADD
, /* s: [...] edge2 cur_len edge org_pos org_center */
4040 CALL
, /* cur_pos1 = ROUND(org_pos) */
4052 SUB
, /* s: [...] edge2 cur_len edge org_center cur_pos1 cur_pos2 */
4061 SUB
, /* s: ... cur_len edge cur_pos1 cur_pos2 (cur_len/2 - org_center) */
4068 ABS
, /* delta1 = |cur_pos1 + cur_len / 2 - org_center| */
4074 ABS
, /* s: ... edge2 cur_len edge cur_pos1 cur_pos2 delta1 delta2 */
4075 LT
, /* delta1 < delta2 */
4077 POP
, /* arg = cur_pos1 */
4081 POP
, /* arg = cur_pos2 */
4082 EIF
, /* s: [...] edge2 cur_len edge arg */
4089 SWAP
, /* s: [...] edge2 cur_len edge edge arg edge */
4092 SHPIX
, /* edge = arg */
4093 EIF
, /* s: [...] edge2 cur_len edge */
4103 * Handle the STEM action to align two edges of a stem, then moving one
4104 * edge again if necessary to stay bound.
4106 * The code after computing `cur_len' to shift `edge' and `edge2'
4107 * is equivalent to the snippet below (part of `ta_latin_hint_edges'):
4110 * if cur_len < = 64:
4117 * org_pos = anchor + (edge_orig - anchor_orig)
4118 * org_center = org_pos + org_len / 2
4120 * cur_pos1 = ROUND(org_center)
4121 * delta1 = |org_center - (cur_pos1 - u_off)|
4122 * delta2 = |org_center - (cur_pos1 + d_off)|
4123 * if (delta1 < delta2):
4124 * cur_pos1 = cur_pos1 - u_off
4126 * cur_pos1 = cur_pos1 + d_off
4128 * edge = cur_pos1 - cur_len / 2
4131 * org_pos = anchor + (edge_orig - anchor_orig)
4132 * org_center = org_pos + org_len / 2
4134 * cur_pos1 = ROUND(org_pos)
4135 * delta1 = |cur_pos1 + cur_len / 2 - org_center|
4136 * cur_pos2 = ROUND(org_pos + org_len) - cur_len
4137 * delta2 = |cur_pos2 + cur_len / 2 - org_center|
4139 * if (delta1 < delta2):
4144 * edge2 = edge + cur_len
4146 * in: top_to_bottom_hinting
4149 * edge_point (in twilight zone)
4150 * edge2_point (in twilight zone)
4151 * edge[-1] (in twilight zone)
4152 * ... stuff for bci_align_segments (edge) ...
4153 * ... stuff for bci_align_segments (edge2)...
4159 * sal_top_to_bottom_hinting
4161 * uses: bci_stem_common
4162 * bci_align_segments
4165 static const unsigned char FPGM(bci_stem_bound
) [] =
4176 ROLL
, /* s: edge[-1] cur_len edge edge2 */
4179 ALIGNRP
, /* align `edge2' with rp0 (still `edge') */
4183 WS
, /* s: edge[-1] cur_len edge edge2 */
4185 SHPIX
, /* edge2 = edge + cur_len */
4187 SWAP
, /* s: edge edge[-1] */
4189 MDAP_noround
, /* set rp0 and rp1 to `edge[-1]' */
4194 GC_cur
, /* s: edge edge[-1]_pos edge_pos */
4196 sal_top_to_bottom_hinting
,
4199 LT
, /* edge_pos > edge[-1]_pos */
4201 GT
, /* edge_pos < edge[-1]_pos */
4205 ALIGNRP
, /* align `edge' to `edge[-1]' */
4208 MDAP_noround
, /* set rp0 and rp1 to `edge' */
4213 SZP1
, /* set zp1 to normal zone 1 */
4219 MDAP_noround
, /* set rp0 and rp1 to `edge2' */
4231 * bci_action_stem_bound
4232 * bci_action_stem_bound_serif
4233 * bci_action_stem_bound_round
4234 * bci_action_stem_bound_round_serif
4235 * bci_action_stem_down_bound
4236 * bci_action_stem_down_bound_serif
4237 * bci_action_stem_down_bound_round
4238 * bci_action_stem_down_bound_round_serif
4240 * Higher-level routines for calling `bci_stem_bound'.
4243 static const unsigned char FPGM(bci_action_stem_bound
) [] =
4247 bci_action_stem_bound
,
4261 static const unsigned char FPGM(bci_action_stem_bound_serif
) [] =
4265 bci_action_stem_bound_serif
,
4279 static const unsigned char FPGM(bci_action_stem_bound_round
) [] =
4283 bci_action_stem_bound_round
,
4297 static const unsigned char FPGM(bci_action_stem_bound_round_serif
) [] =
4301 bci_action_stem_bound_round_serif
,
4315 static const unsigned char FPGM(bci_action_stem_down_bound
) [] =
4319 bci_action_stem_down_bound
,
4333 static const unsigned char FPGM(bci_action_stem_down_bound_serif
) [] =
4337 bci_action_stem_down_bound_serif
,
4351 static const unsigned char FPGM(bci_action_stem_down_bound_round
) [] =
4355 bci_action_stem_down_bound_round
,
4369 static const unsigned char FPGM(bci_action_stem_down_bound_round_serif
) [] =
4373 bci_action_stem_down_bound_round_serif
,
4391 * Handle the STEM action to align two edges of a stem.
4393 * See `bci_stem_bound' for more details.
4395 * in: edge2_is_serif
4397 * edge_point (in twilight zone)
4398 * edge2_point (in twilight zone)
4399 * ... stuff for bci_align_segments (edge) ...
4400 * ... stuff for bci_align_segments (edge2)...
4407 * uses: bci_stem_common
4408 * bci_align_segments
4411 static const unsigned char FPGM(bci_stem
) [] =
4424 SWAP
, /* s: cur_len edge2 */
4427 ALIGNRP
, /* align `edge2' with rp0 (still `edge') */
4431 WS
, /* s: cur_len edge2 */
4433 SHPIX
, /* edge2 = edge + cur_len */
4438 SZP1
, /* set zp1 to normal zone 1 */
4444 MDAP_noround
, /* set rp0 and rp1 to `edge2' */
4456 * bci_action_stem_serif
4457 * bci_action_stem_round
4458 * bci_action_stem_round_serif
4460 * Higher-level routines for calling `bci_stem'.
4463 static const unsigned char FPGM(bci_action_stem
) [] =
4480 static const unsigned char FPGM(bci_action_stem_serif
) [] =
4484 bci_action_stem_serif
,
4497 static const unsigned char FPGM(bci_action_stem_round
) [] =
4501 bci_action_stem_round
,
4514 static const unsigned char FPGM(bci_action_stem_round_serif
) [] =
4518 bci_action_stem_round_serif
,
4535 * Handle the LINK action to link an edge to another one.
4539 * base_point (in twilight zone)
4540 * stem_point (in twilight zone)
4541 * ... stuff for bci_align_segments (base) ...
4543 * sal: sal_base_delta
4545 * uses: func[sal_stem_width_function]
4546 * bci_align_segments
4549 static const unsigned char FPGM(bci_link
) [] =
4558 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
4566 DUP
, /* s: stem is_round is_serif stem base base */
4573 SUB
, /* base_delta = base_point_pos - base_point_orig_pos */
4577 WS
, /* sal_base_delta = base_delta */
4579 MDAP_noround
, /* set rp0 and rp1 to `base_point' (for ALIGNRP below) */
4581 MD_orig_ZP2_0
, /* s: stem is_round is_serif dist_orig */
4584 sal_stem_width_function
,
4586 CALL
, /* s: stem new_dist */
4590 ALIGNRP
, /* align `stem_point' with `base_point' */
4592 MDAP_noround
, /* set rp0 and rp1 to `stem_point' */
4594 SHPIX
, /* stem_point = base_point + new_dist */
4599 SZP1
, /* set zp1 to normal zone 1 */
4609 * bci_action_link_serif
4610 * bci_action_link_round
4611 * bci_action_link_round_serif
4613 * Higher-level routines for calling `bci_link'.
4616 static const unsigned char FPGM(bci_action_link
) [] =
4633 static const unsigned char FPGM(bci_action_link_serif
) [] =
4637 bci_action_link_serif
,
4650 static const unsigned char FPGM(bci_action_link_round
) [] =
4654 bci_action_link_round
,
4667 static const unsigned char FPGM(bci_action_link_round_serif
) [] =
4671 bci_action_link_round_serif
,
4688 * Handle the ANCHOR action to align two edges
4689 * and to set the edge anchor.
4691 * The code after computing `cur_len' to shift `edge' and `edge2'
4692 * is equivalent to the snippet below (part of `ta_latin_hint_edges'):
4695 * if cur_len < = 64:
4702 * org_center = edge_orig + org_len / 2
4703 * cur_pos1 = ROUND(org_center)
4705 * error1 = |org_center - (cur_pos1 - u_off)|
4706 * error2 = |org_center - (cur_pos1 + d_off)|
4707 * if (error1 < error2):
4708 * cur_pos1 = cur_pos1 - u_off
4710 * cur_pos1 = cur_pos1 + d_off
4712 * edge = cur_pos1 - cur_len / 2
4713 * edge2 = edge + cur_len
4716 * edge = ROUND(edge_orig)
4718 * in: edge2_is_serif
4720 * edge_point (in twilight zone)
4721 * edge2_point (in twilight zone)
4722 * ... stuff for bci_align_segments (edge) ...
4730 * uses: func[sal_stem_width_function]
4732 * bci_align_segments
4736 #define sal_u_off sal_temp1
4738 #define sal_d_off sal_temp2
4740 #define sal_org_len sal_temp3
4742 static const unsigned char FPGM(bci_anchor
) [] =
4749 /* store anchor point number in `sal_anchor' */
4754 WS
, /* sal_anchor = edge_point */
4758 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
4766 DUP
, /* s: edge2 edge is_round is_serif edge2 edge edge */
4767 MDAP_noround
, /* set rp0 and rp1 to `edge_point' (for ALIGNRP below) */
4769 MD_orig_ZP2_0
, /* s: edge2 edge is_round is_serif org_len */
4777 sal_base_delta
, /* no base_delta needed here */
4782 sal_stem_width_function
,
4784 CALL
, /* s: edge2 edge cur_len */
4789 LT
, /* cur_len < 96 */
4794 LTEQ
, /* cur_len <= 64 */
4812 SWAP
, /* s: edge2 cur_len edge */
4813 DUP
, /* s: edge2 cur_len edge edge */
4820 ADD
, /* s: edge2 cur_len edge org_center */
4825 CALL
, /* s: edge2 cur_len edge org_center cur_pos1 */
4830 SUB
, /* s: edge2 cur_len edge cur_pos1 (org_center - cur_pos1) */
4837 ABS
, /* s: edge2 cur_len edge cur_pos1 (org_center - cur_pos1) error1 */
4844 ABS
, /* s: edge2 cur_len edge cur_pos1 error1 error2 */
4846 LT
, /* error1 < error2 */
4851 SUB
, /* cur_pos1 = cur_pos1 - u_off */
4857 ADD
, /* cur_pos1 = cur_pos1 + d_off */
4858 EIF
, /* s: edge2 cur_len edge cur_pos1 */
4864 SUB
, /* s: edge2 cur_len edge (cur_pos1 - cur_len/2) */
4868 CINDEX
, /* s: edge2 cur_len edge (cur_pos1 - cur_len/2) edge */
4871 SHPIX
, /* edge = cur_pos1 - cur_len/2 */
4873 SWAP
, /* s: cur_len edge2 */
4875 ALIGNRP
, /* align `edge2' with rp0 (still `edge') */
4877 SHPIX
, /* edge2 = edge1 + cur_len */
4880 POP
, /* s: edge2 edge */
4888 CALL
, /* s: edge2 edge edge_pos round(edge_orig_pos) */
4891 SHPIX
, /* edge = round(edge_orig) */
4893 /* clean up stack */
4900 SZP1
, /* set zp1 to normal zone 1 */
4910 * bci_action_anchor_serif
4911 * bci_action_anchor_round
4912 * bci_action_anchor_round_serif
4914 * Higher-level routines for calling `bci_anchor'.
4917 static const unsigned char FPGM(bci_action_anchor
) [] =
4934 static const unsigned char FPGM(bci_action_anchor_serif
) [] =
4938 bci_action_anchor_serif
,
4951 static const unsigned char FPGM(bci_action_anchor_round
) [] =
4955 bci_action_anchor_round
,
4968 static const unsigned char FPGM(bci_action_anchor_round_serif
) [] =
4972 bci_action_anchor_round_serif
,
4987 * bci_action_blue_anchor
4989 * Handle the BLUE_ANCHOR action to align an edge with a blue zone
4990 * and to set the edge anchor.
4992 * in: anchor_point (in twilight zone)
4994 * edge_point (in twilight zone)
4995 * ... stuff for bci_align_segments (edge) ...
4999 * uses: bci_action_blue
5002 static const unsigned char FPGM(bci_action_blue_anchor
) [] =
5006 bci_action_blue_anchor
,
5009 /* store anchor point number in `sal_anchor' */
5027 * Handle the BLUE action to align an edge with a blue zone.
5030 * edge_point (in twilight zone)
5031 * ... stuff for bci_align_segments (edge) ...
5033 * uses: bci_align_segments
5036 static const unsigned char FPGM(bci_action_blue
) [] =
5045 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
5047 /* move `edge_point' to `blue_cvt_idx' position; */
5048 /* note that we can't use MIAP since this would modify */
5049 /* the twilight point's original coordinates also */
5053 MDAP_noround
, /* set rp0 and rp1 to `edge' */
5055 GC_cur
, /* s: new_pos edge edge_pos */
5058 SUB
, /* s: edge (new_pos - edge_pos) */
5064 SZP1
, /* set zp1 to normal zone 1 */
5075 * Common code for bci_action_serif routines.
5077 * in: top_to_bottom_hinting
5081 * sal: sal_top_to_bottom_hinting
5085 static const unsigned char FPGM(bci_serif_common
) [] =
5094 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
5097 sal_top_to_bottom_hinting
,
5106 MINDEX
, /* s: [...] serif serif serif serif base */
5108 MDAP_noround
, /* set rp0 and rp1 to `base_point' */
5111 ALIGNRP
, /* align `serif_point' with `base_point' */
5112 SHPIX
, /* serif = base + (serif_orig_pos - base_orig_pos) */
5122 * Move an edge if necessary to stay within a lower bound.
5127 * sal: sal_top_to_bottom_hinting
5129 * uses: bci_align_segments
5132 static const unsigned char FPGM(bci_lower_bound
) [] =
5139 SWAP
, /* s: edge bound */
5141 MDAP_noround
, /* set rp0 and rp1 to `bound' */
5146 GC_cur
, /* s: edge bound_pos edge_pos */
5148 sal_top_to_bottom_hinting
,
5151 LT
, /* edge_pos > bound_pos */
5153 GT
, /* edge_pos < bound_pos */
5157 ALIGNRP
, /* align `edge' to `bound' */
5160 MDAP_noround
, /* set rp0 and rp1 to `edge_point' */
5165 SZP1
, /* set zp1 to normal zone 1 */
5176 * Move an edge if necessary to stay within an upper bound.
5181 * sal: sal_top_to_bottom_hinting
5183 * uses: bci_align_segments
5186 static const unsigned char FPGM(bci_upper_bound
) [] =
5193 SWAP
, /* s: edge bound */
5195 MDAP_noround
, /* set rp0 and rp1 to `bound' */
5200 GC_cur
, /* s: edge bound_pos edge_pos */
5202 sal_top_to_bottom_hinting
,
5205 GT
, /* edge_pos < bound_pos */
5207 LT
, /* edge_pos > bound_pos */
5211 ALIGNRP
, /* align `edge' to `bound' */
5214 MDAP_noround
, /* set rp0 and rp1 to `edge_point' */
5219 SZP1
, /* set zp1 to normal zone 1 */
5228 * bci_upper_lower_bound
5230 * Move an edge if necessary to stay within a lower and lower bound.
5236 * sal: sal_top_to_bottom_hinting
5238 * uses: bci_align_segments
5241 static const unsigned char FPGM(bci_upper_lower_bound
) [] =
5245 bci_upper_lower_bound
,
5248 SWAP
, /* s: upper serif lower */
5250 MDAP_noround
, /* set rp0 and rp1 to `lower' */
5255 GC_cur
, /* s: upper serif lower_pos serif_pos */
5257 sal_top_to_bottom_hinting
,
5260 LT
, /* serif_pos > lower_pos */
5262 GT
, /* serif_pos < lower_pos */
5266 ALIGNRP
, /* align `serif' to `lower' */
5269 SWAP
, /* s: serif upper */
5271 MDAP_noround
, /* set rp0 and rp1 to `upper' */
5276 GC_cur
, /* s: serif upper_pos serif_pos */
5278 sal_top_to_bottom_hinting
,
5281 GT
, /* serif_pos < upper_pos */
5283 LT
, /* serif_pos > upper_pos */
5287 ALIGNRP
, /* align `serif' to `upper' */
5290 MDAP_noround
, /* set rp0 and rp1 to `serif_point' */
5295 SZP1
, /* set zp1 to normal zone 1 */
5306 * Handle the SERIF action to align a serif with its base.
5308 * in: serif_point (in twilight zone)
5309 * base_point (in twilight zone)
5310 * ... stuff for bci_align_segments (serif) ...
5312 * uses: bci_serif_common
5313 * bci_align_segments
5316 static const unsigned char FPGM(bci_action_serif
) [] =
5328 MDAP_noround
, /* set rp0 and rp1 to `serif_point' */
5333 SZP1
, /* set zp1 to normal zone 1 */
5342 * bci_action_serif_lower_bound
5344 * Handle the SERIF action to align a serif with its base, then moving it
5345 * again if necessary to stay within a lower bound.
5347 * in: serif_point (in twilight zone)
5348 * base_point (in twilight zone)
5349 * edge[-1] (in twilight zone)
5350 * ... stuff for bci_align_segments (serif) ...
5352 * uses: bci_serif_common
5356 static const unsigned char FPGM(bci_action_serif_lower_bound
) [] =
5360 bci_action_serif_lower_bound
,
5378 * bci_action_serif_upper_bound
5380 * Handle the SERIF action to align a serif with its base, then moving it
5381 * again if necessary to stay within an upper bound.
5383 * in: serif_point (in twilight zone)
5384 * base_point (in twilight zone)
5385 * edge[1] (in twilight zone)
5386 * ... stuff for bci_align_segments (serif) ...
5388 * uses: bci_serif_common
5392 static const unsigned char FPGM(bci_action_serif_upper_bound
) [] =
5396 bci_action_serif_upper_bound
,
5414 * bci_action_serif_upper_lower_bound
5416 * Handle the SERIF action to align a serif with its base, then moving it
5417 * again if necessary to stay within a lower and upper bound.
5419 * in: serif_point (in twilight zone)
5420 * base_point (in twilight zone)
5421 * edge[-1] (in twilight zone)
5422 * edge[1] (in twilight zone)
5423 * ... stuff for bci_align_segments (serif) ...
5425 * uses: bci_serif_common
5426 * bci_upper_lower_bound
5429 static const unsigned char FPGM(bci_action_serif_upper_lower_bound
) [] =
5433 bci_action_serif_upper_lower_bound
,
5438 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
5446 bci_upper_lower_bound
,
5455 * bci_action_serif_down_lower_bound
5457 * Handle the SERIF action to align a serif with its base, then moving it
5458 * again if necessary to stay within a lower bound. We hint top to
5461 * in: serif_point (in twilight zone)
5462 * base_point (in twilight zone)
5463 * edge[-1] (in twilight zone)
5464 * ... stuff for bci_align_segments (serif) ...
5466 * uses: bci_serif_common
5470 static const unsigned char FPGM(bci_action_serif_down_lower_bound
) [] =
5474 bci_action_serif_down_lower_bound
,
5492 * bci_action_serif_down_upper_bound
5494 * Handle the SERIF action to align a serif with its base, then moving it
5495 * again if necessary to stay within an upper bound. We hint top to
5498 * in: serif_point (in twilight zone)
5499 * base_point (in twilight zone)
5500 * edge[1] (in twilight zone)
5501 * ... stuff for bci_align_segments (serif) ...
5503 * uses: bci_serif_common
5507 static const unsigned char FPGM(bci_action_serif_down_upper_bound
) [] =
5511 bci_action_serif_down_upper_bound
,
5529 * bci_action_serif_down_upper_lower_bound
5531 * Handle the SERIF action to align a serif with its base, then moving it
5532 * again if necessary to stay within a lower and upper bound. We hint top
5535 * in: serif_point (in twilight zone)
5536 * base_point (in twilight zone)
5537 * edge[-1] (in twilight zone)
5538 * edge[1] (in twilight zone)
5539 * ... stuff for bci_align_segments (serif) ...
5541 * uses: bci_serif_common
5542 * bci_upper_lower_bound
5545 static const unsigned char FPGM(bci_action_serif_down_upper_lower_bound
) [] =
5549 bci_action_serif_down_upper_lower_bound
,
5554 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
5562 bci_upper_lower_bound
,
5571 * bci_serif_anchor_common
5573 * Common code for bci_action_serif_anchor routines.
5575 * in: top_to_bottom_hinting
5578 * out: edge (adjusted)
5581 * sal_top_to_bottom_hinting
5586 static const unsigned char FPGM(bci_serif_anchor_common
) [] =
5590 bci_serif_anchor_common
,
5595 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
5598 sal_top_to_bottom_hinting
,
5606 WS
, /* sal_anchor = edge_point */
5616 CALL
, /* s: [...] edge edge edge_pos round(edge_orig_pos) */
5619 SHPIX
, /* edge = round(edge_orig) */
5627 * bci_action_serif_anchor
5629 * Handle the SERIF_ANCHOR action to align a serif and to set the edge
5632 * in: edge_point (in twilight zone)
5633 * ... stuff for bci_align_segments (edge) ...
5635 * uses: bci_serif_anchor_common
5636 * bci_align_segments
5639 static const unsigned char FPGM(bci_action_serif_anchor
) [] =
5643 bci_action_serif_anchor
,
5648 bci_serif_anchor_common
,
5651 MDAP_noround
, /* set rp0 and rp1 to `edge' */
5656 SZP1
, /* set zp1 to normal zone 1 */
5665 * bci_action_serif_anchor_lower_bound
5667 * Handle the SERIF_ANCHOR action to align a serif and to set the edge
5668 * anchor, then moving it again if necessary to stay within a lower
5671 * in: edge_point (in twilight zone)
5672 * edge[-1] (in twilight zone)
5673 * ... stuff for bci_align_segments (edge) ...
5675 * uses: bci_serif_anchor_common
5679 static const unsigned char FPGM(bci_action_serif_anchor_lower_bound
) [] =
5683 bci_action_serif_anchor_lower_bound
,
5688 bci_serif_anchor_common
,
5701 * bci_action_serif_anchor_upper_bound
5703 * Handle the SERIF_ANCHOR action to align a serif and to set the edge
5704 * anchor, then moving it again if necessary to stay within an upper
5707 * in: edge_point (in twilight zone)
5708 * edge[1] (in twilight zone)
5709 * ... stuff for bci_align_segments (edge) ...
5711 * uses: bci_serif_anchor_common
5715 static const unsigned char FPGM(bci_action_serif_anchor_upper_bound
) [] =
5719 bci_action_serif_anchor_upper_bound
,
5724 bci_serif_anchor_common
,
5737 * bci_action_serif_anchor_upper_lower_bound
5739 * Handle the SERIF_ANCHOR action to align a serif and to set the edge
5740 * anchor, then moving it again if necessary to stay within a lower and
5743 * in: edge_point (in twilight zone)
5744 * edge[-1] (in twilight zone)
5745 * edge[1] (in twilight zone)
5746 * ... stuff for bci_align_segments (edge) ...
5748 * uses: bci_serif_anchor_common
5749 * bci_upper_lower_bound
5752 static const unsigned char FPGM(bci_action_serif_anchor_upper_lower_bound
) [] =
5756 bci_action_serif_anchor_upper_lower_bound
,
5761 bci_serif_anchor_common
,
5765 bci_upper_lower_bound
,
5774 * bci_action_serif_anchor_down_lower_bound
5776 * Handle the SERIF_ANCHOR action to align a serif and to set the edge
5777 * anchor, then moving it again if necessary to stay within a lower
5778 * bound. We hint top to bottom.
5780 * in: edge_point (in twilight zone)
5781 * edge[-1] (in twilight zone)
5782 * ... stuff for bci_align_segments (edge) ...
5784 * uses: bci_serif_anchor_common
5788 static const unsigned char FPGM(bci_action_serif_anchor_down_lower_bound
) [] =
5792 bci_action_serif_anchor_down_lower_bound
,
5797 bci_serif_anchor_common
,
5810 * bci_action_serif_anchor_down_upper_bound
5812 * Handle the SERIF_ANCHOR action to align a serif and to set the edge
5813 * anchor, then moving it again if necessary to stay within an upper
5814 * bound. We hint top to bottom.
5816 * in: edge_point (in twilight zone)
5817 * edge[1] (in twilight zone)
5818 * ... stuff for bci_align_segments (edge) ...
5820 * uses: bci_serif_anchor_common
5824 static const unsigned char FPGM(bci_action_serif_anchor_down_upper_bound
) [] =
5828 bci_action_serif_anchor_down_upper_bound
,
5833 bci_serif_anchor_common
,
5846 * bci_action_serif_anchor_down_upper_lower_bound
5848 * Handle the SERIF_ANCHOR action to align a serif and to set the edge
5849 * anchor, then moving it again if necessary to stay within a lower and
5850 * upper bound. We hint top to bottom.
5852 * in: edge_point (in twilight zone)
5853 * edge[-1] (in twilight zone)
5854 * edge[1] (in twilight zone)
5855 * ... stuff for bci_align_segments (edge) ...
5857 * uses: bci_serif_anchor_common
5858 * bci_upper_lower_bound
5861 static const unsigned char FPGM(bci_action_serif_anchor_down_upper_lower_bound
) [] =
5865 bci_action_serif_anchor_down_upper_lower_bound
,
5870 bci_serif_anchor_common
,
5874 bci_upper_lower_bound
,
5883 * bci_serif_link1_common
5885 * Common code for bci_action_serif_link1 routines.
5887 * in: top_to_bottom_hinting
5892 * out: edge (adjusted)
5894 * sal: sal_top_to_bottom_hinting
5898 static const unsigned char FPGM(bci_serif_link1_common
) [] =
5902 bci_serif_link1_common
,
5907 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
5910 sal_top_to_bottom_hinting
,
5916 CINDEX
, /* s: [...] after edge before after */
5919 CINDEX
, /* s: [...] after edge before after before */
5923 EQ
, /* after_orig_pos == before_orig_pos */
5924 IF
, /* s: [...] after edge before */
5925 MDAP_noround
, /* set rp0 and rp1 to `before' */
5927 ALIGNRP
, /* align `edge' with `before' */
5932 /* we have to execute `a*b/c', with b/c very near to 1: */
5933 /* to avoid overflow while retaining precision, */
5934 /* we transform this to `a + a * (b-c)/c' */
5938 CINDEX
, /* s: [...] after edge before edge */
5941 CINDEX
, /* s: [...] after edge before edge before */
5942 MD_orig_ZP2_0
, /* a = edge_orig_pos - before_orig_pos */
5947 CINDEX
, /* s: [...] after edge before a a after */
5950 CINDEX
, /* s: [...] after edge before a a after before */
5951 MD_orig_ZP2_0
, /* c = after_orig_pos - before_orig_pos */
5955 CINDEX
, /* s: [...] after edge before a a c after */
5958 CINDEX
, /* s: [...] after edge before a a c after before */
5959 MD_cur
, /* b = after_pos - before_pos */
5963 CINDEX
, /* s: [...] after edge before a a c b c */
5972 MUL
, /* (b-c) in 16.16 format */
5977 DIV
, /* s: [...] after edge before a a (b-c)/c */
5979 POP
, /* avoid division by zero */
5982 MUL
, /* a * (b-c)/c * 2^10 */
5983 DIV_BY_1024
, /* a * (b-c)/c */
5987 MDAP_noround
, /* set rp0 and rp1 to `before' */
5988 SWAP
, /* s: [...] after a*b/c edge */
5991 ALIGNRP
, /* align `edge' with `before' */
5993 SHPIX
, /* shift `edge' by `a*b/c' */
5995 SWAP
, /* s: [...] edge after */
6005 * bci_action_serif_link1
6007 * Handle the SERIF_LINK1 action to align a serif, depending on edges
6010 * in: before_point (in twilight zone)
6011 * edge_point (in twilight zone)
6012 * after_point (in twilight zone)
6013 * ... stuff for bci_align_segments (edge) ...
6015 * uses: bci_serif_link1_common
6016 * bci_align_segments
6019 static const unsigned char FPGM(bci_action_serif_link1
) [] =
6023 bci_action_serif_link1
,
6028 bci_serif_link1_common
,
6031 MDAP_noround
, /* set rp0 and rp1 to `edge' */
6036 SZP1
, /* set zp1 to normal zone 1 */
6045 * bci_action_serif_link1_lower_bound
6047 * Handle the SERIF_LINK1 action to align a serif, depending on edges
6048 * before and after. Additionally, move the serif again if necessary to
6049 * stay within a lower bound.
6051 * in: before_point (in twilight zone)
6052 * edge_point (in twilight zone)
6053 * after_point (in twilight zone)
6054 * edge[-1] (in twilight zone)
6055 * ... stuff for bci_align_segments (edge) ...
6057 * uses: bci_serif_link1_common
6061 static const unsigned char FPGM(bci_action_serif_link1_lower_bound
) [] =
6065 bci_action_serif_link1_lower_bound
,
6070 bci_serif_link1_common
,
6083 * bci_action_serif_link1_upper_bound
6085 * Handle the SERIF_LINK1 action to align a serif, depending on edges
6086 * before and after. Additionally, move the serif again if necessary to
6087 * stay within an upper bound.
6089 * in: before_point (in twilight zone)
6090 * edge_point (in twilight zone)
6091 * after_point (in twilight zone)
6092 * edge[1] (in twilight zone)
6093 * ... stuff for bci_align_segments (edge) ...
6095 * uses: bci_serif_link1_common
6099 static const unsigned char FPGM(bci_action_serif_link1_upper_bound
) [] =
6103 bci_action_serif_link1_upper_bound
,
6108 bci_serif_link1_common
,
6121 * bci_action_serif_link1_upper_lower_bound
6123 * Handle the SERIF_LINK1 action to align a serif, depending on edges
6124 * before and after. Additionally, move the serif again if necessary to
6125 * stay within a lower and upper bound.
6127 * in: before_point (in twilight zone)
6128 * edge_point (in twilight zone)
6129 * after_point (in twilight zone)
6130 * edge[-1] (in twilight zone)
6131 * edge[1] (in twilight zone)
6132 * ... stuff for bci_align_segments (edge) ...
6134 * uses: bci_serif_link1_common
6135 * bci_upper_lower_bound
6138 static const unsigned char FPGM(bci_action_serif_link1_upper_lower_bound
) [] =
6142 bci_action_serif_link1_upper_lower_bound
,
6147 bci_serif_link1_common
,
6151 bci_upper_lower_bound
,
6160 * bci_action_serif_link1_down_lower_bound
6162 * Handle the SERIF_LINK1 action to align a serif, depending on edges
6163 * before and after. Additionally, move the serif again if necessary to
6164 * stay within a lower bound. We hint top to bottom.
6166 * in: before_point (in twilight zone)
6167 * edge_point (in twilight zone)
6168 * after_point (in twilight zone)
6169 * edge[-1] (in twilight zone)
6170 * ... stuff for bci_align_segments (edge) ...
6172 * uses: bci_serif_link1_common
6176 static const unsigned char FPGM(bci_action_serif_link1_down_lower_bound
) [] =
6180 bci_action_serif_link1_down_lower_bound
,
6185 bci_serif_link1_common
,
6198 * bci_action_serif_link1_down_upper_bound
6200 * Handle the SERIF_LINK1 action to align a serif, depending on edges
6201 * before and after. Additionally, move the serif again if necessary to
6202 * stay within an upper bound. We hint top to bottom.
6204 * in: before_point (in twilight zone)
6205 * edge_point (in twilight zone)
6206 * after_point (in twilight zone)
6207 * edge[1] (in twilight zone)
6208 * ... stuff for bci_align_segments (edge) ...
6210 * uses: bci_serif_link1_common
6214 static const unsigned char FPGM(bci_action_serif_link1_down_upper_bound
) [] =
6218 bci_action_serif_link1_down_upper_bound
,
6223 bci_serif_link1_common
,
6236 * bci_action_serif_link1_down_upper_lower_bound
6238 * Handle the SERIF_LINK1 action to align a serif, depending on edges
6239 * before and after. Additionally, move the serif again if necessary to
6240 * stay within a lower and upper bound. We hint top to bottom.
6242 * in: before_point (in twilight zone)
6243 * edge_point (in twilight zone)
6244 * after_point (in twilight zone)
6245 * edge[-1] (in twilight zone)
6246 * edge[1] (in twilight zone)
6247 * ... stuff for bci_align_segments (edge) ...
6249 * uses: bci_serif_link1_common
6250 * bci_upper_lower_bound
6253 static const unsigned char FPGM(bci_action_serif_link1_down_upper_lower_bound
) [] =
6257 bci_action_serif_link1_down_upper_lower_bound
,
6262 bci_serif_link1_common
,
6266 bci_upper_lower_bound
,
6275 * bci_serif_link2_common
6277 * Common code for bci_action_serif_link2 routines.
6279 * in: top_to_bottom_hinting
6282 * out: edge (adjusted)
6285 * sal_top_to_bottom_hinting
6289 static const unsigned char FPGM(bci_serif_link2_common
) [] =
6293 bci_serif_link2_common
,
6298 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
6301 sal_top_to_bottom_hinting
,
6305 DUP
, /* s: [...] edge edge */
6309 DUP
, /* s: [...] edge edge anchor anchor */
6310 MDAP_noround
, /* set rp0 and rp1 to `sal_anchor' */
6319 DIV_BY_2
, /* delta = (edge_orig_pos - anchor_orig_pos + 16) & ~31 */
6324 ALIGNRP
, /* align `edge' with `sal_anchor' */
6326 SHPIX
, /* shift `edge' by `delta' */
6334 * bci_action_serif_link2
6336 * Handle the SERIF_LINK2 action to align a serif relative to the anchor.
6338 * in: edge_point (in twilight zone)
6339 * ... stuff for bci_align_segments (edge) ...
6341 * uses: bci_serif_link2_common
6342 * bci_align_segments
6345 static const unsigned char FPGM(bci_action_serif_link2
) [] =
6349 bci_action_serif_link2
,
6354 bci_serif_link2_common
,
6357 MDAP_noround
, /* set rp0 and rp1 to `edge' */
6362 SZP1
, /* set zp1 to normal zone 1 */
6371 * bci_action_serif_link2_lower_bound
6373 * Handle the SERIF_LINK2 action to align a serif relative to the anchor.
6374 * Additionally, move the serif again if necessary to stay within a lower
6377 * in: edge_point (in twilight zone)
6378 * edge[-1] (in twilight zone)
6379 * ... stuff for bci_align_segments (edge) ...
6381 * uses: bci_serif_link2_common
6385 static const unsigned char FPGM(bci_action_serif_link2_lower_bound
) [] =
6389 bci_action_serif_link2_lower_bound
,
6394 bci_serif_link2_common
,
6407 * bci_action_serif_link2_upper_bound
6409 * Handle the SERIF_LINK2 action to align a serif relative to the anchor.
6410 * Additionally, move the serif again if necessary to stay within an upper
6413 * in: edge_point (in twilight zone)
6414 * edge[1] (in twilight zone)
6415 * ... stuff for bci_align_segments (edge) ...
6417 * uses: bci_serif_link2_common
6421 static const unsigned char FPGM(bci_action_serif_link2_upper_bound
) [] =
6425 bci_action_serif_link2_upper_bound
,
6430 bci_serif_link2_common
,
6443 * bci_action_serif_link2_upper_lower_bound
6445 * Handle the SERIF_LINK2 action to align a serif relative to the anchor.
6446 * Additionally, move the serif again if necessary to stay within a lower
6449 * in: edge_point (in twilight zone)
6450 * edge[-1] (in twilight zone)
6451 * edge[1] (in twilight zone)
6452 * ... stuff for bci_align_segments (edge) ...
6454 * uses: bci_serif_link2_common
6455 * bci_upper_lower_bound
6458 static const unsigned char FPGM(bci_action_serif_link2_upper_lower_bound
) [] =
6462 bci_action_serif_link2_upper_lower_bound
,
6467 bci_serif_link2_common
,
6471 bci_upper_lower_bound
,
6480 * bci_action_serif_link2_down_lower_bound
6482 * Handle the SERIF_LINK2 action to align a serif relative to the anchor.
6483 * Additionally, move the serif again if necessary to stay within a lower
6484 * bound. We hint top to bottom.
6486 * in: edge_point (in twilight zone)
6487 * edge[-1] (in twilight zone)
6488 * ... stuff for bci_align_segments (edge) ...
6490 * uses: bci_serif_link2_common
6494 static const unsigned char FPGM(bci_action_serif_link2_down_lower_bound
) [] =
6498 bci_action_serif_link2_down_lower_bound
,
6503 bci_serif_link2_common
,
6516 * bci_action_serif_link2_down_upper_bound
6518 * Handle the SERIF_LINK2 action to align a serif relative to the anchor.
6519 * Additionally, move the serif again if necessary to stay within an upper
6520 * bound. We hint top to bottom.
6522 * in: edge_point (in twilight zone)
6523 * edge[1] (in twilight zone)
6524 * ... stuff for bci_align_segments (edge) ...
6526 * uses: bci_serif_link2_common
6530 static const unsigned char FPGM(bci_action_serif_link2_down_upper_bound
) [] =
6534 bci_action_serif_link2_down_upper_bound
,
6539 bci_serif_link2_common
,
6552 * bci_action_serif_link2_down_upper_lower_bound
6554 * Handle the SERIF_LINK2 action to align a serif relative to the anchor.
6555 * Additionally, move the serif again if necessary to stay within a lower
6556 * and upper bound. We hint top to bottom.
6558 * in: edge_point (in twilight zone)
6559 * edge[-1] (in twilight zone)
6560 * edge[1] (in twilight zone)
6561 * ... stuff for bci_align_segments (edge) ...
6563 * uses: bci_serif_link2_common
6564 * bci_upper_lower_bound
6567 static const unsigned char FPGM(bci_action_serif_link2_down_upper_lower_bound
) [] =
6571 bci_action_serif_link2_down_upper_lower_bound
,
6576 bci_serif_link2_common
,
6580 bci_upper_lower_bound
,
6591 * This is the top-level glyph hinting function which parses the arguments
6592 * on the stack and calls subroutines.
6594 * in: action_0_func_idx
6600 * CVT: cvtl_is_subglyph
6601 * cvtl_use_strong_functions
6604 * sal: sal_stem_width_function
6606 * uses: bci_action_ip_before
6607 * bci_action_ip_after
6609 * bci_action_ip_between
6611 * bci_action_adjust_bound
6612 * bci_action_adjust_bound_serif
6613 * bci_action_adjust_bound_round
6614 * bci_action_adjust_bound_round_serif
6616 * bci_action_stem_bound
6617 * bci_action_stem_bound_serif
6618 * bci_action_stem_bound_round
6619 * bci_action_stem_bound_round_serif
6622 * bci_action_link_serif
6623 * bci_action_link_round
6624 * bci_action_link_round_serif
6627 * bci_action_anchor_serif
6628 * bci_action_anchor_round
6629 * bci_action_anchor_round_serif
6631 * bci_action_blue_anchor
6634 * bci_action_adjust_serif
6635 * bci_action_adjust_round
6636 * bci_action_adjust_round_serif
6639 * bci_action_stem_serif
6640 * bci_action_stem_round
6641 * bci_action_stem_round_serif
6646 * bci_action_serif_lower_bound
6647 * bci_action_serif_upper_bound
6648 * bci_action_serif_upper_lower_bound
6650 * bci_action_serif_anchor
6651 * bci_action_serif_anchor_lower_bound
6652 * bci_action_serif_anchor_upper_bound
6653 * bci_action_serif_anchor_upper_lower_bound
6655 * bci_action_serif_link1
6656 * bci_action_serif_link1_lower_bound
6657 * bci_action_serif_link1_upper_bound
6658 * bci_action_serif_link1_upper_lower_bound
6660 * bci_action_serif_link2
6661 * bci_action_serif_link2_lower_bound
6662 * bci_action_serif_link2_upper_bound
6663 * bci_action_serif_link2_upper_lower_bound
6666 static const unsigned char FPGM(bci_hint_glyph
) [] =
6673 /* set up stem width function based on flag in CVT */
6675 sal_stem_width_function
,
6676 bci_strong_stem_width
,
6677 bci_smooth_stem_width
,
6678 cvtl_use_strong_functions
,
6691 /* loop until all data on stack is used */
6700 JROT
, /* goto start_loop */
6705 SZP2
, /* set zp2 to normal zone 1 */
6716 #define COPY_FPGM(func_name) \
6719 memcpy(bufp, fpgm_ ## func_name, \
6720 sizeof (fpgm_ ## func_name)); \
6721 bufp += sizeof (fpgm_ ## func_name); \
6725 TA_table_build_fpgm(FT_Byte
** fpgm
,
6730 SFNT_Table
* glyf_table
= &font
->tables
[sfnt
->glyf_idx
];
6731 glyf_Data
* data
= (glyf_Data
*)glyf_table
->data
;
6733 unsigned char num_used_styles
= (unsigned char)data
->num_used_styles
;
6734 unsigned char fallback_style
=
6735 CVT_SCALING_VALUE_OFFSET(0)
6736 + (unsigned char)data
->style_ids
[font
->fallback_style
];
6744 /* for compatibility with dumb bytecode interpreters or analyzers, */
6745 /* FDEFs are stored in ascending index order, without holes -- */
6746 /* note that some FDEFs are not always needed */
6747 /* (depending on options of `TTFautohint'), */
6748 /* but implementing dynamic FDEF indices would be a lot of work */
6750 buf_len
= sizeof (FPGM(bci_align_x_height_a
))
6751 + (font
->increase_x_height
6752 ? (sizeof (FPGM(bci_align_x_height_b1a
))
6754 + sizeof (FPGM(bci_align_x_height_b1b
)))
6755 : sizeof (FPGM(bci_align_x_height_b2
)))
6756 + sizeof (FPGM(bci_align_x_height_c
))
6757 + sizeof (FPGM(bci_round
))
6758 + sizeof (FPGM(bci_smooth_stem_width
))
6759 + sizeof (FPGM(bci_get_best_width
))
6760 + sizeof (FPGM(bci_strong_stem_width_a
))
6762 + sizeof (FPGM(bci_strong_stem_width_b
))
6763 + sizeof (FPGM(bci_loop_do
))
6764 + sizeof (FPGM(bci_loop
))
6765 + sizeof (FPGM(bci_cvt_rescale
))
6766 + sizeof (FPGM(bci_cvt_rescale_range
))
6767 + sizeof (FPGM(bci_vwidth_data_store
))
6768 + sizeof (FPGM(bci_smooth_blue_round
))
6769 + sizeof (FPGM(bci_strong_blue_round
))
6770 + sizeof (FPGM(bci_blue_round_range
))
6771 + sizeof (FPGM(bci_decrement_component_counter
))
6772 + sizeof (FPGM(bci_get_point_extrema
))
6773 + sizeof (FPGM(bci_nibbles
))
6774 + sizeof (FPGM(bci_number_set_is_element
))
6775 + sizeof (FPGM(bci_number_set_is_element2
))
6777 + sizeof (FPGM(bci_create_segment
))
6778 + sizeof (FPGM(bci_create_segments_a
))
6780 + sizeof (FPGM(bci_create_segments_b
))
6781 + (font
->control_data_head
!= 0
6782 ? sizeof (FPGM(bci_create_segments_c
))
6784 + sizeof (FPGM(bci_create_segments_d
))
6786 + sizeof (FPGM(bci_create_segments_0
))
6787 + sizeof (FPGM(bci_create_segments_1
))
6788 + sizeof (FPGM(bci_create_segments_2
))
6789 + sizeof (FPGM(bci_create_segments_3
))
6790 + sizeof (FPGM(bci_create_segments_4
))
6791 + sizeof (FPGM(bci_create_segments_5
))
6792 + sizeof (FPGM(bci_create_segments_6
))
6793 + sizeof (FPGM(bci_create_segments_7
))
6794 + sizeof (FPGM(bci_create_segments_8
))
6795 + sizeof (FPGM(bci_create_segments_9
))
6797 + sizeof (FPGM(bci_deltap1
))
6798 + sizeof (FPGM(bci_deltap2
))
6799 + sizeof (FPGM(bci_deltap3
))
6801 + sizeof (FPGM(bci_create_segments_composite_a
))
6803 + sizeof (FPGM(bci_create_segments_composite_b
))
6804 + (font
->control_data_head
!= 0
6805 ? sizeof (FPGM(bci_create_segments_composite_c
))
6807 + sizeof (FPGM(bci_create_segments_composite_d
))
6809 + sizeof (FPGM(bci_create_segments_composite_0
))
6810 + sizeof (FPGM(bci_create_segments_composite_1
))
6811 + sizeof (FPGM(bci_create_segments_composite_2
))
6812 + sizeof (FPGM(bci_create_segments_composite_3
))
6813 + sizeof (FPGM(bci_create_segments_composite_4
))
6814 + sizeof (FPGM(bci_create_segments_composite_5
))
6815 + sizeof (FPGM(bci_create_segments_composite_6
))
6816 + sizeof (FPGM(bci_create_segments_composite_7
))
6817 + sizeof (FPGM(bci_create_segments_composite_8
))
6818 + sizeof (FPGM(bci_create_segments_composite_9
))
6820 + sizeof (FPGM(bci_align_point
))
6821 + sizeof (FPGM(bci_align_segment
))
6822 + sizeof (FPGM(bci_align_segments
))
6824 + sizeof (FPGM(bci_scale_contour
))
6825 + sizeof (FPGM(bci_scale_glyph_a
))
6827 + sizeof (FPGM(bci_scale_glyph_b
))
6828 + sizeof (FPGM(bci_scale_composite_glyph_a
))
6830 + sizeof (FPGM(bci_scale_composite_glyph_b
))
6831 + sizeof (FPGM(bci_shift_contour
))
6832 + sizeof (FPGM(bci_shift_subglyph_a
))
6834 + sizeof (FPGM(bci_shift_subglyph_b
))
6835 + (font
->control_data_head
!= 0
6836 ? sizeof (FPGM(bci_shift_subglyph_c
))
6838 + sizeof (FPGM(bci_shift_subglyph_d
))
6840 + sizeof (FPGM(bci_ip_outer_align_point
))
6841 + sizeof (FPGM(bci_ip_on_align_points
))
6842 + sizeof (FPGM(bci_ip_between_align_point
))
6843 + sizeof (FPGM(bci_ip_between_align_points
))
6845 + sizeof (FPGM(bci_adjust_common
))
6846 + sizeof (FPGM(bci_stem_common
))
6847 + sizeof (FPGM(bci_serif_common
))
6848 + sizeof (FPGM(bci_serif_anchor_common
))
6849 + sizeof (FPGM(bci_serif_link1_common
))
6850 + sizeof (FPGM(bci_serif_link2_common
))
6852 + sizeof (FPGM(bci_lower_bound
))
6853 + sizeof (FPGM(bci_upper_bound
))
6854 + sizeof (FPGM(bci_upper_lower_bound
))
6856 + sizeof (FPGM(bci_adjust_bound
))
6857 + sizeof (FPGM(bci_stem_bound
))
6858 + sizeof (FPGM(bci_link
))
6859 + sizeof (FPGM(bci_anchor
))
6860 + sizeof (FPGM(bci_adjust
))
6861 + sizeof (FPGM(bci_stem
))
6863 + sizeof (FPGM(bci_action_ip_before
))
6864 + sizeof (FPGM(bci_action_ip_after
))
6865 + sizeof (FPGM(bci_action_ip_on
))
6866 + sizeof (FPGM(bci_action_ip_between
))
6868 + sizeof (FPGM(bci_action_blue
))
6869 + sizeof (FPGM(bci_action_blue_anchor
))
6871 + sizeof (FPGM(bci_action_anchor
))
6872 + sizeof (FPGM(bci_action_anchor_serif
))
6873 + sizeof (FPGM(bci_action_anchor_round
))
6874 + sizeof (FPGM(bci_action_anchor_round_serif
))
6876 + sizeof (FPGM(bci_action_adjust
))
6877 + sizeof (FPGM(bci_action_adjust_serif
))
6878 + sizeof (FPGM(bci_action_adjust_round
))
6879 + sizeof (FPGM(bci_action_adjust_round_serif
))
6880 + sizeof (FPGM(bci_action_adjust_bound
))
6881 + sizeof (FPGM(bci_action_adjust_bound_serif
))
6882 + sizeof (FPGM(bci_action_adjust_bound_round
))
6883 + sizeof (FPGM(bci_action_adjust_bound_round_serif
))
6884 + sizeof (FPGM(bci_action_adjust_down_bound
))
6885 + sizeof (FPGM(bci_action_adjust_down_bound_serif
))
6886 + sizeof (FPGM(bci_action_adjust_down_bound_round
))
6887 + sizeof (FPGM(bci_action_adjust_down_bound_round_serif
))
6889 + sizeof (FPGM(bci_action_link
))
6890 + sizeof (FPGM(bci_action_link_serif
))
6891 + sizeof (FPGM(bci_action_link_round
))
6892 + sizeof (FPGM(bci_action_link_round_serif
))
6894 + sizeof (FPGM(bci_action_stem
))
6895 + sizeof (FPGM(bci_action_stem_serif
))
6896 + sizeof (FPGM(bci_action_stem_round
))
6897 + sizeof (FPGM(bci_action_stem_round_serif
))
6898 + sizeof (FPGM(bci_action_stem_bound
))
6899 + sizeof (FPGM(bci_action_stem_bound_serif
))
6900 + sizeof (FPGM(bci_action_stem_bound_round
))
6901 + sizeof (FPGM(bci_action_stem_bound_round_serif
))
6902 + sizeof (FPGM(bci_action_stem_down_bound
))
6903 + sizeof (FPGM(bci_action_stem_down_bound_serif
))
6904 + sizeof (FPGM(bci_action_stem_down_bound_round
))
6905 + sizeof (FPGM(bci_action_stem_down_bound_round_serif
))
6907 + sizeof (FPGM(bci_action_serif
))
6908 + sizeof (FPGM(bci_action_serif_lower_bound
))
6909 + sizeof (FPGM(bci_action_serif_upper_bound
))
6910 + sizeof (FPGM(bci_action_serif_upper_lower_bound
))
6911 + sizeof (FPGM(bci_action_serif_down_lower_bound
))
6912 + sizeof (FPGM(bci_action_serif_down_upper_bound
))
6913 + sizeof (FPGM(bci_action_serif_down_upper_lower_bound
))
6915 + sizeof (FPGM(bci_action_serif_anchor
))
6916 + sizeof (FPGM(bci_action_serif_anchor_lower_bound
))
6917 + sizeof (FPGM(bci_action_serif_anchor_upper_bound
))
6918 + sizeof (FPGM(bci_action_serif_anchor_upper_lower_bound
))
6919 + sizeof (FPGM(bci_action_serif_anchor_down_lower_bound
))
6920 + sizeof (FPGM(bci_action_serif_anchor_down_upper_bound
))
6921 + sizeof (FPGM(bci_action_serif_anchor_down_upper_lower_bound
))
6923 + sizeof (FPGM(bci_action_serif_link1
))
6924 + sizeof (FPGM(bci_action_serif_link1_lower_bound
))
6925 + sizeof (FPGM(bci_action_serif_link1_upper_bound
))
6926 + sizeof (FPGM(bci_action_serif_link1_upper_lower_bound
))
6927 + sizeof (FPGM(bci_action_serif_link1_down_lower_bound
))
6928 + sizeof (FPGM(bci_action_serif_link1_down_upper_bound
))
6929 + sizeof (FPGM(bci_action_serif_link1_down_upper_lower_bound
))
6931 + sizeof (FPGM(bci_action_serif_link2
))
6932 + sizeof (FPGM(bci_action_serif_link2_lower_bound
))
6933 + sizeof (FPGM(bci_action_serif_link2_upper_bound
))
6934 + sizeof (FPGM(bci_action_serif_link2_upper_lower_bound
))
6935 + sizeof (FPGM(bci_action_serif_link2_down_lower_bound
))
6936 + sizeof (FPGM(bci_action_serif_link2_down_upper_bound
))
6937 + sizeof (FPGM(bci_action_serif_link2_down_upper_lower_bound
))
6939 + sizeof (FPGM(bci_hint_glyph
));
6941 /* buffer length must be a multiple of four */
6942 len
= (buf_len
+ 3) & ~3U;
6943 buf
= (FT_Byte
*)malloc(len
);
6945 return FT_Err_Out_Of_Memory
;
6947 /* pad end of buffer with zeros */
6948 buf
[len
- 1] = 0x00;
6949 buf
[len
- 2] = 0x00;
6950 buf
[len
- 3] = 0x00;
6952 /* copy font program into buffer and fill in the missing variables */
6955 COPY_FPGM(bci_align_x_height_a
);
6956 if (font
->increase_x_height
)
6958 COPY_FPGM(bci_align_x_height_b1a
);
6959 *(bufp
++) = HIGH(font
->increase_x_height
);
6960 *(bufp
++) = LOW(font
->increase_x_height
);
6961 COPY_FPGM(bci_align_x_height_b1b
);
6964 COPY_FPGM(bci_align_x_height_b2
);
6965 COPY_FPGM(bci_align_x_height_c
);
6967 COPY_FPGM(bci_round
);
6968 COPY_FPGM(bci_smooth_stem_width
);
6969 COPY_FPGM(bci_get_best_width
);
6970 COPY_FPGM(bci_strong_stem_width_a
);
6971 *(bufp
++) = num_used_styles
;
6972 COPY_FPGM(bci_strong_stem_width_b
);
6973 COPY_FPGM(bci_loop_do
);
6974 COPY_FPGM(bci_loop
);
6975 COPY_FPGM(bci_cvt_rescale
);
6976 COPY_FPGM(bci_cvt_rescale_range
);
6977 COPY_FPGM(bci_vwidth_data_store
);
6978 COPY_FPGM(bci_smooth_blue_round
);
6979 COPY_FPGM(bci_strong_blue_round
);
6980 COPY_FPGM(bci_blue_round_range
);
6981 COPY_FPGM(bci_decrement_component_counter
);
6982 COPY_FPGM(bci_get_point_extrema
);
6983 COPY_FPGM(bci_nibbles
);
6984 COPY_FPGM(bci_number_set_is_element
);
6985 COPY_FPGM(bci_number_set_is_element2
);
6987 COPY_FPGM(bci_create_segment
);
6988 COPY_FPGM(bci_create_segments_a
);
6989 *(bufp
++) = num_used_styles
;
6990 COPY_FPGM(bci_create_segments_b
);
6991 if (font
->control_data_head
)
6992 COPY_FPGM(bci_create_segments_c
);
6993 COPY_FPGM(bci_create_segments_d
);
6995 COPY_FPGM(bci_create_segments_0
);
6996 COPY_FPGM(bci_create_segments_1
);
6997 COPY_FPGM(bci_create_segments_2
);
6998 COPY_FPGM(bci_create_segments_3
);
6999 COPY_FPGM(bci_create_segments_4
);
7000 COPY_FPGM(bci_create_segments_5
);
7001 COPY_FPGM(bci_create_segments_6
);
7002 COPY_FPGM(bci_create_segments_7
);
7003 COPY_FPGM(bci_create_segments_8
);
7004 COPY_FPGM(bci_create_segments_9
);
7006 COPY_FPGM(bci_deltap1
);
7007 COPY_FPGM(bci_deltap2
);
7008 COPY_FPGM(bci_deltap3
);
7010 COPY_FPGM(bci_create_segments_composite_a
);
7011 *(bufp
++) = num_used_styles
;
7012 COPY_FPGM(bci_create_segments_composite_b
);
7013 if (font
->control_data_head
)
7014 COPY_FPGM(bci_create_segments_composite_c
);
7015 COPY_FPGM(bci_create_segments_composite_d
);
7017 COPY_FPGM(bci_create_segments_composite_0
);
7018 COPY_FPGM(bci_create_segments_composite_1
);
7019 COPY_FPGM(bci_create_segments_composite_2
);
7020 COPY_FPGM(bci_create_segments_composite_3
);
7021 COPY_FPGM(bci_create_segments_composite_4
);
7022 COPY_FPGM(bci_create_segments_composite_5
);
7023 COPY_FPGM(bci_create_segments_composite_6
);
7024 COPY_FPGM(bci_create_segments_composite_7
);
7025 COPY_FPGM(bci_create_segments_composite_8
);
7026 COPY_FPGM(bci_create_segments_composite_9
);
7028 COPY_FPGM(bci_align_point
);
7029 COPY_FPGM(bci_align_segment
);
7030 COPY_FPGM(bci_align_segments
);
7032 COPY_FPGM(bci_scale_contour
);
7033 COPY_FPGM(bci_scale_glyph_a
);
7034 *(bufp
++) = fallback_style
;
7035 COPY_FPGM(bci_scale_glyph_b
);
7036 COPY_FPGM(bci_scale_composite_glyph_a
);
7037 *(bufp
++) = fallback_style
;
7038 COPY_FPGM(bci_scale_composite_glyph_b
);
7039 COPY_FPGM(bci_shift_contour
);
7040 COPY_FPGM(bci_shift_subglyph_a
);
7041 *(bufp
++) = fallback_style
;
7042 COPY_FPGM(bci_shift_subglyph_b
);
7043 if (font
->control_data_head
)
7044 COPY_FPGM(bci_shift_subglyph_c
);
7045 COPY_FPGM(bci_shift_subglyph_d
);
7047 COPY_FPGM(bci_ip_outer_align_point
);
7048 COPY_FPGM(bci_ip_on_align_points
);
7049 COPY_FPGM(bci_ip_between_align_point
);
7050 COPY_FPGM(bci_ip_between_align_points
);
7052 COPY_FPGM(bci_adjust_common
);
7053 COPY_FPGM(bci_stem_common
);
7054 COPY_FPGM(bci_serif_common
);
7055 COPY_FPGM(bci_serif_anchor_common
);
7056 COPY_FPGM(bci_serif_link1_common
);
7057 COPY_FPGM(bci_serif_link2_common
);
7059 COPY_FPGM(bci_lower_bound
);
7060 COPY_FPGM(bci_upper_bound
);
7061 COPY_FPGM(bci_upper_lower_bound
);
7063 COPY_FPGM(bci_adjust_bound
);
7064 COPY_FPGM(bci_stem_bound
);
7065 COPY_FPGM(bci_link
);
7066 COPY_FPGM(bci_anchor
);
7067 COPY_FPGM(bci_adjust
);
7068 COPY_FPGM(bci_stem
);
7070 COPY_FPGM(bci_action_ip_before
);
7071 COPY_FPGM(bci_action_ip_after
);
7072 COPY_FPGM(bci_action_ip_on
);
7073 COPY_FPGM(bci_action_ip_between
);
7075 COPY_FPGM(bci_action_blue
);
7076 COPY_FPGM(bci_action_blue_anchor
);
7078 COPY_FPGM(bci_action_anchor
);
7079 COPY_FPGM(bci_action_anchor_serif
);
7080 COPY_FPGM(bci_action_anchor_round
);
7081 COPY_FPGM(bci_action_anchor_round_serif
);
7083 COPY_FPGM(bci_action_adjust
);
7084 COPY_FPGM(bci_action_adjust_serif
);
7085 COPY_FPGM(bci_action_adjust_round
);
7086 COPY_FPGM(bci_action_adjust_round_serif
);
7087 COPY_FPGM(bci_action_adjust_bound
);
7088 COPY_FPGM(bci_action_adjust_bound_serif
);
7089 COPY_FPGM(bci_action_adjust_bound_round
);
7090 COPY_FPGM(bci_action_adjust_bound_round_serif
);
7091 COPY_FPGM(bci_action_adjust_down_bound
);
7092 COPY_FPGM(bci_action_adjust_down_bound_serif
);
7093 COPY_FPGM(bci_action_adjust_down_bound_round
);
7094 COPY_FPGM(bci_action_adjust_down_bound_round_serif
);
7096 COPY_FPGM(bci_action_link
);
7097 COPY_FPGM(bci_action_link_serif
);
7098 COPY_FPGM(bci_action_link_round
);
7099 COPY_FPGM(bci_action_link_round_serif
);
7101 COPY_FPGM(bci_action_stem
);
7102 COPY_FPGM(bci_action_stem_serif
);
7103 COPY_FPGM(bci_action_stem_round
);
7104 COPY_FPGM(bci_action_stem_round_serif
);
7105 COPY_FPGM(bci_action_stem_bound
);
7106 COPY_FPGM(bci_action_stem_bound_serif
);
7107 COPY_FPGM(bci_action_stem_bound_round
);
7108 COPY_FPGM(bci_action_stem_bound_round_serif
);
7109 COPY_FPGM(bci_action_stem_down_bound
);
7110 COPY_FPGM(bci_action_stem_down_bound_serif
);
7111 COPY_FPGM(bci_action_stem_down_bound_round
);
7112 COPY_FPGM(bci_action_stem_down_bound_round_serif
);
7114 COPY_FPGM(bci_action_serif
);
7115 COPY_FPGM(bci_action_serif_lower_bound
);
7116 COPY_FPGM(bci_action_serif_upper_bound
);
7117 COPY_FPGM(bci_action_serif_upper_lower_bound
);
7118 COPY_FPGM(bci_action_serif_down_lower_bound
);
7119 COPY_FPGM(bci_action_serif_down_upper_bound
);
7120 COPY_FPGM(bci_action_serif_down_upper_lower_bound
);
7122 COPY_FPGM(bci_action_serif_anchor
);
7123 COPY_FPGM(bci_action_serif_anchor_lower_bound
);
7124 COPY_FPGM(bci_action_serif_anchor_upper_bound
);
7125 COPY_FPGM(bci_action_serif_anchor_upper_lower_bound
);
7126 COPY_FPGM(bci_action_serif_anchor_down_lower_bound
);
7127 COPY_FPGM(bci_action_serif_anchor_down_upper_bound
);
7128 COPY_FPGM(bci_action_serif_anchor_down_upper_lower_bound
);
7130 COPY_FPGM(bci_action_serif_link1
);
7131 COPY_FPGM(bci_action_serif_link1_lower_bound
);
7132 COPY_FPGM(bci_action_serif_link1_upper_bound
);
7133 COPY_FPGM(bci_action_serif_link1_upper_lower_bound
);
7134 COPY_FPGM(bci_action_serif_link1_down_lower_bound
);
7135 COPY_FPGM(bci_action_serif_link1_down_upper_bound
);
7136 COPY_FPGM(bci_action_serif_link1_down_upper_lower_bound
);
7138 COPY_FPGM(bci_action_serif_link2
);
7139 COPY_FPGM(bci_action_serif_link2_lower_bound
);
7140 COPY_FPGM(bci_action_serif_link2_upper_bound
);
7141 COPY_FPGM(bci_action_serif_link2_upper_lower_bound
);
7142 COPY_FPGM(bci_action_serif_link2_down_lower_bound
);
7143 COPY_FPGM(bci_action_serif_link2_down_upper_bound
);
7144 COPY_FPGM(bci_action_serif_link2_down_upper_lower_bound
);
7146 COPY_FPGM(bci_hint_glyph
);
7149 *fpgm_len
= buf_len
;
7156 TA_sfnt_build_fpgm_table(SFNT
* sfnt
,
7161 SFNT_Table
* glyf_table
= &font
->tables
[sfnt
->glyf_idx
];
7162 glyf_Data
* data
= (glyf_Data
*)glyf_table
->data
;
7168 error
= TA_sfnt_add_table_info(sfnt
);
7172 /* `glyf', `cvt', `fpgm', and `prep' are always used in parallel */
7173 if (glyf_table
->processed
)
7175 sfnt
->table_infos
[sfnt
->num_table_infos
- 1] = data
->fpgm_idx
;
7179 error
= TA_table_build_fpgm(&fpgm_buf
, &fpgm_len
, sfnt
, font
);
7183 if (fpgm_len
> sfnt
->max_instructions
)
7184 sfnt
->max_instructions
= (FT_UShort
)fpgm_len
;
7186 /* in case of success, `fpgm_buf' gets linked */
7187 /* and is eventually freed in `TA_font_unload' */
7188 error
= TA_font_add_table(font
,
7189 &sfnt
->table_infos
[sfnt
->num_table_infos
- 1],
7190 TTAG_fpgm
, fpgm_len
, fpgm_buf
);
7194 data
->fpgm_idx
= sfnt
->table_infos
[sfnt
->num_table_infos
- 1];
7200 /* end of tafpgm.c */