3 /* written 2011 by Werner Lemberg <wl@gnu.org> */
6 #include "tabytecode.h"
11 int _ta_debug_disable_horz_hints
;
12 int _ta_debug_disable_vert_hints
;
13 int _ta_debug_disable_blue_hints
;
14 void* _ta_debug_hints
;
19 TA_sfnt_compute_global_hints(SFNT
* sfnt
,
23 FT_Face face
= sfnt
->face
;
27 static const FT_Encoding latin_encs
[] =
30 FT_ENCODING_APPLE_ROMAN
,
31 FT_ENCODING_ADOBE_STANDARD
,
32 FT_ENCODING_ADOBE_LATIN_1
,
34 FT_ENCODING_NONE
/* end of list */
38 error
= ta_loader_init(font
->loader
);
42 /* try to select a latin charmap */
43 for (enc
= 0; latin_encs
[enc
] != FT_ENCODING_NONE
; enc
++)
45 error
= FT_Select_Charmap(face
, latin_encs
[enc
]);
50 /* load latin glyph `a' to trigger all initializations */
51 idx
= FT_Get_Char_Index(face
, 'a');
52 error
= ta_loader_load_glyph(font
->loader
, face
, idx
, 0);
59 TA_table_build_cvt(FT_Byte
** cvt
,
76 error
= TA_sfnt_compute_global_hints(sfnt
, font
);
80 /* XXX check validity of pointers */
81 haxis
= &((TA_LatinMetrics
)font
->loader
->hints
.metrics
)->axis
[0];
82 vaxis
= &((TA_LatinMetrics
)font
->loader
->hints
.metrics
)->axis
[1];
84 buf_len
= 2 * (haxis
->width_count
+ vaxis
->width_count
85 + 2 * vaxis
->blue_count
);
86 buf
= (FT_Byte
*)malloc(buf_len
);
88 return FT_Err_Out_Of_Memory
;
92 /* XXX emit standard_width also? */
94 for (i
= 0; i
< haxis
->width_count
; i
++)
96 if (haxis
->widths
[i
].org
> 0xFFFF)
98 *(buf_p
++) = HIGH(haxis
->widths
[i
].org
);
99 *(buf_p
++) = LOW(haxis
->widths
[i
].org
);
102 for (i
= 0; i
< vaxis
->width_count
; i
++)
104 if (vaxis
->widths
[i
].org
> 0xFFFF)
106 *(buf_p
++) = HIGH(vaxis
->widths
[i
].org
);
107 *(buf_p
++) = LOW(vaxis
->widths
[i
].org
);
110 for (i
= 0; i
< vaxis
->blue_count
; i
++)
112 if (vaxis
->blues
[i
].ref
.org
> 0xFFFF)
114 *(buf_p
++) = HIGH(vaxis
->blues
[i
].ref
.org
);
115 *(buf_p
++) = LOW(vaxis
->blues
[i
].ref
.org
);
116 if (vaxis
->blues
[i
].shoot
.org
> 0xFFFF)
118 *(buf_p
++) = HIGH(vaxis
->blues
[i
].shoot
.org
);
119 *(buf_p
++) = LOW(vaxis
->blues
[i
].shoot
.org
);
123 TA_LOG(("--------------------------------------------------\n"));
124 TA_LOG(("glyph %d:\n", idx
));
125 ta_glyph_hints_dump_edges(_ta_debug_hints
);
126 ta_glyph_hints_dump_segments(_ta_debug_hints
);
127 ta_glyph_hints_dump_points(_ta_debug_hints
);
137 return TA_Err_Hinter_Overflow
;
142 TA_sfnt_build_cvt_table(SFNT
* sfnt
,
151 error
= TA_sfnt_add_table_info(sfnt
);
155 error
= TA_table_build_cvt(&cvt_buf
, &cvt_len
, sfnt
, font
);
159 /* in case of success, `cvt_buf' gets linked */
160 /* and is eventually freed in `TA_font_unload' */
161 error
= TA_font_add_table(font
,
162 &sfnt
->table_infos
[sfnt
->num_table_infos
- 1],
163 TTAG_cvt
, cvt_len
, cvt_buf
);
172 /* the horizontal stem widths */
173 #define CVT_HORZ_WIDTHS_OFFSET(font) 0
174 #define CVT_HORZ_WIDTHS_SIZE(font) \
175 ((TA_LatinMetrics)font->loader->hints.metrics)->axis[0].width_count
177 /* the vertical stem widths */
178 #define CVT_VERT_WIDTHS_OFFSET(font) \
179 CVT_HORZ_WIDTHS_OFFSET(font) \
180 + ((TA_LatinMetrics)font->loader->hints.metrics)->axis[0].width_count
181 #define CVT_VERT_WIDTHS_SIZE(font) \
182 ((TA_LatinMetrics)font->loader->hints.metrics)->axis[1].width_count
184 /* the blue zone values for flat edges */
185 #define CVT_BLUE_REFS_OFFSET(font) \
186 CVT_VERT_WIDTHS_OFFSET(font) \
187 + ((TA_LatinMetrics)font->loader->hints.metrics)->axis[1].width_count
188 #define CVT_BLUE_REFS_SIZE(font) \
189 ((TA_LatinMetrics)font->loader->hints.metrics)->axis[1].blue_count
191 /* the blue zone values for round edges */
192 #define CVT_BLUE_SHOOTS_OFFSET(font) \
193 CVT_BLUE_REFS_OFFSET(font) \
194 + ((TA_LatinMetrics)font->loader->hints.metrics)->axis[1].blue_count
195 #define CVT_BLUE_SHOOTS_SIZE(font) \
196 ((TA_LatinMetrics)font->loader->hints.metrics)->axis[1].blue_count
199 /* symbolic names for storage area locations */
201 #define sal_counter 0,
204 #define sal_0x10000 3,
207 /* in the comments below, the top of the stack (`s:') */
208 /* is the rightmost element; the stack is shown */
209 /* after the instruction on the same line has been executed */
214 * This is the equivalent to the following code from function
215 * `ta_latin_compute_stem_width':
222 * else if base_is_round:
226 * dist = MIN(56, dist)
228 * delta = ABS(dist - std_width)
231 * dist = MIN(48, std_width)
237 * delta = delta - dist
240 * dist = dist + delta
241 * else if delta < 32:
243 * else if delta < 54:
246 * dist = dist + delta
257 * Function 0: compute_stem_width
263 * CVT: is_extra_light XXX
267 #define compute_stem_width 0,
269 unsigned char fpgm_0a
[] = {
276 ABS
/* s: base_is_round stem_is_serif width dist */
285 MINDEX
/* s: base_is_round width dist (dist<3*64) stem_is_serif */
287 AND
/* stem_is_serif && dist < 3*64 */
288 IF
/* s: base_is_round width dist */
294 ROLL
/* s: width dist base_is_round */
295 IF
/* s: width dist */
300 IF
/* s: width dist */
309 MIN
/* dist = min(56, dist) */
312 DUP
/* s: width dist dist */
317 /* %c, index of std_width */
319 unsigned char fpgm_0b
[] = {
323 ABS
/* s: width dist delta */
328 IF
/* s: width dist */
335 /* %c, index of std_width */
337 unsigned char fpgm_0c
[] = {
340 MIN
/* dist = min(48, std_width) */
343 DUP
/* s: width dist dist */
348 DUP
/* s: width delta dist */
349 FLOOR
/* dist = FLOOR(dist) */
350 DUP
/* s: width delta dist dist */
352 ROLL
/* s: width dist delta dist */
353 SUB
/* delta = delta - dist */
355 DUP
/* s: width dist delta delta */
359 IF
/* s: width dist delta */
360 ADD
/* dist = dist + delta */
371 ADD
/* dist = dist + 10 */
382 ADD
/* dist = dist + 54 */
385 ADD
/* dist = dist + delta */
395 FLOOR
/* dist = round(dist) */
400 SWAP
/* s: dist width */
404 NEG
/* dist = -dist */
417 * Take a range and a function number and apply the function to all
418 * elements of the range. The called function must not change the
427 * uses: sal_counter (counter initialized with `start')
433 unsigned char fpgm_1
[] = {
439 ROLL
/* s: func_num start end */
457 LTEQ
/* start <= end */
465 ADD
/* start = start + 1 */
474 JMPR
/* goto start_loop */
485 * rescale_horizontally
487 * All entries in the CVT table get scaled automatically using the
488 * vertical resolution. However, some widths must be scaled with the
489 * horizontal resolution.
491 * Function 2: rescale_horizontally
493 * uses: sal_counter (CVT index)
494 * sal_scale (scale in 16.16 format)
497 #define rescale_horizontally 2,
499 unsigned char fpgm_2
[] = {
513 MUL
/* CVT * scale * 2^10 */
517 DIV
/* CVT * scale */
527 /* we often need 0x10000 which can't be pushed directly onto the stack, */
528 /* thus we provide it in the storage area */
530 unsigned char fpgm_A
[] = {
546 TA_table_build_fpgm(FT_Byte
** fpgm
,
555 buf_len
= sizeof (fpgm_0a
)
563 buf
= (FT_Byte
*)malloc(buf_len
);
565 return FT_Err_Out_Of_Memory
;
567 /* copy font program into buffer and fill in the missing variables */
569 memcpy(buf_p
, fpgm_0a
, sizeof (fpgm_0a
));
570 buf_p
+= sizeof (fpgm_0a
);
571 *(buf_p
++) = (unsigned char)CVT_VERT_WIDTHS_OFFSET(font
);
572 memcpy(buf_p
, fpgm_0b
, sizeof (fpgm_0b
));
573 buf_p
+= sizeof (fpgm_0b
);
574 *(buf_p
++) = (unsigned char)CVT_VERT_WIDTHS_OFFSET(font
);
575 memcpy(buf_p
, fpgm_0c
, sizeof (fpgm_0c
));
576 buf_p
+= sizeof (fpgm_0c
);
577 memcpy(buf_p
, fpgm_1
, sizeof (fpgm_1
));
578 buf_p
+= sizeof (fpgm_1
);
579 memcpy(buf_p
, fpgm_2
, sizeof (fpgm_2
));
580 buf_p
+= sizeof (fpgm_2
);
581 memcpy(buf_p
, fpgm_A
, sizeof (fpgm_A
));
591 TA_sfnt_build_fpgm_table(SFNT
* sfnt
,
600 error
= TA_sfnt_add_table_info(sfnt
);
604 error
= TA_table_build_fpgm(&fpgm_buf
, &fpgm_len
, font
);
608 /* in case of success, `fpgm_buf' gets linked */
609 /* and is eventually freed in `TA_font_unload' */
610 error
= TA_font_add_table(font
,
611 &sfnt
->table_infos
[sfnt
->num_table_infos
- 1],
612 TTAG_fpgm
, fpgm_len
, fpgm_buf
);
621 /* the `prep' instructions */
623 unsigned char prep_a
[] = {
625 /* scale horizontal CVT entries */
626 /* if horizontal and vertical resolutions differ */
632 NEQ
/* horz_ppem != vert_ppem */
639 MUL
/* horz_ppem in 22.10 format */
643 DIV
/* (horz_ppem / vert_ppem) in 16.16 format */
650 /* loop over horizontal CVT entries */
655 /* %c, first horizontal index */
656 /* %c, last horizontal index */
658 unsigned char prep_b
[] = {
669 TA_table_build_prep(FT_Byte
** prep
,
678 buf_len
= sizeof (prep_a
)
681 buf
= (FT_Byte
*)malloc(buf_len
);
683 return FT_Err_Out_Of_Memory
;
685 /* copy cvt program into buffer and fill in the missing variables */
687 memcpy(buf_p
, prep_a
, sizeof (prep_a
));
688 buf_p
+= sizeof (prep_a
);
689 *(buf_p
++) = (unsigned char)CVT_HORZ_WIDTHS_OFFSET(font
);
690 *(buf_p
++) = (unsigned char)(CVT_HORZ_WIDTHS_OFFSET(font
)
691 + CVT_HORZ_WIDTHS_SIZE(font
) - 1);
692 memcpy(buf_p
, prep_b
, sizeof (prep_b
));
702 TA_sfnt_build_prep_table(SFNT
* sfnt
,
711 error
= TA_sfnt_add_table_info(sfnt
);
715 error
= TA_table_build_prep(&prep_buf
, &prep_len
, font
);
719 /* in case of success, `prep_buf' gets linked */
720 /* and is eventually freed in `TA_font_unload' */
721 error
= TA_font_add_table(font
,
722 &sfnt
->table_infos
[sfnt
->num_table_infos
- 1],
723 TTAG_prep
, prep_len
, prep_buf
);
731 /* end of tabytecode.c */