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_quantize_stem_width
322 * Take a stem width and compare it against a set of already stored stem
323 * widths. If the difference to one of the values is less than 4, replace
324 * the argument with the stored one. Otherwise add the argument to the
325 * array of stem widths, without changing the argument.
327 * We do this to catch rounding errors.
331 * out: quantized(val)
333 * sal: sal_num_stem_widths
334 * sal_stem_width_offset
337 * sal_have_cached_width
338 * sal_cached_width_offset
341 static const unsigned char FPGM(bci_quantize_stem_width
) [] =
345 bci_quantize_stem_width
,
349 ABS
, /* s: val |val| */
353 sal_stem_width_offset
,
354 sal_have_cached_width
,
356 WS
, /* sal_have_cached_width = 0 */
363 ADD
, /* sal_limit = sal_stem_width_offset + 2 * sal_num_stem_widths */
368 sal_stem_width_offset
,
370 WS
, /* sal_k = sal_stem_width_offset */
374 37, /* not_in_array jump offset */
380 EQ
, /* sal_limit == sal_k ? */
381 JROT
,/* goto not_in_array */
385 12, /* found_stem jump offset */
390 RS
, /* cur_stem_width = sal[sal_k] */
395 LT
, /* |val - cur_stem_width| < 4 ? */
396 JROT
, /* goto found_stem */
403 ADD
, /* sal_k = sal_k + 2, skipping associated cache value */
407 33, /* start_loop jump offset */
409 JMPR
, /* goto start_loop */
412 POP
, /* discard val */
416 RS
, /* val = sal[sal_k] */
418 14, /* exit jump offset */
419 sal_have_cached_width
,
421 WS
, /* sal_have_cached_width = 1 */
422 JMPR
, /* goto exit */
430 WS
, /* sal[sal_k] = val */
438 WS
, /* sal_num_stem_widths = sal_num_stem_widths + 1 */
441 SWAP
, /* s: |new_val| val */
446 NEG
, /* new_val = -new_val */
449 /* for input width array index `n' we have (or soon will have) */
450 /* a cached output width at array index `n + 1' */
452 sal_cached_width_offset
,
457 WS
, /* sal_cached_width_offset = sal_k + 1 */
465 * bci_smooth_stem_width
467 * This is the equivalent to the following code from function
468 * `ta_latin_compute_stem_width':
476 * else if base_is_round:
482 * delta = |dist - std_width|
493 * delta = delta - dist
496 * dist = dist + delta
497 * else if delta < 32:
499 * else if delta < 54:
502 * dist = dist + delta
506 * if width * base_delta > 0:
508 * bdelta = base_delta
510 * bdelta = (base_delta * (30 - ppem)) / 20
514 * dist = ROUND(dist - bdelta)
521 * If `cvtl_ignore_std_width' is set, we simply set `std_width'
524 * If `sal_have_cached_width' is set (by `bci_quantize_stem_width'), the
525 * cached value given by `sal_cached_width_offset' is directly taken, not
526 * computing the width again. Otherwise, the computed width gets stored
527 * at the given offset.
535 * sal: sal_vwidth_data_offset
537 * sal_have_cached_width
538 * sal_cached_width_offset
541 * cvtl_ignore_std_width
544 * bci_quantize_stem_width
547 static const unsigned char FPGM(bci_smooth_stem_width
) [] =
551 bci_smooth_stem_width
,
555 bci_quantize_stem_width
,
559 sal_have_cached_width
,
568 sal_cached_width_offset
,
570 RS
, /* cached_width = sal[sal_cached_width_offset] */
576 NEG
, /* cached_width = -cached_width */
581 ABS
, /* s: base_is_round stem_is_serif width dist */
586 LT
, /* dist < 3*64 */
590 MINDEX
, /* s: base_is_round width dist (dist<3*64) stem_is_serif */
591 AND
, /* stem_is_serif && dist < 3*64 */
596 sal_vwidth_data_offset
,
598 RCVT
, /* first indirection */
599 MUL
, /* divide by 64 */
600 RCVT
, /* second indirection */
603 cvtl_ignore_std_width
,
606 POP
, /* s: ... dist (stem_is_serif && dist < 3*64) 40 */
609 CINDEX
, /* standard_width = dist */
612 GT
, /* standard_width < 40 */
613 OR
, /* (stem_is_serif && dist < 3*64) || standard_width < 40 */
615 IF
, /* s: base_is_round width dist */
621 ROLL
, /* s: width dist base_is_round */
622 IF
, /* s: width dist */
627 IF
, /* s: width dist */
638 IF
, /* s: width dist */
645 DUP
, /* s: width dist dist */
648 sal_vwidth_data_offset
,
650 RCVT
, /* first indirection */
651 MUL
, /* divide by 64 */
652 RCVT
, /* second indirection */
654 ABS
, /* s: width dist delta */
659 IF
, /* s: width dist */
663 sal_vwidth_data_offset
,
665 RCVT
, /* first indirection */
666 MUL
, /* divide by 64 */
667 RCVT
, /* second indirection; dist = std_width */
679 DUP
, /* s: width dist dist */
682 LT
, /* dist < 3*64 */
684 DUP
, /* s: width delta dist */
685 FLOOR
, /* dist = FLOOR(dist) */
686 DUP
, /* s: width delta dist dist */
688 ROLL
, /* s: width dist delta dist */
689 SUB
, /* delta = delta - dist */
691 DUP
, /* s: width dist delta delta */
695 IF
, /* s: width dist delta */
696 ADD
, /* dist = dist + delta */
707 ADD
, /* dist = dist + 10 */
718 ADD
, /* dist = dist + 54 */
721 ADD
, /* dist = dist + delta */
730 CINDEX
, /* s: width dist width */
734 MUL
, /* s: width dist width*base_delta */
737 GT
, /* width * base_delta > 0 */
740 0, /* s: width dist bdelta */
750 RS
, /* bdelta = base_delta */
766 MUL
, /* (30 - ppem) in 26.6 format */
770 MUL
, /* base_delta * (30 - ppem) */
774 DIV
, /* bdelta = (base_delta * (30 - ppem)) / 20 */
778 ABS
, /* bdelta = |bdelta| */
779 SUB
, /* dist = dist - bdelta */
784 CALL
, /* dist = round(dist) */
789 SWAP
, /* s: dist width */
794 NEG
, /* dist = -dist */
801 sal_cached_width_offset
,
804 WS
, /* sal[sal_cached_width_offset] = |dist| */
815 * An auxiliary function for `bci_strong_stem_width'.
817 * in: n (initialized with CVT index for first vertical width)
829 static const unsigned char FPGM(bci_get_best_width
) [] =
837 RCVT
, /* s: dist n w */
841 CINDEX
, /* s: dist n w w dist */
843 ABS
, /* s: dist n w d */
847 RS
, /* s: dist n w d d best */
857 WS
, /* reference = w */
874 * bci_strong_stem_width
876 * This is the equivalent to the following code (function
877 * `ta_latin_snap_width' and some lines from
878 * `ta_latin_compute_stem_width'):
884 * for n in 0 .. num_widths:
892 * if dist >= reference:
893 * if dist < ROUND(reference) + 48:
896 * if dist > ROUND(reference) - 48:
908 * If `cvtl_ignore_std_width' is set, we leave `reference = width'.
911 * stem_is_serif (unused)
912 * base_is_round (unused)
918 * sal_vwidth_data_offset
921 * cvtl_ignore_std_width
923 * uses: bci_get_best_width
925 * bci_quantize_stem_width
928 static const unsigned char FPGM(bci_strong_stem_width_a
) [] =
932 bci_strong_stem_width
,
941 bci_quantize_stem_width
,
945 ABS
, /* s: width dist */
950 WS
, /* sal_best = 98 */
956 WS
, /* sal_ref = width */
959 cvtl_ignore_std_width
,
967 sal_vwidth_data_offset
,
970 MUL
, /* divide by 64; first index of vertical widths */
972 /* s: width dist vw_idx */
975 sal_vwidth_data_offset
,
981 /* %c, number of used styles */
983 static const unsigned char FPGM(bci_strong_stem_width_b
) [] =
987 RCVT
, /* number of vertical widths */
988 MUL
, /* divide by 64 */
990 /* s: width dist vw_idx loop_count */
995 POP
, /* s: width dist */
1000 RS
, /* s: width dist dist reference */
1007 CALL
, /* s: width dist reference dist dist ROUND(reference) */
1011 CINDEX
, /* s: width dist reference dist dist ROUND(reference) 48 reference */
1014 MINDEX
, /* s: width dist reference dist ROUND(reference) 48 reference dist */
1016 LTEQ
, /* reference <= dist */
1017 IF
, /* s: width dist reference dist ROUND(reference) 48 */
1019 LT
, /* dist < ROUND(reference) + 48 */
1023 GT
, /* dist > ROUND(reference) - 48 */
1027 SWAP
, /* s: width reference=new_dist dist */
1030 EIF
, /* !cvtl_ignore_std_width */
1032 DUP
, /* s: width dist dist */
1035 GTEQ
, /* dist >= 64 */
1039 CALL
, /* dist = ROUND(dist) */
1047 SWAP
, /* s: dist width */
1052 NEG
, /* dist = -dist */
1063 * An auxiliary function for `bci_loop'.
1065 * sal: sal_i (gets incremented by 2 after execution)
1068 * uses: func[sal_func]
1071 static const unsigned char FPGM(bci_loop_do
) [] =
1088 ADD
, /* sal_i = sal_i + 2 */
1099 * Take a range `start'..`end' and a function number and apply the
1100 * associated function to the range elements `start', `start+2',
1107 * sal: sal_i (counter initialized with `start')
1108 * sal_func (`func_num')
1113 static const unsigned char FPGM(bci_loop
) [] =
1123 WS
, /* sal_func = func_num */
1130 WS
, /* sal_i = start */
1136 ADD
, /* number of loops ((end - start) / 2 + 1) */
1150 * Rescale CVT value by `sal_scale' (in 16.16 format).
1152 * The scaling factor `sal_scale' isn't stored as `b/c' but as `(b-c)/c';
1153 * consequently, the calculation `a * b/c' is done as `a + delta' with
1154 * `delta = a * (b-c)/c'. This avoids overflow.
1163 static const unsigned char FPGM(bci_cvt_rescale
) [] =
1186 * bci_cvt_rescale_range
1188 * Rescale a range of CVT values with `bci_cvt_rescale', using a custom
1191 * This function gets used in the `prep' table.
1196 * sal: sal_i (CVT index of the style's scaling value;
1197 * gets incremented by 1 after execution)
1200 * uses: bci_cvt_rescale
1203 static const unsigned char FPGM(bci_cvt_rescale_range
) [] =
1207 bci_cvt_rescale_range
,
1210 /* store scaling value in `sal_scale' */
1217 WS
, /* s: cvt_start_idx num_cvt bci_cvt_rescale */
1220 /* clean up stack */
1228 ADD
, /* sal_i = sal_i + 1 */
1237 * bci_vwidth_data_store
1239 * Store a vertical width array value.
1241 * This function gets used in the `prep' table.
1245 * sal: sal_i (CVT index of the style's vwidth data;
1246 * gets incremented by 1 after execution)
1249 static const unsigned char FPGM(bci_vwidth_data_store
) [] =
1253 bci_vwidth_data_store
,
1267 ADD
, /* sal_i = sal_i + 1 */
1276 * bci_smooth_blue_round
1278 * Round a blue ref value and adjust its corresponding shoot value.
1280 * This is the equivalent to the following code (function
1281 * `ta_latin_metrics_scale_dim'):
1289 * else if delta < 48:
1299 * sal: sal_i (number of blue zones)
1306 static const unsigned char FPGM(bci_smooth_blue_round
) [] =
1310 bci_smooth_blue_round
,
1315 RCVT
, /* s: ref_idx ref_idx ref */
1321 SWAP
, /* s: ref_idx ref_idx round(ref) ref */
1329 ADD
, /* s: ref_idx ref_idx round(ref) ref shoot_idx */
1331 RCVT
, /* s: ref_idx ref_idx round(ref) ref shoot_idx shoot */
1333 ROLL
, /* s: ref_idx ref_idx round(ref) shoot_idx shoot ref */
1335 SUB
, /* s: ref_idx ref_idx round(ref) shoot_idx dist */
1337 ABS
, /* s: ref_idx ref_idx round(ref) shoot_idx dist delta */
1342 LT
, /* delta < 32 */
1351 LT
, /* delta < 48 */
1354 32, /* delta = 32 */
1358 64, /* delta = 64 */
1362 SWAP
, /* s: ref_idx ref_idx round(ref) shoot_idx delta dist */
1367 NEG
, /* delta = -delta */
1374 SUB
, /* s: ref_idx ref_idx round(ref) shoot_idx (round(ref) - delta) */
1381 ADD
, /* s: (ref_idx + 1) */
1389 * bci_strong_blue_round
1391 * Round a blue ref value and adjust its corresponding shoot value.
1393 * This is the equivalent to the following code:
1407 * It doesn't have corresponding code in talatin.c; however, some tests
1408 * have shown that the `smooth' code works just fine for this case also.
1412 * sal: sal_i (number of blue zones)
1419 static const unsigned char FPGM(bci_strong_blue_round
) [] =
1423 bci_strong_blue_round
,
1428 RCVT
, /* s: ref_idx ref_idx ref */
1434 SWAP
, /* s: ref_idx ref_idx round(ref) ref */
1442 ADD
, /* s: ref_idx ref_idx round(ref) ref shoot_idx */
1444 RCVT
, /* s: ref_idx ref_idx round(ref) ref shoot_idx shoot */
1446 ROLL
, /* s: ref_idx ref_idx round(ref) shoot_idx shoot ref */
1448 SUB
, /* s: ref_idx ref_idx round(ref) shoot_idx dist */
1450 ABS
, /* s: ref_idx ref_idx round(ref) shoot_idx dist delta */
1454 LT
, /* delta < 36 */
1457 0, /* delta = 0 (set overshoot to zero if < 0.56 pixel units) */
1461 64, /* delta = 64 (one pixel unit) */
1464 SWAP
, /* s: ref_idx ref_idx round(ref) shoot_idx delta dist */
1469 NEG
, /* delta = -delta */
1476 SUB
, /* s: ref_idx ref_idx round(ref) shoot_idx (round(ref) - delta) */
1483 ADD
, /* s: (ref_idx + 1) */
1491 * bci_blue_round_range
1493 * Round a range of blue zones (both reference and shoot values).
1495 * This function gets used in the `prep' table.
1497 * in: num_blue_zones
1500 * sal: sal_i (holds a copy of `num_blue_zones' for blue rounding function)
1502 * uses: bci_smooth_blue_round
1503 * bci_strong_blue_round
1506 static const unsigned char FPGM(bci_blue_round_range
) [] =
1510 bci_blue_round_range
,
1519 /* select blue rounding function based on flag in CVT */
1521 bci_strong_blue_round
,
1522 bci_smooth_blue_round
,
1523 cvtl_use_strong_functions
,
1534 /* clean up stack */
1543 * bci_decrement_component_counter
1545 * An auxiliary function for composite glyphs.
1547 * CVT: cvtl_is_subglyph
1550 static const unsigned char FPGM(bci_decrement_component_counter
) [] =
1554 bci_decrement_component_counter
,
1557 /* decrement `cvtl_is_subglyph' counter */
1573 * bci_get_point_extrema
1575 * An auxiliary function for `bci_create_segment'.
1581 * sal: sal_point_min
1585 static const unsigned char FPGM(bci_get_point_extrema
) [] =
1589 bci_get_point_extrema
,
1598 /* check whether `point' is a new minimum */
1601 RS
, /* s: point point point point_min */
1603 /* if distance is negative, we have a new minimum */
1607 IF
, /* s: point point */
1615 /* check whether `point' is a new maximum */
1618 RS
, /* s: point point point_max */
1620 /* if distance is positive, we have a new maximum */
1640 * Pop a byte with two delta arguments in its nibbles and push the
1641 * expanded arguments separately as two bytes.
1643 * in: 16 * (end - start) + (start - base)
1648 * sal: sal_base (set to `end' at return)
1652 static const unsigned char FPGM(bci_nibbles
) [] =
1659 PUSHB_1
, /* cf. DIV_POS_BY_2 macro */
1665 MUL
, /* s: in hnibble */
1670 MUL
, /* s: in hnibble (hnibble * 16) */
1673 SUB
, /* s: hnibble lnibble */
1678 ADD
, /* s: hnibble start */
1681 ADD
, /* s: start end */
1687 WS
, /* sal_base = end */
1697 * bci_number_set_is_element
1699 * Pop values from stack until it is empty. If one of them is equal to
1700 * the current PPEM value, set `cvtl_is_element' to 100 (and to 0
1707 * CVT: cvtl_is_element
1710 static const unsigned char FPGM(bci_number_set_is_element
) [] =
1714 bci_number_set_is_element
,
1732 JROT
, /* goto start_loop if stack depth != 0 */
1740 * bci_number_set_is_element2
1742 * Pop value ranges from stack until it is empty. If one of them contains
1743 * the current PPEM value, set `cvtl_is_element' to 100 (and to 0
1746 * in: ppem_range_1_start
1748 * ppem_range_2_start
1752 * CVT: cvtl_is_element
1755 static const unsigned char FPGM(bci_number_set_is_element2
) [] =
1759 bci_number_set_is_element2
,
1783 JROT
, /* goto start_loop if stack depth != 0 */
1791 * bci_create_segment
1793 * Store start and end point of a segment in the storage area,
1794 * then construct a point in the twilight zone to represent it.
1796 * This function is used by `bci_create_segments'.
1800 * [last (if wrap-around segment)]
1801 * [first (if wrap-around segment)]
1803 * sal: sal_i (start of current segment)
1804 * sal_j (current twilight point)
1808 * sal_num_packed_segments
1813 * uses: bci_get_point_extrema
1816 * If `sal_num_packed_segments' is > 0, the start/end pair is stored as
1817 * delta values in nibbles (without a wrap-around segment).
1820 static const unsigned char FPGM(bci_create_segment
) [] =
1829 sal_num_packed_segments
,
1834 sal_num_packed_segments
,
1835 sal_num_packed_segments
,
1840 WS
, /* sal_num_packed_segments = sal_num_packed_segments - 1 */
1853 WS
, /* sal[sal_i] = start */
1855 /* initialize inner loop(s) */
1860 WS
, /* sal_point_min = start */
1865 WS
, /* sal_point_max = start */
1869 SZPS
, /* set zp0, zp1, and zp2 to normal zone 1 */
1875 CINDEX
, /* s: start end end start */
1876 LT
, /* start > end */
1878 /* we have a wrap-around segment with two more arguments */
1879 /* to give the last and first point of the contour, respectively; */
1880 /* our job is to store a segment `start'-`last', */
1881 /* and to get extrema for the two segments */
1882 /* `start'-`last' and `first'-`end' */
1884 /* s: first last start end */
1893 WS
, /* sal[sal_i + 1] = last */
1896 ROLL
, /* s: first end last start */
1899 SWAP
, /* s: first end start last start */
1900 SUB
, /* s: first end start loop_count */
1903 bci_get_point_extrema
,
1905 /* clean up stack */
1908 SWAP
, /* s: end first */
1913 ROLL
, /* s: (first - 1) (first - 1) end */
1915 SUB
, /* s: (first - 1) loop_count */
1918 bci_get_point_extrema
,
1920 /* clean up stack */
1923 ELSE
, /* s: start end */
1932 WS
, /* sal[sal_i + 1] = end */
1937 SUB
, /* s: start loop_count */
1940 bci_get_point_extrema
,
1942 /* clean up stack */
1946 /* the twilight point representing a segment */
1947 /* is in the middle between the minimum and maximum */
1957 DIV_BY_2
, /* s: middle_pos */
1959 DO_SCALE
, /* middle_pos = middle_pos * scale */
1961 /* write it to temporary CVT location */
1965 SZP0
, /* set zp0 to twilight zone 0 */
1969 /* create twilight point with index `sal_j' */
1982 ADD
, /* twilight_point = twilight_point + 1 */
1991 * bci_create_segments
1993 * This is the top-level entry function.
1995 * It pops point ranges from the stack to define segments, computes
1996 * twilight points to represent segments, and finally calls
1997 * `bci_hint_glyph' to handle the rest.
1999 * The second argument (`data_offset') addresses three CVT arrays in
2003 * the current style's scaling value (stored in `sal_scale')
2005 * data_offset + num_used_styles:
2006 * offset to the current style's vwidth index array (this value gets
2007 * stored in `sal_vwidth_data_offset')
2009 * data_offset + 2*num_used_styles:
2010 * offset to the current style's vwidth size
2012 * This addressing scheme ensures that (a) we only need a single argument,
2013 * and (b) this argument supports up to (256-cvtl_max_runtime) styles,
2014 * which should be sufficient for a long time.
2016 * in: num_packed_segments
2021 * [contour_last 0 (if wrap-around segment)]
2022 * [contour_first 0 (if wrap-around segment)]
2025 * [contour_last 0 (if wrap-around segment)]
2026 * [contour_first 0 (if wrap-around segment)]
2028 * segment_start_(N-1)
2030 * [contour_last (N-1) (if wrap-around segment)]
2031 * [contour_first (N-1) (if wrap-around segment)]
2032 * ... stuff for bci_hint_glyph ...
2034 * sal: sal_i (start of current segment)
2035 * sal_j (current twilight point)
2036 * sal_num_packed_segments
2037 * sal_base (the base for delta values in nibbles)
2038 * sal_vwidth_data_offset
2041 * CVT: cvtl_is_subglyph
2043 * uses: bci_create_segment
2047 * If `num_packed_segments' is set to p, the first p start/end pairs are
2048 * stored as delta values in nibbles, with the `start' delta in the lower
2049 * nibble (and there are no wrap-around segments). For example, if the
2050 * first three pairs are 1/3, 5/8, and 12/13, the topmost three bytes on the
2051 * stack are 0x21, 0x32, and 0x14.
2055 static const unsigned char FPGM(bci_create_segments_a
) [] =
2059 bci_create_segments
,
2062 /* all our measurements are taken along the y axis */
2065 /* only do something if we are not a subglyph */
2073 sal_num_packed_segments
,
2080 sal_scale
, /* sal_scale = CVT(data_offset) */
2085 sal_vwidth_data_offset
,
2091 /* %c, number of used styles */
2093 static const unsigned char FPGM(bci_create_segments_b
) [] =
2097 WS
, /* sal_vwidth_data_offset = data_offset + num_used_styles */
2101 sal_stem_width_offset
,
2103 WS
, /* sal_stem_width_offset = num_segments (more to come) */
2109 SUB
, /* delta = (2*num_segments - 1) */
2119 sal_num_stem_widths
,
2121 WS
, /* sal_num_stem_widths = 0 */
2122 WS
, /* sal_base = 0 */
2123 WS
, /* sal_j = 0 (point offset) */
2126 ADD
, /* s: ... sal_segment_offset (sal_segment_offset + delta) */
2130 sal_stem_width_offset
,
2134 sal_stem_width_offset
,
2136 WS
, /* sal_stem_width_offset += sal_segment_offset + delta */
2149 /* used if we have delta exceptions */
2151 static const unsigned char FPGM(bci_create_segments_c
) [] =
2160 static const unsigned char FPGM(bci_create_segments_d
) [] =
2173 * bci_create_segments_X
2175 * Top-level routines for calling `bci_create_segments'.
2178 static const unsigned char FPGM(bci_create_segments_0
) [] =
2182 bci_create_segments_0
,
2187 bci_create_segments
,
2194 static const unsigned char FPGM(bci_create_segments_1
) [] =
2198 bci_create_segments_1
,
2203 bci_create_segments
,
2210 static const unsigned char FPGM(bci_create_segments_2
) [] =
2214 bci_create_segments_2
,
2219 bci_create_segments
,
2226 static const unsigned char FPGM(bci_create_segments_3
) [] =
2230 bci_create_segments_3
,
2235 bci_create_segments
,
2242 static const unsigned char FPGM(bci_create_segments_4
) [] =
2246 bci_create_segments_4
,
2251 bci_create_segments
,
2258 static const unsigned char FPGM(bci_create_segments_5
) [] =
2262 bci_create_segments_5
,
2267 bci_create_segments
,
2274 static const unsigned char FPGM(bci_create_segments_6
) [] =
2278 bci_create_segments_6
,
2283 bci_create_segments
,
2290 static const unsigned char FPGM(bci_create_segments_7
) [] =
2294 bci_create_segments_7
,
2299 bci_create_segments
,
2306 static const unsigned char FPGM(bci_create_segments_8
) [] =
2310 bci_create_segments_8
,
2315 bci_create_segments
,
2322 static const unsigned char FPGM(bci_create_segments_9
) [] =
2326 bci_create_segments_9
,
2331 bci_create_segments
,
2342 * Wrapper functions around DELTAP[123] that touch the affected points
2343 * before applying the delta. This is necessary for ClearType.
2345 * While DELTAP[123] implicitly do a loop, we have to process the
2346 * arguments sequentially by calling `bci_deltaX' with LOOPCALL.
2352 static const unsigned char FPGM(bci_deltap1
) [] =
2360 DUP
, /* s: point arg arg */
2361 PUSHB_1
, /* cf. DIV_POS_BY_2 macro */
2367 MUL
, /* s: point arg hnibble(arg) */
2369 CONTROL_DELTA_PPEM_MIN
,
2370 ADD
, /* s: point arg ppem(arg) */
2376 MDAP_noround
, /* touch `point' */
2380 DELTAP1
, /* process one `(point,arg)' pair */
2390 static const unsigned char FPGM(bci_deltap2
) [] =
2398 DUP
, /* s: point arg arg */
2399 PUSHB_1
, /* cf. DIV_POS_BY_2 macro */
2405 MUL
, /* s: point arg hnibble(arg) */
2407 CONTROL_DELTA_PPEM_MIN
+ 16,
2408 ADD
, /* s: point arg ppem(arg) */
2414 MDAP_noround
, /* touch `point' */
2418 DELTAP2
, /* process one `(point,arg)' pair */
2428 static const unsigned char FPGM(bci_deltap3
) [] =
2436 DUP
, /* s: point arg arg */
2437 PUSHB_1
, /* cf. DIV_POS_BY_2 macro */
2443 MUL
, /* s: point arg hnibble(arg) */
2445 CONTROL_DELTA_PPEM_MIN
+ 32,
2446 ADD
, /* s: point arg ppem(arg) */
2452 MDAP_noround
, /* touch `point' */
2456 DELTAP3
, /* process one `(point,arg)' pair */
2468 * bci_create_segments_composite
2470 * The same as `bci_create_segments'.
2471 * It also decrements the composite component counter.
2473 * sal: sal_num_packed_segments
2474 * sal_segment_offset
2475 * sal_vwidth_data_offset
2477 * CVT: cvtl_is_subglyph
2479 * uses: bci_decrement_component_counter
2480 * bci_create_segment
2485 static const unsigned char FPGM(bci_create_segments_composite_a
) [] =
2489 bci_create_segments_composite
,
2492 /* all our measurements are taken along the y axis */
2496 bci_decrement_component_counter
,
2499 /* only do something if we are not a subglyph */
2507 sal_num_packed_segments
,
2514 sal_scale
, /* sal_scale = CVT(data_offset) */
2519 sal_vwidth_data_offset
,
2525 /* %c, number of used styles */
2527 static const unsigned char FPGM(bci_create_segments_composite_b
) [] =
2531 WS
, /* sal_vwidth_data_offset = data_offset + num_used_styles */
2537 SUB
, /* delta = (2*num_segments - 1) */
2547 WS
, /* sal_base = 0 */
2548 WS
, /* sal_j = 0 (point offset) */
2551 ADD
, /* s: ... sal_segment_offset (sal_segment_offset + delta) */
2564 /* used if we have delta exceptions */
2566 static const unsigned char FPGM(bci_create_segments_composite_c
) [] =
2575 static const unsigned char FPGM(bci_create_segments_composite_d
) [] =
2588 * bci_create_segments_composite_X
2590 * Top-level routines for calling `bci_create_segments_composite'.
2593 static const unsigned char FPGM(bci_create_segments_composite_0
) [] =
2597 bci_create_segments_composite_0
,
2602 bci_create_segments_composite
,
2609 static const unsigned char FPGM(bci_create_segments_composite_1
) [] =
2613 bci_create_segments_composite_1
,
2618 bci_create_segments_composite
,
2625 static const unsigned char FPGM(bci_create_segments_composite_2
) [] =
2629 bci_create_segments_composite_2
,
2634 bci_create_segments_composite
,
2641 static const unsigned char FPGM(bci_create_segments_composite_3
) [] =
2645 bci_create_segments_composite_3
,
2650 bci_create_segments_composite
,
2657 static const unsigned char FPGM(bci_create_segments_composite_4
) [] =
2661 bci_create_segments_composite_4
,
2666 bci_create_segments_composite
,
2673 static const unsigned char FPGM(bci_create_segments_composite_5
) [] =
2677 bci_create_segments_composite_5
,
2682 bci_create_segments_composite
,
2689 static const unsigned char FPGM(bci_create_segments_composite_6
) [] =
2693 bci_create_segments_composite_6
,
2698 bci_create_segments_composite
,
2705 static const unsigned char FPGM(bci_create_segments_composite_7
) [] =
2709 bci_create_segments_composite_7
,
2714 bci_create_segments_composite
,
2721 static const unsigned char FPGM(bci_create_segments_composite_8
) [] =
2725 bci_create_segments_composite_8
,
2730 bci_create_segments_composite
,
2737 static const unsigned char FPGM(bci_create_segments_composite_9
) [] =
2741 bci_create_segments_composite_9
,
2746 bci_create_segments_composite
,
2757 * An auxiliary function for `bci_align_segment'.
2764 static const unsigned char FPGM(bci_align_point
) [] =
2772 ALIGNRP
, /* align point with rp0 */
2786 * Align all points in a segment to the twilight point in rp0.
2787 * zp0 and zp1 must be set to 0 (twilight) and 1 (normal), respectively.
2791 * sal: sal_segment_offset
2793 * uses: bci_align_point
2796 static const unsigned char FPGM(bci_align_segment
) [] =
2803 /* we need the values of `sal_segment_offset + 2*segment_index' */
2804 /* and `sal_segment_offset + 2*segment_index + 1' */
2816 RS
, /* s: first last */
2820 CINDEX
, /* s: first last first */
2824 ADD
, /* s: first loop_count */
2829 /* clean up stack */
2838 * bci_align_segments
2840 * Align segments to the twilight point in rp0.
2841 * zp0 and zp1 must be set to 0 (twilight) and 1 (normal), respectively.
2850 * uses: bci_align_segment
2853 static const unsigned char FPGM(bci_align_segments
) [] =
2876 * Scale a contour using two points giving the maximum and minimum
2879 * It expects that no point on the contour is touched.
2887 static const unsigned char FPGM(bci_scale_contour
) [] =
2898 DO_SCALE
, /* min_pos_new = min_pos * scale */
2903 /* don't scale a single-point contour twice */
2912 DO_SCALE
, /* max_pos_new = max_pos * scale */
2929 * Scale a glyph using a list of points (two points per contour, giving
2930 * the maximum and mininum coordinates).
2932 * It expects that no point in the glyph is touched.
2934 * Note that the point numbers are sorted in ascending order;
2935 * `min_point_X' and `max_point_X' thus refer to the two extrema of a
2936 * contour without specifying which one is the minimum and maximum.
2938 * in: num_contours (N)
2947 * CVT: cvtl_is_subglyph
2952 * uses: bci_scale_contour
2955 static const unsigned char FPGM(bci_scale_glyph_a
) [] =
2962 /* all our measurements are taken along the y axis */
2965 /* only do something if we are not a subglyph */
2972 /* use fallback scaling value */
2978 /* %c, fallback scaling index */
2980 static const unsigned char FPGM(bci_scale_glyph_b
) [] =
2988 SZPS
, /* set zp0, zp1, and zp2 to normal zone 1 */
2997 SZP2
, /* set zp2 to normal zone 1 */
3013 * bci_scale_composite_glyph
3015 * The same as `bci_scale_glyph'.
3016 * It also decrements the composite component counter.
3018 * CVT: cvtl_is_subglyph
3023 * uses: bci_decrement_component_counter
3027 static const unsigned char FPGM(bci_scale_composite_glyph_a
) [] =
3031 bci_scale_composite_glyph
,
3034 /* all our measurements are taken along the y axis */
3038 bci_decrement_component_counter
,
3041 /* only do something if we are not a subglyph */
3048 /* use fallback scaling value */
3054 /* %c, fallback scaling index */
3056 static const unsigned char FPGM(bci_scale_composite_glyph_b
) [] =
3064 SZPS
, /* set zp0, zp1, and zp2 to normal zone 1 */
3073 SZP2
, /* set zp2 to normal zone 1 */
3091 * Shift a contour by a given amount.
3093 * It expects that rp1 (pointed to by zp0) is set up properly; zp2 must
3094 * point to the normal zone 1.
3101 static const unsigned char FPGM(bci_shift_contour
) [] =
3109 SHC_rp1
, /* shift `contour' by (rp1_pos - rp1_orig_pos) */
3121 * bci_shift_subglyph
3123 * Shift a subglyph. To be more specific, it corrects the already applied
3124 * subglyph offset (if any) from the `glyf' table which needs to be scaled
3127 * If this function is called, a point `x' in the subglyph has been scaled
3128 * already (during the hinting of the subglyph itself), and `offset' has
3129 * been applied also:
3131 * x -> x * scale + offset (1)
3133 * However, the offset should be applied first, then the scaling:
3135 * x -> (x + offset) * scale (2)
3137 * Our job is now to transform (1) to (2); a simple calculation shows that
3138 * we have to shift all points of the subglyph by
3140 * offset * scale - offset = offset * (scale - 1)
3142 * Note that `sal_scale' is equal to the above `scale - 1'.
3144 * in: offset (in FUnits)
3148 * CVT: cvtl_funits_to_pixels
3156 static const unsigned char FPGM(bci_shift_subglyph_a
) [] =
3163 /* all our measurements are taken along the y axis */
3166 /* use fallback scaling value */
3172 /* %c, fallback scaling index */
3174 static const unsigned char FPGM(bci_shift_subglyph_b
) [] =
3181 cvtl_funits_to_pixels
,
3182 RCVT
, /* scaling factor FUnits -> pixels */
3186 /* the autohinter always rounds offsets */
3189 CALL
, /* offset = round(offset) */
3195 DIV_BY_1024
, /* delta = offset * (scale - 1) */
3197 /* and round again */
3200 CALL
, /* offset = round(offset) */
3204 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
3206 /* we create twilight point 0 as a reference point, */
3207 /* setting the original position to zero (using `cvtl_temp') */
3215 MIAP_noround
, /* rp0 and rp1 now point to twilight point 0 */
3217 SWAP
, /* s: first_contour num_contours 0 delta */
3218 SHPIX
, /* rp1_pos - rp1_orig_pos = delta */
3223 SZP2
, /* set zp2 to normal zone 1 */
3225 /* clean up stack */
3230 /* used if we have delta exceptions */
3232 static const unsigned char FPGM(bci_shift_subglyph_c
) [] =
3241 static const unsigned char FPGM(bci_shift_subglyph_d
) [] =
3250 * bci_ip_outer_align_point
3252 * Auxiliary function for `bci_action_ip_before' and
3253 * `bci_action_ip_after'.
3255 * It expects rp0 to contain the edge for alignment, zp0 set to twilight
3256 * zone, and both zp1 and zp2 set to normal zone.
3260 * sal: sal_i (edge_orig_pos)
3264 static const unsigned char FPGM(bci_ip_outer_align_point
) [] =
3268 bci_ip_outer_align_point
,
3272 ALIGNRP
, /* align `point' with `edge' */
3275 DO_SCALE
, /* point_orig_pos = point_orig_pos * scale */
3280 SUB
, /* s: point (point_orig_pos - edge_orig_pos) */
3289 * bci_ip_on_align_points
3291 * Auxiliary function for `bci_action_ip_on'.
3293 * in: edge (in twilight zone)
3301 static const unsigned char FPGM(bci_ip_on_align_points
) [] =
3305 bci_ip_on_align_points
,
3308 MDAP_noround
, /* set rp0 and rp1 to `edge' */
3319 * bci_ip_between_align_point
3321 * Auxiliary function for `bci_ip_between_align_points'.
3323 * It expects rp0 to contain the edge for alignment, zp0 set to twilight
3324 * zone, and both zp1 and zp2 set to normal zone.
3328 * sal: sal_i (edge_orig_pos)
3329 * sal_j (stretch_factor)
3333 static const unsigned char FPGM(bci_ip_between_align_point
) [] =
3337 bci_ip_between_align_point
,
3341 ALIGNRP
, /* align `point' with `edge' */
3344 DO_SCALE
, /* point_orig_pos = point_orig_pos * scale */
3349 SUB
, /* s: point (point_orig_pos - edge_orig_pos) */
3353 MUL
, /* s: point delta */
3362 * bci_ip_between_align_points
3364 * Auxiliary function for `bci_action_ip_between'.
3366 * in: after_edge (in twilight zone)
3367 * before_edge (in twilight zone)
3374 * sal: sal_i (before_orig_pos)
3375 * sal_j (stretch_factor)
3377 * uses: bci_ip_between_align_point
3380 static const unsigned char FPGM(bci_ip_between_align_points
) [] =
3384 bci_ip_between_align_points
,
3390 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
3392 DUP
, /* s: ... before after before before */
3393 MDAP_noround
, /* set rp0 and rp1 to `before' */
3395 GC_orig
, /* s: ... before after before before_orig_pos */
3399 WS
, /* sal_i = before_orig_pos */
3402 CINDEX
, /* s: ... before after before after */
3403 MD_cur
, /* a = after_pos - before_pos */
3406 MD_orig_ZP2_0
, /* b = after_orig_pos - before_orig_pos */
3412 POP
, /* avoid division by zero */
3418 WS
, /* sal_j = stretch_factor */
3421 bci_ip_between_align_point
,
3424 SZP2
, /* set zp2 to normal zone 1 */
3425 SZP1
, /* set zp1 to normal zone 1 */
3434 * bci_action_ip_before
3436 * Handle `ip_before' data to align points located before the first edge.
3438 * in: first_edge (in twilight zone)
3445 * sal: sal_i (first_edge_orig_pos)
3447 * uses: bci_ip_outer_align_point
3450 static const unsigned char FPGM(bci_action_ip_before
) [] =
3454 bci_action_ip_before
,
3459 SZP2
, /* set zp2 to twilight zone 0 */
3466 WS
, /* sal_i = first_edge_orig_pos */
3472 SZP2
, /* set zp2 to normal zone 1 */
3473 SZP1
, /* set zp1 to normal zone 1 */
3474 SZP0
, /* set zp0 to twilight zone 0 */
3476 MDAP_noround
, /* set rp0 and rp1 to `first_edge' */
3479 bci_ip_outer_align_point
,
3488 * bci_action_ip_after
3490 * Handle `ip_after' data to align points located after the last edge.
3492 * in: last_edge (in twilight zone)
3499 * sal: sal_i (last_edge_orig_pos)
3501 * uses: bci_ip_outer_align_point
3504 static const unsigned char FPGM(bci_action_ip_after
) [] =
3508 bci_action_ip_after
,
3513 SZP2
, /* set zp2 to twilight zone 0 */
3520 WS
, /* sal_i = last_edge_orig_pos */
3526 SZP2
, /* set zp2 to normal zone 1 */
3527 SZP1
, /* set zp1 to normal zone 1 */
3528 SZP0
, /* set zp0 to twilight zone 0 */
3530 MDAP_noround
, /* set rp0 and rp1 to `last_edge' */
3533 bci_ip_outer_align_point
,
3544 * Handle `ip_on' data to align points located on an edge coordinate (but
3545 * not part of an edge).
3547 * in: loop_counter (M)
3548 * edge_1 (in twilight zone)
3549 * loop_counter (N_1)
3554 * edge_2 (in twilight zone)
3555 * loop_counter (N_2)
3561 * edge_M (in twilight zone)
3562 * loop_counter (N_M)
3568 * uses: bci_ip_on_align_points
3571 static const unsigned char FPGM(bci_action_ip_on
) [] =
3581 SZP1
, /* set zp1 to normal zone 1 */
3582 SZP0
, /* set zp0 to twilight zone 0 */
3585 bci_ip_on_align_points
,
3594 * bci_action_ip_between
3596 * Handle `ip_between' data to align points located between two edges.
3598 * in: loop_counter (M)
3599 * before_edge_1 (in twilight zone)
3600 * after_edge_1 (in twilight zone)
3601 * loop_counter (N_1)
3606 * before_edge_2 (in twilight zone)
3607 * after_edge_2 (in twilight zone)
3608 * loop_counter (N_2)
3614 * before_edge_M (in twilight zone)
3615 * after_edge_M (in twilight zone)
3616 * loop_counter (N_M)
3622 * uses: bci_ip_between_align_points
3625 static const unsigned char FPGM(bci_action_ip_between
) [] =
3629 bci_action_ip_between
,
3633 bci_ip_between_align_points
,
3644 * Common code for bci_action_adjust routines.
3646 * in: top_to_bottom_hinting
3652 * out: edge (adjusted)
3654 * sal: sal_top_to_bottom_hinting
3657 * uses: func[sal_stem_width_function]
3660 static const unsigned char FPGM(bci_adjust_common
) [] =
3669 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
3671 sal_top_to_bottom_hinting
,
3677 CINDEX
, /* s: [...] edge2 edge is_round is_serif edge2 */
3680 CINDEX
, /* s: [...] edge2 edge is_round is_serif edge2 edge */
3681 MD_orig_ZP2_0
, /* s: [...] edge2 edge is_round is_serif org_len */
3684 sal_base_delta
, /* no base_delta needed here */
3689 sal_stem_width_function
,
3692 NEG
, /* s: [...] edge2 edge -cur_len */
3694 ROLL
, /* s: [...] edge -cur_len edge2 */
3695 MDAP_noround
, /* set rp0 and rp1 to `edge2' */
3698 DUP
, /* s: [...] -cur_len edge edge edge */
3699 ALIGNRP
, /* align `edge' with `edge2' */
3701 SHPIX
, /* shift `edge' by -cur_len */
3711 * Handle the ADJUST + BOUND actions to align an edge of a stem if the
3712 * other edge of the stem has already been moved, then moving it again if
3713 * necessary to stay bound.
3715 * in: top_to_bottom_hinting
3718 * edge_point (in twilight zone)
3719 * edge2_point (in twilight zone)
3720 * edge[-1] (in twilight zone)
3721 * ... stuff for bci_align_segments (edge) ...
3723 * sal: sal_top_to_bottom_hinting
3725 * uses: bci_adjust_common
3726 * bci_align_segments
3729 static const unsigned char FPGM(bci_adjust_bound
) [] =
3740 SWAP
, /* s: edge edge[-1] */
3742 MDAP_noround
, /* set rp0 and rp1 to `edge[-1]' */
3747 GC_cur
, /* s: edge edge[-1]_pos edge_pos */
3749 sal_top_to_bottom_hinting
,
3752 LT
, /* edge_pos > edge[-1]_pos */
3754 GT
, /* edge_pos < edge[-1]_pos */
3758 ALIGNRP
, /* align `edge' to `edge[-1]' */
3761 MDAP_noround
, /* set rp0 and rp1 to `edge' */
3766 SZP1
, /* set zp1 to normal zone 1 */
3775 * bci_action_adjust_bound
3776 * bci_action_adjust_bound_serif
3777 * bci_action_adjust_bound_round
3778 * bci_action_adjust_bound_round_serif
3779 * bci_action_adjust_down_bound
3780 * bci_action_adjust_down_bound_serif
3781 * bci_action_adjust_down_bound_round
3782 * bci_action_adjust_down_bound_round_serif
3784 * Higher-level routines for calling `bci_adjust_bound'.
3787 static const unsigned char FPGM(bci_action_adjust_bound
) [] =
3791 bci_action_adjust_bound
,
3805 static const unsigned char FPGM(bci_action_adjust_bound_serif
) [] =
3809 bci_action_adjust_bound_serif
,
3823 static const unsigned char FPGM(bci_action_adjust_bound_round
) [] =
3827 bci_action_adjust_bound_round
,
3841 static const unsigned char FPGM(bci_action_adjust_bound_round_serif
) [] =
3845 bci_action_adjust_bound_round_serif
,
3859 static const unsigned char FPGM(bci_action_adjust_down_bound
) [] =
3863 bci_action_adjust_down_bound
,
3877 static const unsigned char FPGM(bci_action_adjust_down_bound_serif
) [] =
3881 bci_action_adjust_down_bound_serif
,
3895 static const unsigned char FPGM(bci_action_adjust_down_bound_round
) [] =
3899 bci_action_adjust_down_bound_round
,
3913 static const unsigned char FPGM(bci_action_adjust_down_bound_round_serif
) [] =
3917 bci_action_adjust_down_bound_round_serif
,
3935 * Handle the ADJUST action to align an edge of a stem if the other edge
3936 * of the stem has already been moved.
3938 * in: edge2_is_serif
3940 * edge_point (in twilight zone)
3941 * edge2_point (in twilight zone)
3942 * ... stuff for bci_align_segments (edge) ...
3944 * uses: bci_adjust_common
3945 * bci_align_segments
3948 static const unsigned char FPGM(bci_adjust
) [] =
3960 MDAP_noround
, /* set rp0 and rp1 to `edge' */
3965 SZP1
, /* set zp1 to normal zone 1 */
3975 * bci_action_adjust_serif
3976 * bci_action_adjust_round
3977 * bci_action_adjust_round_serif
3979 * Higher-level routines for calling `bci_adjust'.
3982 static const unsigned char FPGM(bci_action_adjust
) [] =
3999 static const unsigned char FPGM(bci_action_adjust_serif
) [] =
4003 bci_action_adjust_serif
,
4016 static const unsigned char FPGM(bci_action_adjust_round
) [] =
4020 bci_action_adjust_round
,
4033 static const unsigned char FPGM(bci_action_adjust_round_serif
) [] =
4037 bci_action_adjust_round_serif
,
4054 * Common code for bci_action_stem routines.
4056 * in: top_to_bottom_hinting
4070 * sal_top_to_bottom_hinting
4073 * uses: func[sal_stem_width_function]
4078 #define sal_u_off sal_temp1
4080 #define sal_d_off sal_temp2
4082 #define sal_org_len sal_temp3
4084 #define sal_edge2 sal_temp3
4086 static const unsigned char FPGM(bci_stem_common
) [] =
4095 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
4098 sal_top_to_bottom_hinting
,
4108 DUP
, /* s: [...] edge2 edge is_round is_serif edge2 edge edge */
4109 MDAP_noround
, /* set rp0 and rp1 to `edge_point' (for ALIGNRP below) */
4111 MD_orig_ZP2_0
, /* s: [...] edge2 edge is_round is_serif org_len */
4119 sal_base_delta
, /* no base_delta needed here */
4124 sal_stem_width_function
,
4126 CALL
, /* s: [...] edge2 edge cur_len */
4131 LT
, /* cur_len < 96 */
4136 LTEQ
, /* cur_len <= 64 */
4154 SWAP
, /* s: [...] edge2 cur_len edge */
4159 DUP
, /* s: [...] edge2 cur_len edge edge anchor anchor */
4165 ADD
, /* s: [...] edge2 cur_len edge org_pos */
4170 ADD
, /* s: [...] edge2 cur_len edge org_center */
4175 CALL
, /* s: [...] edge2 cur_len edge org_center cur_pos1 */
4180 SUB
, /* s: ... cur_len edge cur_pos1 (org_center - cur_pos1) */
4187 ABS
, /* s: ... cur_len edge cur_pos1 (org_center - cur_pos1) delta1 */
4194 ABS
, /* s: [...] edge2 cur_len edge cur_pos1 delta1 delta2 */
4196 LT
, /* delta1 < delta2 */
4201 SUB
, /* cur_pos1 = cur_pos1 - u_off */
4207 ADD
, /* cur_pos1 = cur_pos1 + d_off */
4208 EIF
, /* s: [...] edge2 cur_len edge cur_pos1 */
4214 SUB
, /* arg = cur_pos1 - cur_len/2 */
4216 SWAP
, /* s: [...] edge2 cur_len arg edge */
4222 SWAP
, /* s: [...] edge2 cur_len edge edge arg edge */
4225 SHPIX
, /* edge = cur_pos1 - cur_len/2 */
4228 SWAP
, /* s: [...] edge2 cur_len edge */
4232 GC_cur
, /* s: [...] edge2 cur_len edge anchor_pos */
4240 ADD
, /* s: [...] edge2 cur_len edge org_pos */
4247 ADD
, /* s: [...] edge2 cur_len edge org_pos org_center */
4253 CALL
, /* cur_pos1 = ROUND(org_pos) */
4265 SUB
, /* s: [...] edge2 cur_len edge org_center cur_pos1 cur_pos2 */
4274 SUB
, /* s: ... cur_len edge cur_pos1 cur_pos2 (cur_len/2 - org_center) */
4281 ABS
, /* delta1 = |cur_pos1 + cur_len / 2 - org_center| */
4287 ABS
, /* s: ... edge2 cur_len edge cur_pos1 cur_pos2 delta1 delta2 */
4288 LT
, /* delta1 < delta2 */
4290 POP
, /* arg = cur_pos1 */
4294 POP
, /* arg = cur_pos2 */
4295 EIF
, /* s: [...] edge2 cur_len edge arg */
4302 SWAP
, /* s: [...] edge2 cur_len edge edge arg edge */
4305 SHPIX
, /* edge = arg */
4306 EIF
, /* s: [...] edge2 cur_len edge */
4316 * Handle the STEM action to align two edges of a stem, then moving one
4317 * edge again if necessary to stay bound.
4319 * The code after computing `cur_len' to shift `edge' and `edge2'
4320 * is equivalent to the snippet below (part of `ta_latin_hint_edges'):
4323 * if cur_len < = 64:
4330 * org_pos = anchor + (edge_orig - anchor_orig)
4331 * org_center = org_pos + org_len / 2
4333 * cur_pos1 = ROUND(org_center)
4334 * delta1 = |org_center - (cur_pos1 - u_off)|
4335 * delta2 = |org_center - (cur_pos1 + d_off)|
4336 * if (delta1 < delta2):
4337 * cur_pos1 = cur_pos1 - u_off
4339 * cur_pos1 = cur_pos1 + d_off
4341 * edge = cur_pos1 - cur_len / 2
4344 * org_pos = anchor + (edge_orig - anchor_orig)
4345 * org_center = org_pos + org_len / 2
4347 * cur_pos1 = ROUND(org_pos)
4348 * delta1 = |cur_pos1 + cur_len / 2 - org_center|
4349 * cur_pos2 = ROUND(org_pos + org_len) - cur_len
4350 * delta2 = |cur_pos2 + cur_len / 2 - org_center|
4352 * if (delta1 < delta2):
4357 * edge2 = edge + cur_len
4359 * in: top_to_bottom_hinting
4362 * edge_point (in twilight zone)
4363 * edge2_point (in twilight zone)
4364 * edge[-1] (in twilight zone)
4365 * ... stuff for bci_align_segments (edge) ...
4366 * ... stuff for bci_align_segments (edge2)...
4372 * sal_top_to_bottom_hinting
4374 * uses: bci_stem_common
4375 * bci_align_segments
4378 static const unsigned char FPGM(bci_stem_bound
) [] =
4389 ROLL
, /* s: edge[-1] cur_len edge edge2 */
4392 ALIGNRP
, /* align `edge2' with rp0 (still `edge') */
4396 WS
, /* s: edge[-1] cur_len edge edge2 */
4398 SHPIX
, /* edge2 = edge + cur_len */
4400 SWAP
, /* s: edge edge[-1] */
4402 MDAP_noround
, /* set rp0 and rp1 to `edge[-1]' */
4407 GC_cur
, /* s: edge edge[-1]_pos edge_pos */
4409 sal_top_to_bottom_hinting
,
4412 LT
, /* edge_pos > edge[-1]_pos */
4414 GT
, /* edge_pos < edge[-1]_pos */
4418 ALIGNRP
, /* align `edge' to `edge[-1]' */
4421 MDAP_noround
, /* set rp0 and rp1 to `edge' */
4426 SZP1
, /* set zp1 to normal zone 1 */
4432 MDAP_noround
, /* set rp0 and rp1 to `edge2' */
4444 * bci_action_stem_bound
4445 * bci_action_stem_bound_serif
4446 * bci_action_stem_bound_round
4447 * bci_action_stem_bound_round_serif
4448 * bci_action_stem_down_bound
4449 * bci_action_stem_down_bound_serif
4450 * bci_action_stem_down_bound_round
4451 * bci_action_stem_down_bound_round_serif
4453 * Higher-level routines for calling `bci_stem_bound'.
4456 static const unsigned char FPGM(bci_action_stem_bound
) [] =
4460 bci_action_stem_bound
,
4474 static const unsigned char FPGM(bci_action_stem_bound_serif
) [] =
4478 bci_action_stem_bound_serif
,
4492 static const unsigned char FPGM(bci_action_stem_bound_round
) [] =
4496 bci_action_stem_bound_round
,
4510 static const unsigned char FPGM(bci_action_stem_bound_round_serif
) [] =
4514 bci_action_stem_bound_round_serif
,
4528 static const unsigned char FPGM(bci_action_stem_down_bound
) [] =
4532 bci_action_stem_down_bound
,
4546 static const unsigned char FPGM(bci_action_stem_down_bound_serif
) [] =
4550 bci_action_stem_down_bound_serif
,
4564 static const unsigned char FPGM(bci_action_stem_down_bound_round
) [] =
4568 bci_action_stem_down_bound_round
,
4582 static const unsigned char FPGM(bci_action_stem_down_bound_round_serif
) [] =
4586 bci_action_stem_down_bound_round_serif
,
4604 * Handle the STEM action to align two edges of a stem.
4606 * See `bci_stem_bound' for more details.
4608 * in: edge2_is_serif
4610 * edge_point (in twilight zone)
4611 * edge2_point (in twilight zone)
4612 * ... stuff for bci_align_segments (edge) ...
4613 * ... stuff for bci_align_segments (edge2)...
4620 * uses: bci_stem_common
4621 * bci_align_segments
4624 static const unsigned char FPGM(bci_stem
) [] =
4637 SWAP
, /* s: cur_len edge2 */
4640 ALIGNRP
, /* align `edge2' with rp0 (still `edge') */
4644 WS
, /* s: cur_len edge2 */
4646 SHPIX
, /* edge2 = edge + cur_len */
4651 SZP1
, /* set zp1 to normal zone 1 */
4657 MDAP_noround
, /* set rp0 and rp1 to `edge2' */
4669 * bci_action_stem_serif
4670 * bci_action_stem_round
4671 * bci_action_stem_round_serif
4673 * Higher-level routines for calling `bci_stem'.
4676 static const unsigned char FPGM(bci_action_stem
) [] =
4693 static const unsigned char FPGM(bci_action_stem_serif
) [] =
4697 bci_action_stem_serif
,
4710 static const unsigned char FPGM(bci_action_stem_round
) [] =
4714 bci_action_stem_round
,
4727 static const unsigned char FPGM(bci_action_stem_round_serif
) [] =
4731 bci_action_stem_round_serif
,
4748 * Handle the LINK action to link an edge to another one.
4752 * base_point (in twilight zone)
4753 * stem_point (in twilight zone)
4754 * ... stuff for bci_align_segments (base) ...
4756 * sal: sal_base_delta
4758 * uses: func[sal_stem_width_function]
4759 * bci_align_segments
4762 static const unsigned char FPGM(bci_link
) [] =
4771 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
4779 DUP
, /* s: stem is_round is_serif stem base base */
4786 SUB
, /* base_delta = base_point_pos - base_point_orig_pos */
4790 WS
, /* sal_base_delta = base_delta */
4792 MDAP_noround
, /* set rp0 and rp1 to `base_point' (for ALIGNRP below) */
4794 MD_orig_ZP2_0
, /* s: stem is_round is_serif dist_orig */
4797 sal_stem_width_function
,
4799 CALL
, /* s: stem new_dist */
4803 ALIGNRP
, /* align `stem_point' with `base_point' */
4805 MDAP_noround
, /* set rp0 and rp1 to `stem_point' */
4807 SHPIX
, /* stem_point = base_point + new_dist */
4812 SZP1
, /* set zp1 to normal zone 1 */
4822 * bci_action_link_serif
4823 * bci_action_link_round
4824 * bci_action_link_round_serif
4826 * Higher-level routines for calling `bci_link'.
4829 static const unsigned char FPGM(bci_action_link
) [] =
4846 static const unsigned char FPGM(bci_action_link_serif
) [] =
4850 bci_action_link_serif
,
4863 static const unsigned char FPGM(bci_action_link_round
) [] =
4867 bci_action_link_round
,
4880 static const unsigned char FPGM(bci_action_link_round_serif
) [] =
4884 bci_action_link_round_serif
,
4901 * Handle the ANCHOR action to align two edges
4902 * and to set the edge anchor.
4904 * The code after computing `cur_len' to shift `edge' and `edge2'
4905 * is equivalent to the snippet below (part of `ta_latin_hint_edges'):
4908 * if cur_len < = 64:
4915 * org_center = edge_orig + org_len / 2
4916 * cur_pos1 = ROUND(org_center)
4918 * error1 = |org_center - (cur_pos1 - u_off)|
4919 * error2 = |org_center - (cur_pos1 + d_off)|
4920 * if (error1 < error2):
4921 * cur_pos1 = cur_pos1 - u_off
4923 * cur_pos1 = cur_pos1 + d_off
4925 * edge = cur_pos1 - cur_len / 2
4926 * edge2 = edge + cur_len
4929 * edge = ROUND(edge_orig)
4931 * in: edge2_is_serif
4933 * edge_point (in twilight zone)
4934 * edge2_point (in twilight zone)
4935 * ... stuff for bci_align_segments (edge) ...
4943 * uses: func[sal_stem_width_function]
4945 * bci_align_segments
4949 #define sal_u_off sal_temp1
4951 #define sal_d_off sal_temp2
4953 #define sal_org_len sal_temp3
4955 static const unsigned char FPGM(bci_anchor
) [] =
4962 /* store anchor point number in `sal_anchor' */
4967 WS
, /* sal_anchor = edge_point */
4971 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
4979 DUP
, /* s: edge2 edge is_round is_serif edge2 edge edge */
4980 MDAP_noround
, /* set rp0 and rp1 to `edge_point' (for ALIGNRP below) */
4982 MD_orig_ZP2_0
, /* s: edge2 edge is_round is_serif org_len */
4990 sal_base_delta
, /* no base_delta needed here */
4995 sal_stem_width_function
,
4997 CALL
, /* s: edge2 edge cur_len */
5002 LT
, /* cur_len < 96 */
5007 LTEQ
, /* cur_len <= 64 */
5025 SWAP
, /* s: edge2 cur_len edge */
5026 DUP
, /* s: edge2 cur_len edge edge */
5033 ADD
, /* s: edge2 cur_len edge org_center */
5038 CALL
, /* s: edge2 cur_len edge org_center cur_pos1 */
5043 SUB
, /* s: edge2 cur_len edge cur_pos1 (org_center - cur_pos1) */
5050 ABS
, /* s: edge2 cur_len edge cur_pos1 (org_center - cur_pos1) error1 */
5057 ABS
, /* s: edge2 cur_len edge cur_pos1 error1 error2 */
5059 LT
, /* error1 < error2 */
5064 SUB
, /* cur_pos1 = cur_pos1 - u_off */
5070 ADD
, /* cur_pos1 = cur_pos1 + d_off */
5071 EIF
, /* s: edge2 cur_len edge cur_pos1 */
5077 SUB
, /* s: edge2 cur_len edge (cur_pos1 - cur_len/2) */
5081 CINDEX
, /* s: edge2 cur_len edge (cur_pos1 - cur_len/2) edge */
5084 SHPIX
, /* edge = cur_pos1 - cur_len/2 */
5086 SWAP
, /* s: cur_len edge2 */
5088 ALIGNRP
, /* align `edge2' with rp0 (still `edge') */
5090 SHPIX
, /* edge2 = edge1 + cur_len */
5093 POP
, /* s: edge2 edge */
5101 CALL
, /* s: edge2 edge edge_pos round(edge_orig_pos) */
5104 SHPIX
, /* edge = round(edge_orig) */
5106 /* clean up stack */
5113 SZP1
, /* set zp1 to normal zone 1 */
5123 * bci_action_anchor_serif
5124 * bci_action_anchor_round
5125 * bci_action_anchor_round_serif
5127 * Higher-level routines for calling `bci_anchor'.
5130 static const unsigned char FPGM(bci_action_anchor
) [] =
5147 static const unsigned char FPGM(bci_action_anchor_serif
) [] =
5151 bci_action_anchor_serif
,
5164 static const unsigned char FPGM(bci_action_anchor_round
) [] =
5168 bci_action_anchor_round
,
5181 static const unsigned char FPGM(bci_action_anchor_round_serif
) [] =
5185 bci_action_anchor_round_serif
,
5200 * bci_action_blue_anchor
5202 * Handle the BLUE_ANCHOR action to align an edge with a blue zone
5203 * and to set the edge anchor.
5205 * in: anchor_point (in twilight zone)
5207 * edge_point (in twilight zone)
5208 * ... stuff for bci_align_segments (edge) ...
5212 * uses: bci_action_blue
5215 static const unsigned char FPGM(bci_action_blue_anchor
) [] =
5219 bci_action_blue_anchor
,
5222 /* store anchor point number in `sal_anchor' */
5240 * Handle the BLUE action to align an edge with a blue zone.
5243 * edge_point (in twilight zone)
5244 * ... stuff for bci_align_segments (edge) ...
5246 * uses: bci_align_segments
5249 static const unsigned char FPGM(bci_action_blue
) [] =
5258 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
5260 /* move `edge_point' to `blue_cvt_idx' position; */
5261 /* note that we can't use MIAP since this would modify */
5262 /* the twilight point's original coordinates also */
5266 MDAP_noround
, /* set rp0 and rp1 to `edge' */
5268 GC_cur
, /* s: new_pos edge edge_pos */
5271 SUB
, /* s: edge (new_pos - edge_pos) */
5277 SZP1
, /* set zp1 to normal zone 1 */
5288 * Common code for bci_action_serif routines.
5290 * in: top_to_bottom_hinting
5294 * sal: sal_top_to_bottom_hinting
5298 static const unsigned char FPGM(bci_serif_common
) [] =
5307 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
5310 sal_top_to_bottom_hinting
,
5319 MINDEX
, /* s: [...] serif serif serif serif base */
5321 MDAP_noround
, /* set rp0 and rp1 to `base_point' */
5324 ALIGNRP
, /* align `serif_point' with `base_point' */
5325 SHPIX
, /* serif = base + (serif_orig_pos - base_orig_pos) */
5335 * Move an edge if necessary to stay within a lower bound.
5340 * sal: sal_top_to_bottom_hinting
5342 * uses: bci_align_segments
5345 static const unsigned char FPGM(bci_lower_bound
) [] =
5352 SWAP
, /* s: edge bound */
5354 MDAP_noround
, /* set rp0 and rp1 to `bound' */
5359 GC_cur
, /* s: edge bound_pos edge_pos */
5361 sal_top_to_bottom_hinting
,
5364 LT
, /* edge_pos > bound_pos */
5366 GT
, /* edge_pos < bound_pos */
5370 ALIGNRP
, /* align `edge' to `bound' */
5373 MDAP_noround
, /* set rp0 and rp1 to `edge_point' */
5378 SZP1
, /* set zp1 to normal zone 1 */
5389 * Move an edge if necessary to stay within an upper bound.
5394 * sal: sal_top_to_bottom_hinting
5396 * uses: bci_align_segments
5399 static const unsigned char FPGM(bci_upper_bound
) [] =
5406 SWAP
, /* s: edge bound */
5408 MDAP_noround
, /* set rp0 and rp1 to `bound' */
5413 GC_cur
, /* s: edge bound_pos edge_pos */
5415 sal_top_to_bottom_hinting
,
5418 GT
, /* edge_pos < bound_pos */
5420 LT
, /* edge_pos > bound_pos */
5424 ALIGNRP
, /* align `edge' to `bound' */
5427 MDAP_noround
, /* set rp0 and rp1 to `edge_point' */
5432 SZP1
, /* set zp1 to normal zone 1 */
5441 * bci_upper_lower_bound
5443 * Move an edge if necessary to stay within a lower and lower bound.
5449 * sal: sal_top_to_bottom_hinting
5451 * uses: bci_align_segments
5454 static const unsigned char FPGM(bci_upper_lower_bound
) [] =
5458 bci_upper_lower_bound
,
5461 SWAP
, /* s: upper serif lower */
5463 MDAP_noround
, /* set rp0 and rp1 to `lower' */
5468 GC_cur
, /* s: upper serif lower_pos serif_pos */
5470 sal_top_to_bottom_hinting
,
5473 LT
, /* serif_pos > lower_pos */
5475 GT
, /* serif_pos < lower_pos */
5479 ALIGNRP
, /* align `serif' to `lower' */
5482 SWAP
, /* s: serif upper */
5484 MDAP_noround
, /* set rp0 and rp1 to `upper' */
5489 GC_cur
, /* s: serif upper_pos serif_pos */
5491 sal_top_to_bottom_hinting
,
5494 GT
, /* serif_pos < upper_pos */
5496 LT
, /* serif_pos > upper_pos */
5500 ALIGNRP
, /* align `serif' to `upper' */
5503 MDAP_noround
, /* set rp0 and rp1 to `serif_point' */
5508 SZP1
, /* set zp1 to normal zone 1 */
5519 * Handle the SERIF action to align a serif with its base.
5521 * in: serif_point (in twilight zone)
5522 * base_point (in twilight zone)
5523 * ... stuff for bci_align_segments (serif) ...
5525 * uses: bci_serif_common
5526 * bci_align_segments
5529 static const unsigned char FPGM(bci_action_serif
) [] =
5541 MDAP_noround
, /* set rp0 and rp1 to `serif_point' */
5546 SZP1
, /* set zp1 to normal zone 1 */
5555 * bci_action_serif_lower_bound
5557 * Handle the SERIF action to align a serif with its base, then moving it
5558 * again if necessary to stay within a lower bound.
5560 * in: serif_point (in twilight zone)
5561 * base_point (in twilight zone)
5562 * edge[-1] (in twilight zone)
5563 * ... stuff for bci_align_segments (serif) ...
5565 * uses: bci_serif_common
5569 static const unsigned char FPGM(bci_action_serif_lower_bound
) [] =
5573 bci_action_serif_lower_bound
,
5591 * bci_action_serif_upper_bound
5593 * Handle the SERIF action to align a serif with its base, then moving it
5594 * again if necessary to stay within an upper bound.
5596 * in: serif_point (in twilight zone)
5597 * base_point (in twilight zone)
5598 * edge[1] (in twilight zone)
5599 * ... stuff for bci_align_segments (serif) ...
5601 * uses: bci_serif_common
5605 static const unsigned char FPGM(bci_action_serif_upper_bound
) [] =
5609 bci_action_serif_upper_bound
,
5627 * bci_action_serif_upper_lower_bound
5629 * Handle the SERIF action to align a serif with its base, then moving it
5630 * again if necessary to stay within a lower and upper bound.
5632 * in: serif_point (in twilight zone)
5633 * base_point (in twilight zone)
5634 * edge[-1] (in twilight zone)
5635 * edge[1] (in twilight zone)
5636 * ... stuff for bci_align_segments (serif) ...
5638 * uses: bci_serif_common
5639 * bci_upper_lower_bound
5642 static const unsigned char FPGM(bci_action_serif_upper_lower_bound
) [] =
5646 bci_action_serif_upper_lower_bound
,
5651 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
5659 bci_upper_lower_bound
,
5668 * bci_action_serif_down_lower_bound
5670 * Handle the SERIF action to align a serif with its base, then moving it
5671 * again if necessary to stay within a lower bound. We hint top to
5674 * in: serif_point (in twilight zone)
5675 * base_point (in twilight zone)
5676 * edge[-1] (in twilight zone)
5677 * ... stuff for bci_align_segments (serif) ...
5679 * uses: bci_serif_common
5683 static const unsigned char FPGM(bci_action_serif_down_lower_bound
) [] =
5687 bci_action_serif_down_lower_bound
,
5705 * bci_action_serif_down_upper_bound
5707 * Handle the SERIF action to align a serif with its base, then moving it
5708 * again if necessary to stay within an upper bound. We hint top to
5711 * in: serif_point (in twilight zone)
5712 * base_point (in twilight zone)
5713 * edge[1] (in twilight zone)
5714 * ... stuff for bci_align_segments (serif) ...
5716 * uses: bci_serif_common
5720 static const unsigned char FPGM(bci_action_serif_down_upper_bound
) [] =
5724 bci_action_serif_down_upper_bound
,
5742 * bci_action_serif_down_upper_lower_bound
5744 * Handle the SERIF action to align a serif with its base, then moving it
5745 * again if necessary to stay within a lower and upper bound. We hint top
5748 * in: serif_point (in twilight zone)
5749 * base_point (in twilight zone)
5750 * edge[-1] (in twilight zone)
5751 * edge[1] (in twilight zone)
5752 * ... stuff for bci_align_segments (serif) ...
5754 * uses: bci_serif_common
5755 * bci_upper_lower_bound
5758 static const unsigned char FPGM(bci_action_serif_down_upper_lower_bound
) [] =
5762 bci_action_serif_down_upper_lower_bound
,
5767 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
5775 bci_upper_lower_bound
,
5784 * bci_serif_anchor_common
5786 * Common code for bci_action_serif_anchor routines.
5788 * in: top_to_bottom_hinting
5791 * out: edge (adjusted)
5794 * sal_top_to_bottom_hinting
5799 static const unsigned char FPGM(bci_serif_anchor_common
) [] =
5803 bci_serif_anchor_common
,
5808 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
5811 sal_top_to_bottom_hinting
,
5819 WS
, /* sal_anchor = edge_point */
5829 CALL
, /* s: [...] edge edge edge_pos round(edge_orig_pos) */
5832 SHPIX
, /* edge = round(edge_orig) */
5840 * bci_action_serif_anchor
5842 * Handle the SERIF_ANCHOR action to align a serif and to set the edge
5845 * in: edge_point (in twilight zone)
5846 * ... stuff for bci_align_segments (edge) ...
5848 * uses: bci_serif_anchor_common
5849 * bci_align_segments
5852 static const unsigned char FPGM(bci_action_serif_anchor
) [] =
5856 bci_action_serif_anchor
,
5861 bci_serif_anchor_common
,
5864 MDAP_noround
, /* set rp0 and rp1 to `edge' */
5869 SZP1
, /* set zp1 to normal zone 1 */
5878 * bci_action_serif_anchor_lower_bound
5880 * Handle the SERIF_ANCHOR action to align a serif and to set the edge
5881 * anchor, then moving it again if necessary to stay within a lower
5884 * in: edge_point (in twilight zone)
5885 * edge[-1] (in twilight zone)
5886 * ... stuff for bci_align_segments (edge) ...
5888 * uses: bci_serif_anchor_common
5892 static const unsigned char FPGM(bci_action_serif_anchor_lower_bound
) [] =
5896 bci_action_serif_anchor_lower_bound
,
5901 bci_serif_anchor_common
,
5914 * bci_action_serif_anchor_upper_bound
5916 * Handle the SERIF_ANCHOR action to align a serif and to set the edge
5917 * anchor, then moving it again if necessary to stay within an upper
5920 * in: edge_point (in twilight zone)
5921 * edge[1] (in twilight zone)
5922 * ... stuff for bci_align_segments (edge) ...
5924 * uses: bci_serif_anchor_common
5928 static const unsigned char FPGM(bci_action_serif_anchor_upper_bound
) [] =
5932 bci_action_serif_anchor_upper_bound
,
5937 bci_serif_anchor_common
,
5950 * bci_action_serif_anchor_upper_lower_bound
5952 * Handle the SERIF_ANCHOR action to align a serif and to set the edge
5953 * anchor, then moving it again if necessary to stay within a lower and
5956 * in: edge_point (in twilight zone)
5957 * edge[-1] (in twilight zone)
5958 * edge[1] (in twilight zone)
5959 * ... stuff for bci_align_segments (edge) ...
5961 * uses: bci_serif_anchor_common
5962 * bci_upper_lower_bound
5965 static const unsigned char FPGM(bci_action_serif_anchor_upper_lower_bound
) [] =
5969 bci_action_serif_anchor_upper_lower_bound
,
5974 bci_serif_anchor_common
,
5978 bci_upper_lower_bound
,
5987 * bci_action_serif_anchor_down_lower_bound
5989 * Handle the SERIF_ANCHOR action to align a serif and to set the edge
5990 * anchor, then moving it again if necessary to stay within a lower
5991 * bound. We hint top to bottom.
5993 * in: edge_point (in twilight zone)
5994 * edge[-1] (in twilight zone)
5995 * ... stuff for bci_align_segments (edge) ...
5997 * uses: bci_serif_anchor_common
6001 static const unsigned char FPGM(bci_action_serif_anchor_down_lower_bound
) [] =
6005 bci_action_serif_anchor_down_lower_bound
,
6010 bci_serif_anchor_common
,
6023 * bci_action_serif_anchor_down_upper_bound
6025 * Handle the SERIF_ANCHOR action to align a serif and to set the edge
6026 * anchor, then moving it again if necessary to stay within an upper
6027 * bound. We hint top to bottom.
6029 * in: edge_point (in twilight zone)
6030 * edge[1] (in twilight zone)
6031 * ... stuff for bci_align_segments (edge) ...
6033 * uses: bci_serif_anchor_common
6037 static const unsigned char FPGM(bci_action_serif_anchor_down_upper_bound
) [] =
6041 bci_action_serif_anchor_down_upper_bound
,
6046 bci_serif_anchor_common
,
6059 * bci_action_serif_anchor_down_upper_lower_bound
6061 * Handle the SERIF_ANCHOR action to align a serif and to set the edge
6062 * anchor, then moving it again if necessary to stay within a lower and
6063 * upper bound. We hint top to bottom.
6065 * in: edge_point (in twilight zone)
6066 * edge[-1] (in twilight zone)
6067 * edge[1] (in twilight zone)
6068 * ... stuff for bci_align_segments (edge) ...
6070 * uses: bci_serif_anchor_common
6071 * bci_upper_lower_bound
6074 static const unsigned char FPGM(bci_action_serif_anchor_down_upper_lower_bound
) [] =
6078 bci_action_serif_anchor_down_upper_lower_bound
,
6083 bci_serif_anchor_common
,
6087 bci_upper_lower_bound
,
6096 * bci_serif_link1_common
6098 * Common code for bci_action_serif_link1 routines.
6100 * in: top_to_bottom_hinting
6105 * out: edge (adjusted)
6107 * sal: sal_top_to_bottom_hinting
6111 static const unsigned char FPGM(bci_serif_link1_common
) [] =
6115 bci_serif_link1_common
,
6120 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
6123 sal_top_to_bottom_hinting
,
6129 CINDEX
, /* s: [...] after edge before after */
6132 CINDEX
, /* s: [...] after edge before after before */
6136 EQ
, /* after_orig_pos == before_orig_pos */
6137 IF
, /* s: [...] after edge before */
6138 MDAP_noround
, /* set rp0 and rp1 to `before' */
6140 ALIGNRP
, /* align `edge' with `before' */
6145 /* we have to execute `a*b/c', with b/c very near to 1: */
6146 /* to avoid overflow while retaining precision, */
6147 /* we transform this to `a + a * (b-c)/c' */
6151 CINDEX
, /* s: [...] after edge before edge */
6154 CINDEX
, /* s: [...] after edge before edge before */
6155 MD_orig_ZP2_0
, /* a = edge_orig_pos - before_orig_pos */
6160 CINDEX
, /* s: [...] after edge before a a after */
6163 CINDEX
, /* s: [...] after edge before a a after before */
6164 MD_orig_ZP2_0
, /* c = after_orig_pos - before_orig_pos */
6168 CINDEX
, /* s: [...] after edge before a a c after */
6171 CINDEX
, /* s: [...] after edge before a a c after before */
6172 MD_cur
, /* b = after_pos - before_pos */
6176 CINDEX
, /* s: [...] after edge before a a c b c */
6185 MUL
, /* (b-c) in 16.16 format */
6190 DIV
, /* s: [...] after edge before a a (b-c)/c */
6192 POP
, /* avoid division by zero */
6195 MUL
, /* a * (b-c)/c * 2^10 */
6196 DIV_BY_1024
, /* a * (b-c)/c */
6200 MDAP_noround
, /* set rp0 and rp1 to `before' */
6201 SWAP
, /* s: [...] after a*b/c edge */
6204 ALIGNRP
, /* align `edge' with `before' */
6206 SHPIX
, /* shift `edge' by `a*b/c' */
6208 SWAP
, /* s: [...] edge after */
6218 * bci_action_serif_link1
6220 * Handle the SERIF_LINK1 action to align a serif, depending on edges
6223 * in: before_point (in twilight zone)
6224 * edge_point (in twilight zone)
6225 * after_point (in twilight zone)
6226 * ... stuff for bci_align_segments (edge) ...
6228 * uses: bci_serif_link1_common
6229 * bci_align_segments
6232 static const unsigned char FPGM(bci_action_serif_link1
) [] =
6236 bci_action_serif_link1
,
6241 bci_serif_link1_common
,
6244 MDAP_noround
, /* set rp0 and rp1 to `edge' */
6249 SZP1
, /* set zp1 to normal zone 1 */
6258 * bci_action_serif_link1_lower_bound
6260 * Handle the SERIF_LINK1 action to align a serif, depending on edges
6261 * before and after. Additionally, move the serif again if necessary to
6262 * stay within a lower bound.
6264 * in: before_point (in twilight zone)
6265 * edge_point (in twilight zone)
6266 * after_point (in twilight zone)
6267 * edge[-1] (in twilight zone)
6268 * ... stuff for bci_align_segments (edge) ...
6270 * uses: bci_serif_link1_common
6274 static const unsigned char FPGM(bci_action_serif_link1_lower_bound
) [] =
6278 bci_action_serif_link1_lower_bound
,
6283 bci_serif_link1_common
,
6296 * bci_action_serif_link1_upper_bound
6298 * Handle the SERIF_LINK1 action to align a serif, depending on edges
6299 * before and after. Additionally, move the serif again if necessary to
6300 * stay within an upper bound.
6302 * in: before_point (in twilight zone)
6303 * edge_point (in twilight zone)
6304 * after_point (in twilight zone)
6305 * edge[1] (in twilight zone)
6306 * ... stuff for bci_align_segments (edge) ...
6308 * uses: bci_serif_link1_common
6312 static const unsigned char FPGM(bci_action_serif_link1_upper_bound
) [] =
6316 bci_action_serif_link1_upper_bound
,
6321 bci_serif_link1_common
,
6334 * bci_action_serif_link1_upper_lower_bound
6336 * Handle the SERIF_LINK1 action to align a serif, depending on edges
6337 * before and after. Additionally, move the serif again if necessary to
6338 * stay within a lower and upper bound.
6340 * in: before_point (in twilight zone)
6341 * edge_point (in twilight zone)
6342 * after_point (in twilight zone)
6343 * edge[-1] (in twilight zone)
6344 * edge[1] (in twilight zone)
6345 * ... stuff for bci_align_segments (edge) ...
6347 * uses: bci_serif_link1_common
6348 * bci_upper_lower_bound
6351 static const unsigned char FPGM(bci_action_serif_link1_upper_lower_bound
) [] =
6355 bci_action_serif_link1_upper_lower_bound
,
6360 bci_serif_link1_common
,
6364 bci_upper_lower_bound
,
6373 * bci_action_serif_link1_down_lower_bound
6375 * Handle the SERIF_LINK1 action to align a serif, depending on edges
6376 * before and after. Additionally, move the serif again if necessary to
6377 * stay within a lower bound. We hint top to bottom.
6379 * in: before_point (in twilight zone)
6380 * edge_point (in twilight zone)
6381 * after_point (in twilight zone)
6382 * edge[-1] (in twilight zone)
6383 * ... stuff for bci_align_segments (edge) ...
6385 * uses: bci_serif_link1_common
6389 static const unsigned char FPGM(bci_action_serif_link1_down_lower_bound
) [] =
6393 bci_action_serif_link1_down_lower_bound
,
6398 bci_serif_link1_common
,
6411 * bci_action_serif_link1_down_upper_bound
6413 * Handle the SERIF_LINK1 action to align a serif, depending on edges
6414 * before and after. Additionally, move the serif again if necessary to
6415 * stay within an upper bound. We hint top to bottom.
6417 * in: before_point (in twilight zone)
6418 * edge_point (in twilight zone)
6419 * after_point (in twilight zone)
6420 * edge[1] (in twilight zone)
6421 * ... stuff for bci_align_segments (edge) ...
6423 * uses: bci_serif_link1_common
6427 static const unsigned char FPGM(bci_action_serif_link1_down_upper_bound
) [] =
6431 bci_action_serif_link1_down_upper_bound
,
6436 bci_serif_link1_common
,
6449 * bci_action_serif_link1_down_upper_lower_bound
6451 * Handle the SERIF_LINK1 action to align a serif, depending on edges
6452 * before and after. Additionally, move the serif again if necessary to
6453 * stay within a lower and upper bound. We hint top to bottom.
6455 * in: before_point (in twilight zone)
6456 * edge_point (in twilight zone)
6457 * after_point (in twilight zone)
6458 * edge[-1] (in twilight zone)
6459 * edge[1] (in twilight zone)
6460 * ... stuff for bci_align_segments (edge) ...
6462 * uses: bci_serif_link1_common
6463 * bci_upper_lower_bound
6466 static const unsigned char FPGM(bci_action_serif_link1_down_upper_lower_bound
) [] =
6470 bci_action_serif_link1_down_upper_lower_bound
,
6475 bci_serif_link1_common
,
6479 bci_upper_lower_bound
,
6488 * bci_serif_link2_common
6490 * Common code for bci_action_serif_link2 routines.
6492 * in: top_to_bottom_hinting
6495 * out: edge (adjusted)
6498 * sal_top_to_bottom_hinting
6502 static const unsigned char FPGM(bci_serif_link2_common
) [] =
6506 bci_serif_link2_common
,
6511 SZPS
, /* set zp0, zp1, and zp2 to twilight zone 0 */
6514 sal_top_to_bottom_hinting
,
6518 DUP
, /* s: [...] edge edge */
6522 DUP
, /* s: [...] edge edge anchor anchor */
6523 MDAP_noround
, /* set rp0 and rp1 to `sal_anchor' */
6532 DIV_BY_2
, /* delta = (edge_orig_pos - anchor_orig_pos + 16) & ~31 */
6537 ALIGNRP
, /* align `edge' with `sal_anchor' */
6539 SHPIX
, /* shift `edge' by `delta' */
6547 * bci_action_serif_link2
6549 * Handle the SERIF_LINK2 action to align a serif relative to the anchor.
6551 * in: edge_point (in twilight zone)
6552 * ... stuff for bci_align_segments (edge) ...
6554 * uses: bci_serif_link2_common
6555 * bci_align_segments
6558 static const unsigned char FPGM(bci_action_serif_link2
) [] =
6562 bci_action_serif_link2
,
6567 bci_serif_link2_common
,
6570 MDAP_noround
, /* set rp0 and rp1 to `edge' */
6575 SZP1
, /* set zp1 to normal zone 1 */
6584 * bci_action_serif_link2_lower_bound
6586 * Handle the SERIF_LINK2 action to align a serif relative to the anchor.
6587 * Additionally, move the serif again if necessary to stay within a lower
6590 * in: edge_point (in twilight zone)
6591 * edge[-1] (in twilight zone)
6592 * ... stuff for bci_align_segments (edge) ...
6594 * uses: bci_serif_link2_common
6598 static const unsigned char FPGM(bci_action_serif_link2_lower_bound
) [] =
6602 bci_action_serif_link2_lower_bound
,
6607 bci_serif_link2_common
,
6620 * bci_action_serif_link2_upper_bound
6622 * Handle the SERIF_LINK2 action to align a serif relative to the anchor.
6623 * Additionally, move the serif again if necessary to stay within an upper
6626 * in: edge_point (in twilight zone)
6627 * edge[1] (in twilight zone)
6628 * ... stuff for bci_align_segments (edge) ...
6630 * uses: bci_serif_link2_common
6634 static const unsigned char FPGM(bci_action_serif_link2_upper_bound
) [] =
6638 bci_action_serif_link2_upper_bound
,
6643 bci_serif_link2_common
,
6656 * bci_action_serif_link2_upper_lower_bound
6658 * Handle the SERIF_LINK2 action to align a serif relative to the anchor.
6659 * Additionally, move the serif again if necessary to stay within a lower
6662 * in: edge_point (in twilight zone)
6663 * edge[-1] (in twilight zone)
6664 * edge[1] (in twilight zone)
6665 * ... stuff for bci_align_segments (edge) ...
6667 * uses: bci_serif_link2_common
6668 * bci_upper_lower_bound
6671 static const unsigned char FPGM(bci_action_serif_link2_upper_lower_bound
) [] =
6675 bci_action_serif_link2_upper_lower_bound
,
6680 bci_serif_link2_common
,
6684 bci_upper_lower_bound
,
6693 * bci_action_serif_link2_down_lower_bound
6695 * Handle the SERIF_LINK2 action to align a serif relative to the anchor.
6696 * Additionally, move the serif again if necessary to stay within a lower
6697 * bound. We hint top to bottom.
6699 * in: edge_point (in twilight zone)
6700 * edge[-1] (in twilight zone)
6701 * ... stuff for bci_align_segments (edge) ...
6703 * uses: bci_serif_link2_common
6707 static const unsigned char FPGM(bci_action_serif_link2_down_lower_bound
) [] =
6711 bci_action_serif_link2_down_lower_bound
,
6716 bci_serif_link2_common
,
6729 * bci_action_serif_link2_down_upper_bound
6731 * Handle the SERIF_LINK2 action to align a serif relative to the anchor.
6732 * Additionally, move the serif again if necessary to stay within an upper
6733 * bound. We hint top to bottom.
6735 * in: edge_point (in twilight zone)
6736 * edge[1] (in twilight zone)
6737 * ... stuff for bci_align_segments (edge) ...
6739 * uses: bci_serif_link2_common
6743 static const unsigned char FPGM(bci_action_serif_link2_down_upper_bound
) [] =
6747 bci_action_serif_link2_down_upper_bound
,
6752 bci_serif_link2_common
,
6765 * bci_action_serif_link2_down_upper_lower_bound
6767 * Handle the SERIF_LINK2 action to align a serif relative to the anchor.
6768 * Additionally, move the serif again if necessary to stay within a lower
6769 * and upper bound. We hint top to bottom.
6771 * in: edge_point (in twilight zone)
6772 * edge[-1] (in twilight zone)
6773 * edge[1] (in twilight zone)
6774 * ... stuff for bci_align_segments (edge) ...
6776 * uses: bci_serif_link2_common
6777 * bci_upper_lower_bound
6780 static const unsigned char FPGM(bci_action_serif_link2_down_upper_lower_bound
) [] =
6784 bci_action_serif_link2_down_upper_lower_bound
,
6789 bci_serif_link2_common
,
6793 bci_upper_lower_bound
,
6804 * This is the top-level glyph hinting function which parses the arguments
6805 * on the stack and calls subroutines.
6807 * in: action_0_func_idx
6813 * CVT: cvtl_is_subglyph
6814 * cvtl_use_strong_functions
6817 * sal: sal_stem_width_function
6819 * uses: bci_action_ip_before
6820 * bci_action_ip_after
6822 * bci_action_ip_between
6824 * bci_action_adjust_bound
6825 * bci_action_adjust_bound_serif
6826 * bci_action_adjust_bound_round
6827 * bci_action_adjust_bound_round_serif
6829 * bci_action_stem_bound
6830 * bci_action_stem_bound_serif
6831 * bci_action_stem_bound_round
6832 * bci_action_stem_bound_round_serif
6835 * bci_action_link_serif
6836 * bci_action_link_round
6837 * bci_action_link_round_serif
6840 * bci_action_anchor_serif
6841 * bci_action_anchor_round
6842 * bci_action_anchor_round_serif
6844 * bci_action_blue_anchor
6847 * bci_action_adjust_serif
6848 * bci_action_adjust_round
6849 * bci_action_adjust_round_serif
6852 * bci_action_stem_serif
6853 * bci_action_stem_round
6854 * bci_action_stem_round_serif
6859 * bci_action_serif_lower_bound
6860 * bci_action_serif_upper_bound
6861 * bci_action_serif_upper_lower_bound
6863 * bci_action_serif_anchor
6864 * bci_action_serif_anchor_lower_bound
6865 * bci_action_serif_anchor_upper_bound
6866 * bci_action_serif_anchor_upper_lower_bound
6868 * bci_action_serif_link1
6869 * bci_action_serif_link1_lower_bound
6870 * bci_action_serif_link1_upper_bound
6871 * bci_action_serif_link1_upper_lower_bound
6873 * bci_action_serif_link2
6874 * bci_action_serif_link2_lower_bound
6875 * bci_action_serif_link2_upper_bound
6876 * bci_action_serif_link2_upper_lower_bound
6879 static const unsigned char FPGM(bci_hint_glyph
) [] =
6886 /* set up stem width function based on flag in CVT */
6888 sal_stem_width_function
,
6889 bci_strong_stem_width
,
6890 bci_smooth_stem_width
,
6891 cvtl_use_strong_functions
,
6904 /* loop until all data on stack is used */
6913 JROT
, /* goto start_loop */
6918 SZP2
, /* set zp2 to normal zone 1 */
6929 #define COPY_FPGM(func_name) \
6932 memcpy(bufp, fpgm_ ## func_name, \
6933 sizeof (fpgm_ ## func_name)); \
6934 bufp += sizeof (fpgm_ ## func_name); \
6938 TA_table_build_fpgm(FT_Byte
** fpgm
,
6943 SFNT_Table
* glyf_table
= &font
->tables
[sfnt
->glyf_idx
];
6944 glyf_Data
* data
= (glyf_Data
*)glyf_table
->data
;
6946 unsigned char num_used_styles
= (unsigned char)data
->num_used_styles
;
6947 unsigned char fallback_style
=
6948 CVT_SCALING_VALUE_OFFSET(0)
6949 + (unsigned char)data
->style_ids
[font
->fallback_style
];
6957 /* for compatibility with dumb bytecode interpreters or analyzers, */
6958 /* FDEFs are stored in ascending index order, without holes -- */
6959 /* note that some FDEFs are not always needed */
6960 /* (depending on options of `TTFautohint'), */
6961 /* but implementing dynamic FDEF indices would be a lot of work */
6963 buf_len
= sizeof (FPGM(bci_align_x_height_a
))
6964 + (font
->increase_x_height
6965 ? (sizeof (FPGM(bci_align_x_height_b1a
))
6967 + sizeof (FPGM(bci_align_x_height_b1b
)))
6968 : sizeof (FPGM(bci_align_x_height_b2
)))
6969 + sizeof (FPGM(bci_align_x_height_c
))
6970 + sizeof (FPGM(bci_round
))
6971 + sizeof (FPGM(bci_quantize_stem_width
))
6972 + sizeof (FPGM(bci_smooth_stem_width
))
6973 + sizeof (FPGM(bci_get_best_width
))
6974 + sizeof (FPGM(bci_strong_stem_width_a
))
6976 + sizeof (FPGM(bci_strong_stem_width_b
))
6977 + sizeof (FPGM(bci_loop_do
))
6978 + sizeof (FPGM(bci_loop
))
6979 + sizeof (FPGM(bci_cvt_rescale
))
6980 + sizeof (FPGM(bci_cvt_rescale_range
))
6981 + sizeof (FPGM(bci_vwidth_data_store
))
6982 + sizeof (FPGM(bci_smooth_blue_round
))
6983 + sizeof (FPGM(bci_strong_blue_round
))
6984 + sizeof (FPGM(bci_blue_round_range
))
6985 + sizeof (FPGM(bci_decrement_component_counter
))
6986 + sizeof (FPGM(bci_get_point_extrema
))
6987 + sizeof (FPGM(bci_nibbles
))
6988 + sizeof (FPGM(bci_number_set_is_element
))
6989 + sizeof (FPGM(bci_number_set_is_element2
))
6991 + sizeof (FPGM(bci_create_segment
))
6992 + sizeof (FPGM(bci_create_segments_a
))
6994 + sizeof (FPGM(bci_create_segments_b
))
6995 + (font
->control_data_head
!= 0
6996 ? sizeof (FPGM(bci_create_segments_c
))
6998 + sizeof (FPGM(bci_create_segments_d
))
7000 + sizeof (FPGM(bci_create_segments_0
))
7001 + sizeof (FPGM(bci_create_segments_1
))
7002 + sizeof (FPGM(bci_create_segments_2
))
7003 + sizeof (FPGM(bci_create_segments_3
))
7004 + sizeof (FPGM(bci_create_segments_4
))
7005 + sizeof (FPGM(bci_create_segments_5
))
7006 + sizeof (FPGM(bci_create_segments_6
))
7007 + sizeof (FPGM(bci_create_segments_7
))
7008 + sizeof (FPGM(bci_create_segments_8
))
7009 + sizeof (FPGM(bci_create_segments_9
))
7011 + sizeof (FPGM(bci_deltap1
))
7012 + sizeof (FPGM(bci_deltap2
))
7013 + sizeof (FPGM(bci_deltap3
))
7015 + sizeof (FPGM(bci_create_segments_composite_a
))
7017 + sizeof (FPGM(bci_create_segments_composite_b
))
7018 + (font
->control_data_head
!= 0
7019 ? sizeof (FPGM(bci_create_segments_composite_c
))
7021 + sizeof (FPGM(bci_create_segments_composite_d
))
7023 + sizeof (FPGM(bci_create_segments_composite_0
))
7024 + sizeof (FPGM(bci_create_segments_composite_1
))
7025 + sizeof (FPGM(bci_create_segments_composite_2
))
7026 + sizeof (FPGM(bci_create_segments_composite_3
))
7027 + sizeof (FPGM(bci_create_segments_composite_4
))
7028 + sizeof (FPGM(bci_create_segments_composite_5
))
7029 + sizeof (FPGM(bci_create_segments_composite_6
))
7030 + sizeof (FPGM(bci_create_segments_composite_7
))
7031 + sizeof (FPGM(bci_create_segments_composite_8
))
7032 + sizeof (FPGM(bci_create_segments_composite_9
))
7034 + sizeof (FPGM(bci_align_point
))
7035 + sizeof (FPGM(bci_align_segment
))
7036 + sizeof (FPGM(bci_align_segments
))
7038 + sizeof (FPGM(bci_scale_contour
))
7039 + sizeof (FPGM(bci_scale_glyph_a
))
7041 + sizeof (FPGM(bci_scale_glyph_b
))
7042 + sizeof (FPGM(bci_scale_composite_glyph_a
))
7044 + sizeof (FPGM(bci_scale_composite_glyph_b
))
7045 + sizeof (FPGM(bci_shift_contour
))
7046 + sizeof (FPGM(bci_shift_subglyph_a
))
7048 + sizeof (FPGM(bci_shift_subglyph_b
))
7049 + (font
->control_data_head
!= 0
7050 ? sizeof (FPGM(bci_shift_subglyph_c
))
7052 + sizeof (FPGM(bci_shift_subglyph_d
))
7054 + sizeof (FPGM(bci_ip_outer_align_point
))
7055 + sizeof (FPGM(bci_ip_on_align_points
))
7056 + sizeof (FPGM(bci_ip_between_align_point
))
7057 + sizeof (FPGM(bci_ip_between_align_points
))
7059 + sizeof (FPGM(bci_adjust_common
))
7060 + sizeof (FPGM(bci_stem_common
))
7061 + sizeof (FPGM(bci_serif_common
))
7062 + sizeof (FPGM(bci_serif_anchor_common
))
7063 + sizeof (FPGM(bci_serif_link1_common
))
7064 + sizeof (FPGM(bci_serif_link2_common
))
7066 + sizeof (FPGM(bci_lower_bound
))
7067 + sizeof (FPGM(bci_upper_bound
))
7068 + sizeof (FPGM(bci_upper_lower_bound
))
7070 + sizeof (FPGM(bci_adjust_bound
))
7071 + sizeof (FPGM(bci_stem_bound
))
7072 + sizeof (FPGM(bci_link
))
7073 + sizeof (FPGM(bci_anchor
))
7074 + sizeof (FPGM(bci_adjust
))
7075 + sizeof (FPGM(bci_stem
))
7077 + sizeof (FPGM(bci_action_ip_before
))
7078 + sizeof (FPGM(bci_action_ip_after
))
7079 + sizeof (FPGM(bci_action_ip_on
))
7080 + sizeof (FPGM(bci_action_ip_between
))
7082 + sizeof (FPGM(bci_action_blue
))
7083 + sizeof (FPGM(bci_action_blue_anchor
))
7085 + sizeof (FPGM(bci_action_anchor
))
7086 + sizeof (FPGM(bci_action_anchor_serif
))
7087 + sizeof (FPGM(bci_action_anchor_round
))
7088 + sizeof (FPGM(bci_action_anchor_round_serif
))
7090 + sizeof (FPGM(bci_action_adjust
))
7091 + sizeof (FPGM(bci_action_adjust_serif
))
7092 + sizeof (FPGM(bci_action_adjust_round
))
7093 + sizeof (FPGM(bci_action_adjust_round_serif
))
7094 + sizeof (FPGM(bci_action_adjust_bound
))
7095 + sizeof (FPGM(bci_action_adjust_bound_serif
))
7096 + sizeof (FPGM(bci_action_adjust_bound_round
))
7097 + sizeof (FPGM(bci_action_adjust_bound_round_serif
))
7098 + sizeof (FPGM(bci_action_adjust_down_bound
))
7099 + sizeof (FPGM(bci_action_adjust_down_bound_serif
))
7100 + sizeof (FPGM(bci_action_adjust_down_bound_round
))
7101 + sizeof (FPGM(bci_action_adjust_down_bound_round_serif
))
7103 + sizeof (FPGM(bci_action_link
))
7104 + sizeof (FPGM(bci_action_link_serif
))
7105 + sizeof (FPGM(bci_action_link_round
))
7106 + sizeof (FPGM(bci_action_link_round_serif
))
7108 + sizeof (FPGM(bci_action_stem
))
7109 + sizeof (FPGM(bci_action_stem_serif
))
7110 + sizeof (FPGM(bci_action_stem_round
))
7111 + sizeof (FPGM(bci_action_stem_round_serif
))
7112 + sizeof (FPGM(bci_action_stem_bound
))
7113 + sizeof (FPGM(bci_action_stem_bound_serif
))
7114 + sizeof (FPGM(bci_action_stem_bound_round
))
7115 + sizeof (FPGM(bci_action_stem_bound_round_serif
))
7116 + sizeof (FPGM(bci_action_stem_down_bound
))
7117 + sizeof (FPGM(bci_action_stem_down_bound_serif
))
7118 + sizeof (FPGM(bci_action_stem_down_bound_round
))
7119 + sizeof (FPGM(bci_action_stem_down_bound_round_serif
))
7121 + sizeof (FPGM(bci_action_serif
))
7122 + sizeof (FPGM(bci_action_serif_lower_bound
))
7123 + sizeof (FPGM(bci_action_serif_upper_bound
))
7124 + sizeof (FPGM(bci_action_serif_upper_lower_bound
))
7125 + sizeof (FPGM(bci_action_serif_down_lower_bound
))
7126 + sizeof (FPGM(bci_action_serif_down_upper_bound
))
7127 + sizeof (FPGM(bci_action_serif_down_upper_lower_bound
))
7129 + sizeof (FPGM(bci_action_serif_anchor
))
7130 + sizeof (FPGM(bci_action_serif_anchor_lower_bound
))
7131 + sizeof (FPGM(bci_action_serif_anchor_upper_bound
))
7132 + sizeof (FPGM(bci_action_serif_anchor_upper_lower_bound
))
7133 + sizeof (FPGM(bci_action_serif_anchor_down_lower_bound
))
7134 + sizeof (FPGM(bci_action_serif_anchor_down_upper_bound
))
7135 + sizeof (FPGM(bci_action_serif_anchor_down_upper_lower_bound
))
7137 + sizeof (FPGM(bci_action_serif_link1
))
7138 + sizeof (FPGM(bci_action_serif_link1_lower_bound
))
7139 + sizeof (FPGM(bci_action_serif_link1_upper_bound
))
7140 + sizeof (FPGM(bci_action_serif_link1_upper_lower_bound
))
7141 + sizeof (FPGM(bci_action_serif_link1_down_lower_bound
))
7142 + sizeof (FPGM(bci_action_serif_link1_down_upper_bound
))
7143 + sizeof (FPGM(bci_action_serif_link1_down_upper_lower_bound
))
7145 + sizeof (FPGM(bci_action_serif_link2
))
7146 + sizeof (FPGM(bci_action_serif_link2_lower_bound
))
7147 + sizeof (FPGM(bci_action_serif_link2_upper_bound
))
7148 + sizeof (FPGM(bci_action_serif_link2_upper_lower_bound
))
7149 + sizeof (FPGM(bci_action_serif_link2_down_lower_bound
))
7150 + sizeof (FPGM(bci_action_serif_link2_down_upper_bound
))
7151 + sizeof (FPGM(bci_action_serif_link2_down_upper_lower_bound
))
7153 + sizeof (FPGM(bci_hint_glyph
));
7155 /* buffer length must be a multiple of four */
7156 len
= (buf_len
+ 3) & ~3U;
7157 buf
= (FT_Byte
*)malloc(len
);
7159 return FT_Err_Out_Of_Memory
;
7161 /* pad end of buffer with zeros */
7162 buf
[len
- 1] = 0x00;
7163 buf
[len
- 2] = 0x00;
7164 buf
[len
- 3] = 0x00;
7166 /* copy font program into buffer and fill in the missing variables */
7169 COPY_FPGM(bci_align_x_height_a
);
7170 if (font
->increase_x_height
)
7172 COPY_FPGM(bci_align_x_height_b1a
);
7173 *(bufp
++) = HIGH(font
->increase_x_height
);
7174 *(bufp
++) = LOW(font
->increase_x_height
);
7175 COPY_FPGM(bci_align_x_height_b1b
);
7178 COPY_FPGM(bci_align_x_height_b2
);
7179 COPY_FPGM(bci_align_x_height_c
);
7181 COPY_FPGM(bci_round
);
7182 COPY_FPGM(bci_quantize_stem_width
);
7183 COPY_FPGM(bci_smooth_stem_width
);
7184 COPY_FPGM(bci_get_best_width
);
7185 COPY_FPGM(bci_strong_stem_width_a
);
7186 *(bufp
++) = num_used_styles
;
7187 COPY_FPGM(bci_strong_stem_width_b
);
7188 COPY_FPGM(bci_loop_do
);
7189 COPY_FPGM(bci_loop
);
7190 COPY_FPGM(bci_cvt_rescale
);
7191 COPY_FPGM(bci_cvt_rescale_range
);
7192 COPY_FPGM(bci_vwidth_data_store
);
7193 COPY_FPGM(bci_smooth_blue_round
);
7194 COPY_FPGM(bci_strong_blue_round
);
7195 COPY_FPGM(bci_blue_round_range
);
7196 COPY_FPGM(bci_decrement_component_counter
);
7197 COPY_FPGM(bci_get_point_extrema
);
7198 COPY_FPGM(bci_nibbles
);
7199 COPY_FPGM(bci_number_set_is_element
);
7200 COPY_FPGM(bci_number_set_is_element2
);
7202 COPY_FPGM(bci_create_segment
);
7203 COPY_FPGM(bci_create_segments_a
);
7204 *(bufp
++) = num_used_styles
;
7205 COPY_FPGM(bci_create_segments_b
);
7206 if (font
->control_data_head
)
7207 COPY_FPGM(bci_create_segments_c
);
7208 COPY_FPGM(bci_create_segments_d
);
7210 COPY_FPGM(bci_create_segments_0
);
7211 COPY_FPGM(bci_create_segments_1
);
7212 COPY_FPGM(bci_create_segments_2
);
7213 COPY_FPGM(bci_create_segments_3
);
7214 COPY_FPGM(bci_create_segments_4
);
7215 COPY_FPGM(bci_create_segments_5
);
7216 COPY_FPGM(bci_create_segments_6
);
7217 COPY_FPGM(bci_create_segments_7
);
7218 COPY_FPGM(bci_create_segments_8
);
7219 COPY_FPGM(bci_create_segments_9
);
7221 COPY_FPGM(bci_deltap1
);
7222 COPY_FPGM(bci_deltap2
);
7223 COPY_FPGM(bci_deltap3
);
7225 COPY_FPGM(bci_create_segments_composite_a
);
7226 *(bufp
++) = num_used_styles
;
7227 COPY_FPGM(bci_create_segments_composite_b
);
7228 if (font
->control_data_head
)
7229 COPY_FPGM(bci_create_segments_composite_c
);
7230 COPY_FPGM(bci_create_segments_composite_d
);
7232 COPY_FPGM(bci_create_segments_composite_0
);
7233 COPY_FPGM(bci_create_segments_composite_1
);
7234 COPY_FPGM(bci_create_segments_composite_2
);
7235 COPY_FPGM(bci_create_segments_composite_3
);
7236 COPY_FPGM(bci_create_segments_composite_4
);
7237 COPY_FPGM(bci_create_segments_composite_5
);
7238 COPY_FPGM(bci_create_segments_composite_6
);
7239 COPY_FPGM(bci_create_segments_composite_7
);
7240 COPY_FPGM(bci_create_segments_composite_8
);
7241 COPY_FPGM(bci_create_segments_composite_9
);
7243 COPY_FPGM(bci_align_point
);
7244 COPY_FPGM(bci_align_segment
);
7245 COPY_FPGM(bci_align_segments
);
7247 COPY_FPGM(bci_scale_contour
);
7248 COPY_FPGM(bci_scale_glyph_a
);
7249 *(bufp
++) = fallback_style
;
7250 COPY_FPGM(bci_scale_glyph_b
);
7251 COPY_FPGM(bci_scale_composite_glyph_a
);
7252 *(bufp
++) = fallback_style
;
7253 COPY_FPGM(bci_scale_composite_glyph_b
);
7254 COPY_FPGM(bci_shift_contour
);
7255 COPY_FPGM(bci_shift_subglyph_a
);
7256 *(bufp
++) = fallback_style
;
7257 COPY_FPGM(bci_shift_subglyph_b
);
7258 if (font
->control_data_head
)
7259 COPY_FPGM(bci_shift_subglyph_c
);
7260 COPY_FPGM(bci_shift_subglyph_d
);
7262 COPY_FPGM(bci_ip_outer_align_point
);
7263 COPY_FPGM(bci_ip_on_align_points
);
7264 COPY_FPGM(bci_ip_between_align_point
);
7265 COPY_FPGM(bci_ip_between_align_points
);
7267 COPY_FPGM(bci_adjust_common
);
7268 COPY_FPGM(bci_stem_common
);
7269 COPY_FPGM(bci_serif_common
);
7270 COPY_FPGM(bci_serif_anchor_common
);
7271 COPY_FPGM(bci_serif_link1_common
);
7272 COPY_FPGM(bci_serif_link2_common
);
7274 COPY_FPGM(bci_lower_bound
);
7275 COPY_FPGM(bci_upper_bound
);
7276 COPY_FPGM(bci_upper_lower_bound
);
7278 COPY_FPGM(bci_adjust_bound
);
7279 COPY_FPGM(bci_stem_bound
);
7280 COPY_FPGM(bci_link
);
7281 COPY_FPGM(bci_anchor
);
7282 COPY_FPGM(bci_adjust
);
7283 COPY_FPGM(bci_stem
);
7285 COPY_FPGM(bci_action_ip_before
);
7286 COPY_FPGM(bci_action_ip_after
);
7287 COPY_FPGM(bci_action_ip_on
);
7288 COPY_FPGM(bci_action_ip_between
);
7290 COPY_FPGM(bci_action_blue
);
7291 COPY_FPGM(bci_action_blue_anchor
);
7293 COPY_FPGM(bci_action_anchor
);
7294 COPY_FPGM(bci_action_anchor_serif
);
7295 COPY_FPGM(bci_action_anchor_round
);
7296 COPY_FPGM(bci_action_anchor_round_serif
);
7298 COPY_FPGM(bci_action_adjust
);
7299 COPY_FPGM(bci_action_adjust_serif
);
7300 COPY_FPGM(bci_action_adjust_round
);
7301 COPY_FPGM(bci_action_adjust_round_serif
);
7302 COPY_FPGM(bci_action_adjust_bound
);
7303 COPY_FPGM(bci_action_adjust_bound_serif
);
7304 COPY_FPGM(bci_action_adjust_bound_round
);
7305 COPY_FPGM(bci_action_adjust_bound_round_serif
);
7306 COPY_FPGM(bci_action_adjust_down_bound
);
7307 COPY_FPGM(bci_action_adjust_down_bound_serif
);
7308 COPY_FPGM(bci_action_adjust_down_bound_round
);
7309 COPY_FPGM(bci_action_adjust_down_bound_round_serif
);
7311 COPY_FPGM(bci_action_link
);
7312 COPY_FPGM(bci_action_link_serif
);
7313 COPY_FPGM(bci_action_link_round
);
7314 COPY_FPGM(bci_action_link_round_serif
);
7316 COPY_FPGM(bci_action_stem
);
7317 COPY_FPGM(bci_action_stem_serif
);
7318 COPY_FPGM(bci_action_stem_round
);
7319 COPY_FPGM(bci_action_stem_round_serif
);
7320 COPY_FPGM(bci_action_stem_bound
);
7321 COPY_FPGM(bci_action_stem_bound_serif
);
7322 COPY_FPGM(bci_action_stem_bound_round
);
7323 COPY_FPGM(bci_action_stem_bound_round_serif
);
7324 COPY_FPGM(bci_action_stem_down_bound
);
7325 COPY_FPGM(bci_action_stem_down_bound_serif
);
7326 COPY_FPGM(bci_action_stem_down_bound_round
);
7327 COPY_FPGM(bci_action_stem_down_bound_round_serif
);
7329 COPY_FPGM(bci_action_serif
);
7330 COPY_FPGM(bci_action_serif_lower_bound
);
7331 COPY_FPGM(bci_action_serif_upper_bound
);
7332 COPY_FPGM(bci_action_serif_upper_lower_bound
);
7333 COPY_FPGM(bci_action_serif_down_lower_bound
);
7334 COPY_FPGM(bci_action_serif_down_upper_bound
);
7335 COPY_FPGM(bci_action_serif_down_upper_lower_bound
);
7337 COPY_FPGM(bci_action_serif_anchor
);
7338 COPY_FPGM(bci_action_serif_anchor_lower_bound
);
7339 COPY_FPGM(bci_action_serif_anchor_upper_bound
);
7340 COPY_FPGM(bci_action_serif_anchor_upper_lower_bound
);
7341 COPY_FPGM(bci_action_serif_anchor_down_lower_bound
);
7342 COPY_FPGM(bci_action_serif_anchor_down_upper_bound
);
7343 COPY_FPGM(bci_action_serif_anchor_down_upper_lower_bound
);
7345 COPY_FPGM(bci_action_serif_link1
);
7346 COPY_FPGM(bci_action_serif_link1_lower_bound
);
7347 COPY_FPGM(bci_action_serif_link1_upper_bound
);
7348 COPY_FPGM(bci_action_serif_link1_upper_lower_bound
);
7349 COPY_FPGM(bci_action_serif_link1_down_lower_bound
);
7350 COPY_FPGM(bci_action_serif_link1_down_upper_bound
);
7351 COPY_FPGM(bci_action_serif_link1_down_upper_lower_bound
);
7353 COPY_FPGM(bci_action_serif_link2
);
7354 COPY_FPGM(bci_action_serif_link2_lower_bound
);
7355 COPY_FPGM(bci_action_serif_link2_upper_bound
);
7356 COPY_FPGM(bci_action_serif_link2_upper_lower_bound
);
7357 COPY_FPGM(bci_action_serif_link2_down_lower_bound
);
7358 COPY_FPGM(bci_action_serif_link2_down_upper_bound
);
7359 COPY_FPGM(bci_action_serif_link2_down_upper_lower_bound
);
7361 COPY_FPGM(bci_hint_glyph
);
7364 *fpgm_len
= buf_len
;
7371 TA_sfnt_build_fpgm_table(SFNT
* sfnt
,
7376 SFNT_Table
* glyf_table
= &font
->tables
[sfnt
->glyf_idx
];
7377 glyf_Data
* data
= (glyf_Data
*)glyf_table
->data
;
7383 error
= TA_sfnt_add_table_info(sfnt
);
7387 /* `glyf', `cvt', `fpgm', and `prep' are always used in parallel */
7388 if (glyf_table
->processed
)
7390 sfnt
->table_infos
[sfnt
->num_table_infos
- 1] = data
->fpgm_idx
;
7394 error
= TA_table_build_fpgm(&fpgm_buf
, &fpgm_len
, sfnt
, font
);
7398 if (fpgm_len
> sfnt
->max_instructions
)
7399 sfnt
->max_instructions
= (FT_UShort
)fpgm_len
;
7401 /* in case of success, `fpgm_buf' gets linked */
7402 /* and is eventually freed in `TA_font_unload' */
7403 error
= TA_font_add_table(font
,
7404 &sfnt
->table_infos
[sfnt
->num_table_infos
- 1],
7405 TTAG_fpgm
, fpgm_len
, fpgm_buf
);
7409 data
->fpgm_idx
= sfnt
->table_infos
[sfnt
->num_table_infos
- 1];
7415 /* end of tafpgm.c */