3 /* written 2011 by Werner Lemberg <wl@gnu.org> */
6 #include "tabytecode.h"
9 /* a simple macro to emit bytecode instructions */
10 #define BCI(code) *(bufp++) = (code)
15 int _ta_debug_disable_horz_hints
;
16 int _ta_debug_disable_vert_hints
;
17 int _ta_debug_disable_blue_hints
;
18 void* _ta_debug_hints
;
22 /* structures for hinting sets */
23 typedef struct Edge2Blue_
{
24 FT_UInt first_segment
;
29 FT_UInt num_remaining_segments
;
30 FT_UInt
* remaining_segments
;
33 typedef struct Edge2Link_
{
34 FT_UInt first_segment
;
36 FT_UInt num_remaining_segments
;
37 FT_UInt
* remaining_segments
;
40 typedef struct Hinting_Set_
{
43 FT_UInt num_edges2blues
;
44 Edge2Blue
* edges2blues
;
46 FT_UInt num_edges2links
;
47 Edge2Link
* edges2links
;
52 TA_sfnt_compute_global_hints(SFNT
* sfnt
,
56 FT_Face face
= sfnt
->face
;
60 static const FT_Encoding latin_encs
[] =
63 FT_ENCODING_APPLE_ROMAN
,
64 FT_ENCODING_ADOBE_STANDARD
,
65 FT_ENCODING_ADOBE_LATIN_1
,
67 FT_ENCODING_NONE
/* end of list */
71 error
= ta_loader_init(font
->loader
);
75 /* try to select a latin charmap */
76 for (enc
= 0; latin_encs
[enc
] != FT_ENCODING_NONE
; enc
++)
78 error
= FT_Select_Charmap(face
, latin_encs
[enc
]);
83 /* load latin glyph `a' to trigger all initializations */
84 idx
= FT_Get_Char_Index(face
, 'a');
85 error
= ta_loader_load_glyph(font
->loader
, face
, idx
, 0);
92 TA_table_build_cvt(FT_Byte
** cvt
,
109 error
= TA_sfnt_compute_global_hints(sfnt
, font
);
113 /* XXX check validity of pointers */
114 haxis
= &((TA_LatinMetrics
)font
->loader
->hints
.metrics
)->axis
[0];
115 vaxis
= &((TA_LatinMetrics
)font
->loader
->hints
.metrics
)->axis
[1];
117 buf_len
= 2 * (haxis
->width_count
+ vaxis
->width_count
118 + 2 * vaxis
->blue_count
);
120 /* buffer length must be a multiple of four */
121 len
= (buf_len
+ 3) & ~3;
122 buf
= (FT_Byte
*)malloc(len
);
124 return FT_Err_Out_Of_Memory
;
126 /* pad end of buffer with zeros */
133 /* XXX emit standard_width also? */
135 for (i
= 0; i
< haxis
->width_count
; i
++)
137 if (haxis
->widths
[i
].org
> 0xFFFF)
139 *(buf_p
++) = HIGH(haxis
->widths
[i
].org
);
140 *(buf_p
++) = LOW(haxis
->widths
[i
].org
);
143 for (i
= 0; i
< vaxis
->width_count
; i
++)
145 if (vaxis
->widths
[i
].org
> 0xFFFF)
147 *(buf_p
++) = HIGH(vaxis
->widths
[i
].org
);
148 *(buf_p
++) = LOW(vaxis
->widths
[i
].org
);
151 for (i
= 0; i
< vaxis
->blue_count
; i
++)
153 if (vaxis
->blues
[i
].ref
.org
> 0xFFFF)
155 *(buf_p
++) = HIGH(vaxis
->blues
[i
].ref
.org
);
156 *(buf_p
++) = LOW(vaxis
->blues
[i
].ref
.org
);
159 for (i
= 0; i
< vaxis
->blue_count
; i
++)
161 if (vaxis
->blues
[i
].shoot
.org
> 0xFFFF)
163 *(buf_p
++) = HIGH(vaxis
->blues
[i
].shoot
.org
);
164 *(buf_p
++) = LOW(vaxis
->blues
[i
].shoot
.org
);
168 TA_LOG(("--------------------------------------------------\n"));
169 TA_LOG(("glyph %d:\n", idx
));
170 ta_glyph_hints_dump_edges(_ta_debug_hints
);
171 ta_glyph_hints_dump_segments(_ta_debug_hints
);
172 ta_glyph_hints_dump_points(_ta_debug_hints
);
182 return TA_Err_Hinter_Overflow
;
187 TA_sfnt_build_cvt_table(SFNT
* sfnt
,
196 error
= TA_sfnt_add_table_info(sfnt
);
200 error
= TA_table_build_cvt(&cvt_buf
, &cvt_len
, sfnt
, font
);
204 /* in case of success, `cvt_buf' gets linked */
205 /* and is eventually freed in `TA_font_unload' */
206 error
= TA_font_add_table(font
,
207 &sfnt
->table_infos
[sfnt
->num_table_infos
- 1],
208 TTAG_cvt
, cvt_len
, cvt_buf
);
219 /* the horizontal stem widths */
220 #define CVT_HORZ_WIDTHS_OFFSET(font) 0
221 #define CVT_HORZ_WIDTHS_SIZE(font) \
222 ((TA_LatinMetrics)font->loader->hints.metrics)->axis[0].width_count
224 /* the vertical stem widths */
225 #define CVT_VERT_WIDTHS_OFFSET(font) \
226 CVT_HORZ_WIDTHS_OFFSET(font) \
227 + ((TA_LatinMetrics)font->loader->hints.metrics)->axis[0].width_count
228 #define CVT_VERT_WIDTHS_SIZE(font) \
229 ((TA_LatinMetrics)font->loader->hints.metrics)->axis[1].width_count
231 /* the blue zone values for flat edges */
232 #define CVT_BLUE_REFS_OFFSET(font) \
233 CVT_VERT_WIDTHS_OFFSET(font) \
234 + ((TA_LatinMetrics)font->loader->hints.metrics)->axis[1].width_count
235 #define CVT_BLUE_REFS_SIZE(font) \
236 ((TA_LatinMetrics)font->loader->hints.metrics)->axis[1].blue_count
238 /* the blue zone values for round edges */
239 #define CVT_BLUE_SHOOTS_OFFSET(font) \
240 CVT_BLUE_REFS_OFFSET(font) \
241 + ((TA_LatinMetrics)font->loader->hints.metrics)->axis[1].blue_count
242 #define CVT_BLUE_SHOOTS_SIZE(font) \
243 ((TA_LatinMetrics)font->loader->hints.metrics)->axis[1].blue_count
246 /* symbolic names for storage area locations */
248 #define sal_counter 0
251 #define sal_0x10000 3
252 #define sal_segment_offset 4
255 /* in the comments below, the top of the stack (`s:') */
256 /* is the rightmost element; the stack is shown */
257 /* after the instruction on the same line has been executed */
262 * This is the equivalent to the following code from function
263 * `ta_latin_compute_stem_width':
270 * else if base_is_round:
274 * dist = MIN(56, dist)
276 * delta = ABS(dist - std_width)
279 * dist = MIN(48, std_width)
285 * delta = delta - dist
288 * dist = dist + delta
289 * else if delta < 32:
291 * else if delta < 54:
294 * dist = dist + delta
305 * Function 0: compute_stem_width
311 * CVT: is_extra_light XXX
315 #define compute_stem_width 0
317 unsigned char fpgm_0a
[] = {
324 ABS
, /* s: base_is_round stem_is_serif width dist */
329 LT
, /* dist < 3*64 */
333 MINDEX
, /* s: base_is_round width dist (dist<3*64) stem_is_serif */
335 AND
, /* stem_is_serif && dist < 3*64 */
336 IF
, /* s: base_is_round width dist */
342 ROLL
, /* s: width dist base_is_round */
343 IF
, /* s: width dist */
348 IF
, /* s: width dist */
357 MIN
, /* dist = min(56, dist) */
360 DUP
, /* s: width dist dist */
365 /* %c, index of std_width */
367 unsigned char fpgm_0b
[] = {
371 ABS
, /* s: width dist delta */
376 IF
, /* s: width dist */
383 /* %c, index of std_width */
385 unsigned char fpgm_0c
[] = {
388 MIN
, /* dist = min(48, std_width) */
391 DUP
, /* s: width dist dist */
394 LT
, /* dist < 3*64 */
396 DUP
, /* s: width delta dist */
397 FLOOR
, /* dist = FLOOR(dist) */
398 DUP
, /* s: width delta dist dist */
400 ROLL
, /* s: width dist delta dist */
401 SUB
, /* delta = delta - dist */
403 DUP
, /* s: width dist delta delta */
407 IF
, /* s: width dist delta */
408 ADD
, /* dist = dist + delta */
419 ADD
, /* dist = dist + 10 */
430 ADD
, /* dist = dist + 54 */
433 ADD
, /* dist = dist + delta */
443 FLOOR
, /* dist = round(dist) */
448 SWAP
, /* s: dist width */
452 NEG
, /* dist = -dist */
465 * Take a range and a function number and apply the function to all
466 * elements of the range. The called function must not change the
475 * uses: sal_counter (counter initialized with `start')
481 unsigned char fpgm_1
[] = {
488 ROLL
, /* s: func_num start end */
506 LTEQ
, /* start <= end */
507 IF
, /* s: func_num */
514 ADD
, /* start = start + 1 */
523 JMPR
, /* goto start_loop */
536 * All entries in the CVT table get scaled automatically using the
537 * vertical resolution. However, some widths must be scaled with the
538 * horizontal resolution, and others get adjusted later on.
540 * Function 2: rescale
542 * uses: sal_counter (CVT index)
543 * sal_scale (scale in 16.16 format)
548 unsigned char fpgm_2
[] = {
562 MUL
, /* CVT * scale * 2^10 */
566 DIV
, /* CVT * scale */
578 * Apply the WS instruction repeatedly to stack data.
580 * Function 3: sal_loop_assign
594 unsigned char fpgm_3
[] = {
601 ROLL
, /* s: offset offset data */
606 SUB
, /* s: (offset - 1) */
612 #define sal_loop_assign 4
614 unsigned char fpgm_4
[] = {
620 DUP
, /* s: offset counter counter */
626 SWAP
, /* s: (offset + counter - 1) counter */
628 /* process the stack, popping off the elements in a loop */
640 TA_table_build_fpgm(FT_Byte
** fpgm
,
650 buf_len
= sizeof (fpgm_0a
)
659 /* buffer length must be a multiple of four */
660 len
= (buf_len
+ 3) & ~3;
661 buf
= (FT_Byte
*)malloc(len
);
663 return FT_Err_Out_Of_Memory
;
665 /* pad end of buffer with zeros */
670 /* copy font program into buffer and fill in the missing variables */
673 memcpy(buf_p
, fpgm_0a
, sizeof (fpgm_0a
));
674 buf_p
+= sizeof (fpgm_0a
);
676 *(buf_p
++) = (unsigned char)CVT_VERT_WIDTHS_OFFSET(font
);
678 memcpy(buf_p
, fpgm_0b
, sizeof (fpgm_0b
));
679 buf_p
+= sizeof (fpgm_0b
);
681 *(buf_p
++) = (unsigned char)CVT_VERT_WIDTHS_OFFSET(font
);
683 memcpy(buf_p
, fpgm_0c
, sizeof (fpgm_0c
));
684 buf_p
+= sizeof (fpgm_0c
);
686 memcpy(buf_p
, fpgm_1
, sizeof (fpgm_1
));
687 buf_p
+= sizeof (fpgm_1
);
689 memcpy(buf_p
, fpgm_2
, sizeof (fpgm_2
));
690 buf_p
+= sizeof (fpgm_2
);
692 memcpy(buf_p
, fpgm_3
, sizeof (fpgm_3
));
693 buf_p
+= sizeof (fpgm_3
);
695 memcpy(buf_p
, fpgm_4
, sizeof (fpgm_4
));
705 TA_sfnt_build_fpgm_table(SFNT
* sfnt
,
714 error
= TA_sfnt_add_table_info(sfnt
);
718 error
= TA_table_build_fpgm(&fpgm_buf
, &fpgm_len
, font
);
722 /* in case of success, `fpgm_buf' gets linked */
723 /* and is eventually freed in `TA_font_unload' */
724 error
= TA_font_add_table(font
,
725 &sfnt
->table_infos
[sfnt
->num_table_infos
- 1],
726 TTAG_fpgm
, fpgm_len
, fpgm_buf
);
737 /* the `prep' instructions */
739 /* we often need 0x10000 which can't be pushed directly onto the stack, */
740 /* thus we provide it in the storage area */
742 unsigned char prep_A
[] = {
757 unsigned char prep_a
[] = {
759 /* scale horizontal CVT entries */
760 /* if horizontal and vertical resolutions differ */
766 NEQ
, /* horz_ppem != vert_ppem */
773 MUL
, /* horz_ppem in 22.10 format */
777 DIV
, /* (horz_ppem / vert_ppem) in 16.16 format */
784 /* loop over horizontal CVT entries */
789 /* %c, first horizontal index */
790 /* %c, last horizontal index */
792 unsigned char prep_b
[] = {
801 unsigned char prep_c
[] = {
803 /* optimize the alignment of the top of small letters to the pixel grid */
809 /* %c, index of alignment blue zone */
811 unsigned char prep_d
[] = {
819 FLOOR
, /* fitted = FLOOR(scaled + 40) */
820 DUP
, /* s: scaled scaled fitted fitted */
823 IF
, /* s: scaled fitted */
827 MUL
, /* scaled in 16.16 format */
829 DIV
, /* (fitted / scaled) in 16.16 format */
836 /* loop over vertical CVT entries */
841 /* %c, first vertical index */
842 /* %c, last vertical index */
844 unsigned char prep_e
[] = {
850 /* loop over blue refs */
855 /* %c, first blue ref index */
856 /* %c, last blue ref index */
858 unsigned char prep_f
[] = {
864 /* loop over blue shoots */
869 /* %c, first blue shoot index */
870 /* %c, last blue shoot index */
872 unsigned char prep_g
[] = {
884 TA_table_build_prep(FT_Byte
** prep
,
889 TA_LatinBlue blue_adjustment
;
898 vaxis
= &((TA_LatinMetrics
)font
->loader
->hints
.metrics
)->axis
[1];
899 blue_adjustment
= NULL
;
901 for (i
= 0; i
< vaxis
->blue_count
; i
++)
903 if (vaxis
->blues
[i
].flags
& TA_LATIN_BLUE_ADJUSTMENT
)
905 blue_adjustment
= &vaxis
->blues
[i
];
910 buf_len
= sizeof (prep_A
)
917 buf_len
+= sizeof (prep_c
)
928 /* buffer length must be a multiple of four */
929 len
= (buf_len
+ 3) & ~3;
930 buf
= (FT_Byte
*)malloc(len
);
932 return FT_Err_Out_Of_Memory
;
934 /* pad end of buffer with zeros */
939 /* copy cvt program into buffer and fill in the missing variables */
942 memcpy(buf_p
, prep_A
, sizeof (prep_A
));
943 buf_p
+= sizeof (prep_A
);
945 memcpy(buf_p
, prep_a
, sizeof (prep_a
));
946 buf_p
+= sizeof (prep_a
);
948 *(buf_p
++) = (unsigned char)CVT_HORZ_WIDTHS_OFFSET(font
);
949 *(buf_p
++) = (unsigned char)(CVT_HORZ_WIDTHS_OFFSET(font
)
950 + CVT_HORZ_WIDTHS_SIZE(font
) - 1);
952 memcpy(buf_p
, prep_b
, sizeof (prep_b
));
956 buf_p
+= sizeof (prep_b
);
958 memcpy(buf_p
, prep_c
, sizeof (prep_c
));
959 buf_p
+= sizeof (prep_c
);
961 *(buf_p
++) = blue_adjustment
- vaxis
->blues
962 + CVT_BLUE_SHOOTS_OFFSET(font
);
964 memcpy(buf_p
, prep_d
, sizeof (prep_d
));
965 buf_p
+= sizeof (prep_d
);
967 *(buf_p
++) = (unsigned char)CVT_VERT_WIDTHS_OFFSET(font
);
968 *(buf_p
++) = (unsigned char)(CVT_VERT_WIDTHS_OFFSET(font
)
969 + CVT_VERT_WIDTHS_SIZE(font
) - 1);
971 memcpy(buf_p
, prep_e
, sizeof (prep_e
));
972 buf_p
+= sizeof (prep_e
);
974 *(buf_p
++) = (unsigned char)CVT_BLUE_REFS_OFFSET(font
);
975 *(buf_p
++) = (unsigned char)(CVT_BLUE_REFS_OFFSET(font
)
976 + CVT_BLUE_REFS_SIZE(font
) - 1);
978 memcpy(buf_p
, prep_f
, sizeof (prep_f
));
979 buf_p
+= sizeof (prep_f
);
981 *(buf_p
++) = (unsigned char)CVT_BLUE_SHOOTS_OFFSET(font
);
982 *(buf_p
++) = (unsigned char)(CVT_BLUE_SHOOTS_OFFSET(font
)
983 + CVT_BLUE_SHOOTS_SIZE(font
) - 1);
985 memcpy(buf_p
, prep_g
, sizeof (prep_g
));
988 /* XXX handle extra_light */
998 TA_sfnt_build_prep_table(SFNT
* sfnt
,
1007 error
= TA_sfnt_add_table_info(sfnt
);
1011 error
= TA_table_build_prep(&prep_buf
, &prep_len
, font
);
1015 /* in case of success, `prep_buf' gets linked */
1016 /* and is eventually freed in `TA_font_unload' */
1017 error
= TA_font_add_table(font
,
1018 &sfnt
->table_infos
[sfnt
->num_table_infos
- 1],
1019 TTAG_prep
, prep_len
, prep_buf
);
1030 /* we store the segments in the storage area; */
1031 /* each segment record consists of the first and last point */
1034 TA_font_build_glyph_segments(FONT
* font
,
1037 TA_GlyphHints hints
= &font
->loader
->hints
;
1038 TA_AxisHints axis
= &hints
->axis
[TA_DIMENSION_VERT
];
1039 TA_Point points
= hints
->points
;
1040 TA_Segment segments
= axis
->segments
;
1050 limit
= axis
->num_segments
* 2 + 2;
1053 /* NPUSHB and NPUSHW can't handle more than 256 stack elements */
1055 if (hints
->num_points
> 0xFF)
1059 if (limit
- count
> 256)
1064 if (axis
->num_segments
== 127)
1069 delta
= limit
- count
;
1070 loop_limit
= (delta
- 2) / 2;
1073 while (count
< limit
)
1078 for (i
= 0; i
< loop_limit
; i
++, seg
++)
1080 BCI(HIGH(seg
->first
- points
));
1081 BCI(LOW(seg
->first
- points
));
1082 BCI(HIGH(seg
->last
- points
));
1083 BCI(LOW(seg
->last
- points
));
1088 if (limit
- count
> 256)
1093 if (axis
->num_segments
== 127)
1098 delta
= limit
- count
;
1099 loop_limit
= (delta
- 2) / 2;
1103 BCI(HIGH(sal_segment_offset
));
1104 BCI(LOW(sal_segment_offset
));
1105 BCI(HIGH(axis
->num_segments
* 2));
1106 BCI(LOW(axis
->num_segments
* 2));
1112 if (limit
- count
> 256)
1117 if (axis
->num_segments
== 127)
1122 delta
= limit
- count
;
1123 loop_limit
= (delta
- 2) / 2;
1126 while (count
< limit
)
1131 for (i
= 0; i
< loop_limit
; i
++, seg
++)
1133 BCI(seg
->first
- points
);
1134 BCI(seg
->last
- points
);
1139 if (limit
- count
> 256)
1144 if (axis
->num_segments
== 127)
1149 delta
= limit
- count
;
1150 loop_limit
= (delta
- 2) / 2;
1154 BCI(sal_segment_offset
);
1155 BCI(axis
->num_segments
* 2);
1159 BCI(sal_loop_assign
);
1165 TA_font_clear_edge_DONE_flag(FONT
* font
)
1167 TA_GlyphHints hints
= &font
->loader
->hints
;
1168 TA_AxisHints axis
= &hints
->axis
[TA_DIMENSION_VERT
];
1169 TA_Edge edges
= axis
->edges
;
1170 TA_Edge edge_limit
= edges
+ axis
->num_edges
;
1174 for (edge
= edges
; edge
< edge_limit
; edge
++)
1175 edge
->flags
&= ~TA_EDGE_DONE
;
1180 TA_construct_hinting_set(FONT
* font
,
1182 Hinting_Set
* hinting_set
)
1184 hinting_set
->size
= size
;
1186 /* XXX use real values */
1187 hinting_set
->num_edges2blues
= 0;
1188 hinting_set
->edges2blues
= NULL
;
1189 hinting_set
->num_edges2links
= 0;
1190 hinting_set
->edges2links
= NULL
;
1197 TA_hinting_set_is_different(Hinting_Set
* hinting_sets
,
1198 FT_UInt num_hinting_sets
,
1199 Hinting_Set hinting_set
)
1201 Hinting_Set last_hinting_set
;
1203 Edge2Blue
* edge2blue
;
1204 Edge2Blue
* last_edge2blue
;
1205 Edge2Link
* edge2link
;
1206 Edge2Link
* last_edge2link
;
1214 /* we only need to compare with the last hinting set */
1215 last_hinting_set
= hinting_sets
[num_hinting_sets
- 1];
1217 if (hinting_set
.num_edges2blues
1218 != last_hinting_set
.num_edges2blues
)
1221 edge2blue
= hinting_set
.edges2blues
;
1222 last_edge2blue
= last_hinting_set
.edges2blues
;
1225 i
< hinting_set
.num_edges2blues
;
1226 i
++, edge2blue
++, last_edge2blue
++)
1228 if (edge2blue
->num_remaining_segments
1229 != last_edge2blue
->num_remaining_segments
)
1232 if (edge2blue
->remaining_segments
)
1234 if (memcmp(edge2blue
->remaining_segments
,
1235 last_edge2blue
->remaining_segments
,
1236 sizeof (FT_UInt
) * edge2blue
->num_remaining_segments
))
1241 if (hinting_set
.num_edges2links
1242 != last_hinting_set
.num_edges2links
)
1245 edge2link
= hinting_set
.edges2links
;
1246 last_edge2link
= last_hinting_set
.edges2links
;
1249 i
< hinting_set
.num_edges2links
;
1250 i
++, edge2link
++, last_edge2link
++)
1252 if (edge2link
->num_remaining_segments
1253 != last_edge2link
->num_remaining_segments
)
1256 if (edge2link
->remaining_segments
)
1258 if (memcmp(edge2link
->remaining_segments
,
1259 last_edge2link
->remaining_segments
,
1260 sizeof (FT_UInt
) * edge2link
->num_remaining_segments
))
1270 TA_add_hinting_set(Hinting_Set
** hinting_sets
,
1271 FT_UInt
* num_hinting_sets
,
1272 Hinting_Set hinting_set
)
1274 Hinting_Set
* hinting_sets_new
;
1277 (*num_hinting_sets
)++;
1279 (Hinting_Set
*)realloc(*hinting_sets
, *num_hinting_sets
1280 * sizeof (Hinting_Set
));
1281 if (!hinting_sets_new
)
1283 (*num_hinting_sets
)--;
1284 return FT_Err_Out_Of_Memory
;
1287 *hinting_sets
= hinting_sets_new
;
1289 *hinting_sets
[*num_hinting_sets
- 1] = hinting_set
;
1296 TA_free_hinting_set(Hinting_Set hinting_set
)
1301 for (i
= 0; i
< hinting_set
.num_edges2blues
; i
++)
1302 free(hinting_set
.edges2blues
[i
].remaining_segments
);
1303 free(hinting_set
.edges2blues
);
1305 for (i
= 0; i
< hinting_set
.num_edges2links
; i
++)
1306 free(hinting_set
.edges2links
[i
].remaining_segments
);
1307 free(hinting_set
.edges2links
);
1312 TA_free_hinting_sets(Hinting_Set
* hinting_sets
,
1313 FT_UInt num_hinting_sets
)
1318 for (i
= 0; i
< num_hinting_sets
; i
++)
1319 TA_free_hinting_set(hinting_sets
[i
]);
1326 TA_sfnt_build_glyph_instructions(SFNT
* sfnt
,
1330 FT_Face face
= sfnt
->face
;
1337 SFNT_Table
* glyf_table
= &font
->tables
[sfnt
->glyf_idx
];
1338 glyf_Data
* data
= (glyf_Data
*)glyf_table
->data
;
1339 GLYPH
* glyph
= &data
->glyphs
[idx
];
1341 TA_GlyphHints hints
;
1343 FT_UInt num_hinting_sets
;
1344 Hinting_Set
* hinting_sets
;
1350 return FT_Err_Invalid_Argument
;
1352 /* computing the segments is resolution independent, */
1353 /* thus the pixel size in this call is arbitrary */
1354 error
= FT_Set_Pixel_Sizes(face
, 20, 20);
1358 error
= ta_loader_load_glyph(font
->loader
, face
, (FT_UInt
)idx
, 0);
1362 /* do nothing if we have an empty glyph */
1363 if (!face
->glyph
->outline
.n_contours
)
1366 hints
= &font
->loader
->hints
;
1368 /* we allocate a buffer which is certainly large enough */
1369 /* to hold all of the created bytecode instructions; */
1370 /* later on it gets reallocated to its real size */
1371 ins_len
= hints
->num_points
* 1000;
1372 ins_buf
= (FT_Byte
*)malloc(ins_len
);
1374 return FT_Err_Out_Of_Memory
;
1376 /* initialize array with an invalid bytecode */
1377 /* so that we can easily find the array length at reallocation time */
1378 memset(ins_buf
, INS_A0
, ins_len
);
1380 TA_font_build_glyph_segments(font
, ins_buf
);
1382 /* now we loop over a large range of pixel sizes */
1383 /* to find hinting sets which get pushed onto the bytecode stack */
1384 num_hinting_sets
= 0;
1385 hinting_sets
= NULL
;
1387 for (size
= 8; size
<= 10; size
++)
1389 Hinting_Set hinting_set
;
1392 error
= FT_Set_Pixel_Sizes(face
, size
, size
);
1396 error
= ta_loader_load_glyph(font
->loader
, face
, idx
, 0);
1400 TA_font_clear_edge_DONE_flag(font
);
1402 error
= TA_construct_hinting_set(font
, size
, &hinting_set
);
1406 if (TA_hinting_set_is_different(hinting_sets
,
1410 error
= TA_add_hinting_set(&hinting_sets
,
1415 TA_free_hinting_set(hinting_set
);
1420 TA_free_hinting_set(hinting_set
);
1423 /* push hinting sets */
1424 /* XXX: emit hinting instructions */
1426 /* we are done, so reallocate the instruction array to its real size */
1427 p
= (FT_Byte
*)memchr((char*)ins_buf
, INS_A0
, ins_len
);
1428 ins_len
= p
- ins_buf
;
1430 if (ins_len
> sfnt
->max_instructions
)
1431 sfnt
->max_instructions
= ins_len
;
1433 glyph
->ins_buf
= realloc(ins_buf
, ins_len
);
1434 glyph
->ins_len
= ins_len
;
1436 TA_free_hinting_sets(hinting_sets
, num_hinting_sets
);
1441 TA_free_hinting_sets(hinting_sets
, num_hinting_sets
);
1449 TA_sfnt_build_glyf_hints(SFNT
* sfnt
,
1452 FT_Face face
= sfnt
->face
;
1457 for (idx
= 0; idx
< face
->num_glyphs
; idx
++)
1459 error
= TA_sfnt_build_glyph_instructions(sfnt
, font
, idx
);
1464 /* XXX provide real values or better estimates */
1465 sfnt
->max_storage
= 1000;
1466 sfnt
->max_stack_elements
= 1000;
1471 /* end of tabytecode.c */