static FT_Error TA_table_build_prep(FT_Byte** prep, FT_ULong* prep_len, FONT* font) { TA_LatinAxis vaxis; TA_LatinBlue blue_adjustment = NULL; FT_UInt i; FT_UInt buf_len = 0; FT_UInt len; FT_Byte* buf; FT_Byte* buf_p; if (font->loader->hints.metrics->clazz->script == TA_SCRIPT_NONE) vaxis = NULL; else { vaxis = &((TA_LatinMetrics)font->loader->hints.metrics)->axis[1]; for (i = 0; i < vaxis->blue_count; i++) { if (vaxis->blues[i].flags & TA_LATIN_BLUE_ADJUSTMENT) { blue_adjustment = &vaxis->blues[i]; break; } } } if (font->hinting_limit) buf_len += sizeof (PREP(hinting_limit_a)) + 2 + sizeof (PREP(hinting_limit_b)); buf_len += sizeof (PREP(store_0x10000)); if (blue_adjustment) buf_len += sizeof (PREP(align_top_a)) + 1 + sizeof (PREP(align_top_b)) + (font->increase_x_height ? sizeof (PREP(align_top_c1)) : sizeof (PREP(align_top_c2))) + sizeof (PREP(align_top_d)) + sizeof (PREP(loop_cvt_a)) + 2 + sizeof (PREP(loop_cvt_b)) + 2 + sizeof (PREP(loop_cvt_c)) + 2 + sizeof (PREP(loop_cvt_d)); buf_len += sizeof (PREP(compute_extra_light_a)) + 1 + sizeof (PREP(compute_extra_light_b)); if (CVT_BLUES_SIZE(font)) buf_len += sizeof (PREP(round_blues_a)) + 2 + sizeof (PREP(round_blues_b)); buf_len += sizeof (PREP(set_dropout_mode)); buf_len += sizeof (PREP(reset_component_counter)); /* buffer length must be a multiple of four */ len = (buf_len + 3) & ~3; buf = (FT_Byte*)malloc(len); if (!buf) return FT_Err_Out_Of_Memory; /* pad end of buffer with zeros */ buf[len - 1] = 0x00; buf[len - 2] = 0x00; buf[len - 3] = 0x00; /* copy cvt program into buffer and fill in the missing variables */ buf_p = buf; if (font->hinting_limit) { COPY_PREP(hinting_limit_a); *(buf_p++) = HIGH(font->hinting_limit); *(buf_p++) = LOW(font->hinting_limit); COPY_PREP(hinting_limit_b); } COPY_PREP(store_0x10000); if (blue_adjustment) { COPY_PREP(align_top_a); *(buf_p++) = (unsigned char)(CVT_BLUE_SHOOTS_OFFSET(font) + blue_adjustment - vaxis->blues); COPY_PREP(align_top_b); if (font->increase_x_height) COPY_PREP(align_top_c1); else COPY_PREP(align_top_c2); COPY_PREP(align_top_d); COPY_PREP(loop_cvt_a); *(buf_p++) = (unsigned char)CVT_VERT_WIDTHS_OFFSET(font); *(buf_p++) = (unsigned char)(CVT_VERT_WIDTHS_OFFSET(font) + CVT_VERT_WIDTHS_SIZE(font) - 1); COPY_PREP(loop_cvt_b); *(buf_p++) = (unsigned char)CVT_BLUE_REFS_OFFSET(font); *(buf_p++) = (unsigned char)(CVT_BLUE_REFS_OFFSET(font) + CVT_BLUES_SIZE(font) - 1); COPY_PREP(loop_cvt_c); *(buf_p++) = (unsigned char)CVT_BLUE_SHOOTS_OFFSET(font); *(buf_p++) = (unsigned char)(CVT_BLUE_SHOOTS_OFFSET(font) + CVT_BLUES_SIZE(font) - 1); COPY_PREP(loop_cvt_d); } COPY_PREP(compute_extra_light_a); *(buf_p++) = (unsigned char)CVT_VERT_STANDARD_WIDTH_OFFSET(font); COPY_PREP(compute_extra_light_b); if (CVT_BLUES_SIZE(font)) { COPY_PREP(round_blues_a); *(buf_p++) = (unsigned char)CVT_BLUE_REFS_OFFSET(font); *(buf_p++) = (unsigned char)(CVT_BLUE_REFS_OFFSET(font) + CVT_BLUES_SIZE(font) - 1); COPY_PREP(round_blues_b); } COPY_PREP(set_dropout_mode); COPY_PREP(reset_component_counter); *prep = buf; *prep_len = buf_len; return FT_Err_Ok; }
static void TA_hints_recorder(TA_Action action, TA_GlyphHints hints, TA_Dimension dim, void* arg1, TA_Edge arg2, TA_Edge arg3, TA_Edge lower_bound, TA_Edge upper_bound) { TA_AxisHints axis = &hints->axis[dim]; TA_Edge edges = axis->edges; TA_Segment segments = axis->segments; TA_Point points = hints->points; Recorder* recorder = (Recorder*)hints->user; FONT* font = recorder->font; FT_UInt* wraps = recorder->wrap_around_segments; FT_Byte* p = recorder->hints_record.buf; FT_UInt* ip; FT_UInt* limit; if (dim == TA_DIMENSION_HORZ) return; /* we collect point hints for later processing */ switch (action) { case ta_ip_before: { TA_Point point = (TA_Point)arg1; ip = recorder->ip_before_points; limit = ip + recorder->num_strong_points; for (; ip < limit; ip++) { if (*ip == MISSING) { *ip = point - points; break; } } } return; case ta_ip_after: { TA_Point point = (TA_Point)arg1; ip = recorder->ip_after_points; limit = ip + recorder->num_strong_points; for (; ip < limit; ip++) { if (*ip == MISSING) { *ip = point - points; break; } } } return; case ta_ip_on: { TA_Point point = (TA_Point)arg1; TA_Edge edge = arg2; ip = recorder->ip_on_point_array + recorder->num_strong_points * (edge - edges); limit = ip + recorder->num_strong_points; for (; ip < limit; ip++) { if (*ip == MISSING) { *ip = point - points; break; } } } return; case ta_ip_between: { TA_Point point = (TA_Point)arg1; TA_Edge before = arg2; TA_Edge after = arg3; /* note that `recorder->num_segments' has been used for allocation, */ /* but `axis->num_edges' is used for accessing this array */ ip = recorder->ip_between_point_array + recorder->num_strong_points * axis->num_edges * (before - edges) + recorder->num_strong_points * (after - edges); limit = ip + recorder->num_strong_points; for (; ip < limit; ip++) { if (*ip == MISSING) { *ip = point - points; break; } } } return; case ta_bound: /* we ignore the BOUND action since we signal this information */ /* with the proper function number */ return; default: break; } /* some enum values correspond to four or eight bytecode functions; */ /* if the value is n, the function numbers are n, ..., n+7, */ /* to be differentiated with flags */ switch (action) { case ta_link: { TA_Edge base_edge = (TA_Edge)arg1; TA_Edge stem_edge = arg2; *(p++) = 0; *(p++) = (FT_Byte)action + ACTION_OFFSET + ((stem_edge->flags & TA_EDGE_SERIF) != 0) + 2 * ((base_edge->flags & TA_EDGE_ROUND) != 0); *(p++) = HIGH(base_edge->first - segments); *(p++) = LOW(base_edge->first - segments); *(p++) = HIGH(stem_edge->first - segments); *(p++) = LOW(stem_edge->first - segments); p = TA_hints_recorder_handle_segments(p, axis, stem_edge, wraps); } break; case ta_anchor: { TA_Edge edge = (TA_Edge)arg1; TA_Edge edge2 = arg2; *(p++) = 0; *(p++) = (FT_Byte)action + ACTION_OFFSET + ((edge2->flags & TA_EDGE_SERIF) != 0) + 2 * ((edge->flags & TA_EDGE_ROUND) != 0); *(p++) = HIGH(edge->first - segments); *(p++) = LOW(edge->first - segments); *(p++) = HIGH(edge2->first - segments); *(p++) = LOW(edge2->first - segments); p = TA_hints_recorder_handle_segments(p, axis, edge, wraps); } break; case ta_adjust: { TA_Edge edge = (TA_Edge)arg1; TA_Edge edge2 = arg2; TA_Edge edge_minus_one = lower_bound; *(p++) = 0; *(p++) = (FT_Byte)action + ACTION_OFFSET + ((edge2->flags & TA_EDGE_SERIF) != 0) + 2 * ((edge->flags & TA_EDGE_ROUND) != 0) + 4 * (edge_minus_one != NULL); *(p++) = HIGH(edge->first - segments); *(p++) = LOW(edge->first - segments); *(p++) = HIGH(edge2->first - segments); *(p++) = LOW(edge2->first - segments); if (edge_minus_one) { *(p++) = HIGH(edge_minus_one->first - segments); *(p++) = LOW(edge_minus_one->first - segments); } p = TA_hints_recorder_handle_segments(p, axis, edge, wraps); } break; case ta_blue_anchor: { TA_Edge edge = (TA_Edge)arg1; TA_Edge blue = arg2; *(p++) = 0; *(p++) = (FT_Byte)action + ACTION_OFFSET; *(p++) = HIGH(blue->first - segments); *(p++) = LOW(blue->first - segments); if (edge->best_blue_is_shoot) { *(p++) = HIGH(CVT_BLUE_SHOOTS_OFFSET(font) + edge->best_blue_idx); *(p++) = LOW(CVT_BLUE_SHOOTS_OFFSET(font) + edge->best_blue_idx); } else { *(p++) = HIGH(CVT_BLUE_REFS_OFFSET(font) + edge->best_blue_idx); *(p++) = LOW(CVT_BLUE_REFS_OFFSET(font) + edge->best_blue_idx); } *(p++) = HIGH(edge->first - segments); *(p++) = LOW(edge->first - segments); p = TA_hints_recorder_handle_segments(p, axis, edge, wraps); } break; case ta_stem: { TA_Edge edge = (TA_Edge)arg1; TA_Edge edge2 = arg2; TA_Edge edge_minus_one = lower_bound; *(p++) = 0; *(p++) = (FT_Byte)action + ACTION_OFFSET + ((edge2->flags & TA_EDGE_SERIF) != 0) + 2 * ((edge->flags & TA_EDGE_ROUND) != 0) + 4 * (edge_minus_one != NULL); *(p++) = HIGH(edge->first - segments); *(p++) = LOW(edge->first - segments); *(p++) = HIGH(edge2->first - segments); *(p++) = LOW(edge2->first - segments); if (edge_minus_one) { *(p++) = HIGH(edge_minus_one->first - segments); *(p++) = LOW(edge_minus_one->first - segments); } p = TA_hints_recorder_handle_segments(p, axis, edge, wraps); p = TA_hints_recorder_handle_segments(p, axis, edge2, wraps); } break; case ta_blue: { TA_Edge edge = (TA_Edge)arg1; *(p++) = 0; *(p++) = (FT_Byte)action + ACTION_OFFSET; if (edge->best_blue_is_shoot) { *(p++) = HIGH(CVT_BLUE_SHOOTS_OFFSET(font) + edge->best_blue_idx); *(p++) = LOW(CVT_BLUE_SHOOTS_OFFSET(font) + edge->best_blue_idx); } else { *(p++) = HIGH(CVT_BLUE_REFS_OFFSET(font) + edge->best_blue_idx); *(p++) = LOW(CVT_BLUE_REFS_OFFSET(font) + edge->best_blue_idx); } *(p++) = HIGH(edge->first - segments); *(p++) = LOW(edge->first - segments); p = TA_hints_recorder_handle_segments(p, axis, edge, wraps); } break; case ta_serif: { TA_Edge serif = (TA_Edge)arg1; TA_Edge base = serif->serif; *(p++) = 0; *(p++) = (FT_Byte)action + ACTION_OFFSET + (lower_bound != NULL) + 2 * (upper_bound != NULL); *(p++) = HIGH(serif->first - segments); *(p++) = LOW(serif->first - segments); *(p++) = HIGH(base->first - segments); *(p++) = LOW(base->first - segments); if (lower_bound) { *(p++) = HIGH(lower_bound->first - segments); *(p++) = LOW(lower_bound->first - segments); } if (upper_bound) { *(p++) = HIGH(upper_bound->first - segments); *(p++) = LOW(upper_bound->first - segments); } p = TA_hints_recorder_handle_segments(p, axis, serif, wraps); } break; case ta_serif_anchor: case ta_serif_link2: { TA_Edge edge = (TA_Edge)arg1; *(p++) = 0; *(p++) = (FT_Byte)action + ACTION_OFFSET + (lower_bound != NULL) + 2 * (upper_bound != NULL); *(p++) = HIGH(edge->first - segments); *(p++) = LOW(edge->first - segments); if (lower_bound) { *(p++) = HIGH(lower_bound->first - segments); *(p++) = LOW(lower_bound->first - segments); } if (upper_bound) { *(p++) = HIGH(upper_bound->first - segments); *(p++) = LOW(upper_bound->first - segments); } p = TA_hints_recorder_handle_segments(p, axis, edge, wraps); } break; case ta_serif_link1: { TA_Edge edge = (TA_Edge)arg1; TA_Edge before = arg2; TA_Edge after = arg3; *(p++) = 0; *(p++) = (FT_Byte)action + ACTION_OFFSET + (lower_bound != NULL) + 2 * (upper_bound != NULL); *(p++) = HIGH(before->first - segments); *(p++) = LOW(before->first - segments); *(p++) = HIGH(edge->first - segments); *(p++) = LOW(edge->first - segments); *(p++) = HIGH(after->first - segments); *(p++) = LOW(after->first - segments); if (lower_bound) { *(p++) = HIGH(lower_bound->first - segments); *(p++) = LOW(lower_bound->first - segments); } if (upper_bound) { *(p++) = HIGH(upper_bound->first - segments); *(p++) = LOW(upper_bound->first - segments); } p = TA_hints_recorder_handle_segments(p, axis, edge, wraps); } break; default: /* there are more cases in the enumeration */ /* which are handled with flags */ break; } recorder->hints_record.num_actions++; recorder->hints_record.buf = p; }
static FT_Error TA_table_build_prep(FT_Byte** prep, FT_ULong* prep_len, SFNT* sfnt, FONT* font) { SFNT_Table* glyf_table = &font->tables[sfnt->glyf_idx]; glyf_Data* data = (glyf_Data*)glyf_table->data; /* XXX: make this work for more than 256 styles */ FT_Byte num_used_styles = (FT_Byte)data->num_used_styles; FT_Int i; FT_Byte* buf = NULL; FT_Byte* buf_new; FT_UInt buf_len; FT_UInt buf_new_len; FT_UInt len; FT_Byte* bufp = NULL; if (font->x_height_snapping_exceptions) { bufp = TA_sfnt_build_number_set(sfnt, &buf, font->x_height_snapping_exceptions); if (!bufp) return FT_Err_Out_Of_Memory; } buf_len = (FT_UInt)(bufp - buf); buf_new_len = buf_len; if (font->hinting_limit) buf_new_len += sizeof (PREP(hinting_limit_a)) + 2 + sizeof (PREP(hinting_limit_b)); buf_new_len += sizeof (PREP(store_funits_to_pixels)); if (font->x_height_snapping_exceptions) buf_new_len += sizeof (PREP(test_exception_a)); buf_new_len += sizeof (PREP(align_top_a)) + (num_used_styles > 6 ? num_used_styles + 3 : num_used_styles + 2) + sizeof (PREP(align_top_b)); buf_new_len += sizeof (PREP(loop_cvt_a)) + (num_used_styles > 3 ? 2 * num_used_styles + 3 : 2 * num_used_styles + 2) + sizeof (PREP(loop_cvt_b)) + (num_used_styles > 3 ? 2 * num_used_styles + 3 : 2 * num_used_styles + 2) + sizeof (PREP(loop_cvt_c)); if (font->x_height_snapping_exceptions) buf_new_len += sizeof (PREP(test_exception_b)); buf_new_len += sizeof (PREP(store_vwidth_data_a)) + 1 + sizeof (PREP(store_vwidth_data_b)) + (num_used_styles > 6 ? 2 * (num_used_styles + 1) + 2 : 2 * (num_used_styles + 1) + 1) + sizeof (PREP(store_vwidth_data_c)) + 1 + sizeof (PREP(store_vwidth_data_d)) + (num_used_styles > 6 ? 2 * (num_used_styles + 1) + 2 : 2 * (num_used_styles + 1) + 1) + sizeof (PREP(store_vwidth_data_e)); buf_new_len += sizeof (PREP(set_smooth_or_strong_a)) + 1 + sizeof (PREP(set_smooth_or_strong_b)) + 1 + sizeof (PREP(set_smooth_or_strong_c)) + 1 + sizeof (PREP(set_smooth_or_strong_d)); buf_new_len += (num_used_styles > 3 ? 2 * num_used_styles + 3 : 2 * num_used_styles + 2) + sizeof (PREP(round_blues)); buf_new_len += sizeof (PREP(set_dropout_mode)); buf_new_len += sizeof (PREP(reset_component_counter)); if (font->control_data_head) buf_new_len += sizeof (PREP(adjust_delta_exceptions)); buf_new_len += sizeof (PREP(set_default_cvs_values)); /* buffer length must be a multiple of four */ len = (buf_new_len + 3) & ~3U; buf_new = (FT_Byte*)realloc(buf, len); if (!buf_new) { free(buf); return FT_Err_Out_Of_Memory; } buf = buf_new; /* pad end of buffer with zeros */ buf[len - 1] = 0x00; buf[len - 2] = 0x00; buf[len - 3] = 0x00; /* copy remaining cvt program into buffer */ /* and fill in the missing variables */ bufp = buf + buf_len; if (font->hinting_limit) { COPY_PREP(hinting_limit_a); *(bufp++) = HIGH(font->hinting_limit); *(bufp++) = LOW(font->hinting_limit); COPY_PREP(hinting_limit_b); } COPY_PREP(store_funits_to_pixels); if (font->x_height_snapping_exceptions) COPY_PREP(test_exception_a); COPY_PREP(align_top_a); if (num_used_styles > 6) { BCI(NPUSHB); BCI(num_used_styles + 2); } else BCI(PUSHB_1 - 1 + num_used_styles + 2); /* XXX: make this work for offsets > 255 */ for (i = TA_STYLE_MAX - 1; i >= 0; i--) { if (data->style_ids[i] == 0xFFFFU) continue; *(bufp++) = CVT_X_HEIGHT_BLUE_OFFSET(i) >= 0xFFFFU ? 0 : (unsigned char)CVT_X_HEIGHT_BLUE_OFFSET(i); } *(bufp++) = num_used_styles; COPY_PREP(align_top_b); COPY_PREP(loop_cvt_a); if (num_used_styles > 3) { BCI(NPUSHB); BCI(2 * num_used_styles + 2); } else BCI(PUSHB_1 - 1 + 2 * num_used_styles + 2); /* XXX: make this work for offsets > 255 */ for (i = TA_STYLE_MAX - 1; i >= 0; i--) { if (data->style_ids[i] == 0xFFFFU) continue; /* don't loop over artificial blue zones */ *(bufp++) = (unsigned char)CVT_VERT_STANDARD_WIDTH_OFFSET(i); *(bufp++) = (unsigned char)( 1 + CVT_VERT_WIDTHS_SIZE(i) + (CVT_BLUES_SIZE(i) > 1 ? CVT_BLUES_SIZE(i) - 2 : 0)); } *(bufp++) = num_used_styles; COPY_PREP(loop_cvt_b); if (num_used_styles > 3) { BCI(NPUSHB); BCI(2 * num_used_styles + 2); } else BCI(PUSHB_1 - 1 + 2 * num_used_styles + 2); /* XXX: make this work for offsets > 255 */ for (i = TA_STYLE_MAX - 1; i >= 0; i--) { if (data->style_ids[i] == 0xFFFFU) continue; /* don't loop over artificial blue zones */ *(bufp++) = (unsigned char)CVT_BLUE_SHOOTS_OFFSET(i); *(bufp++) = (unsigned char)( CVT_BLUES_SIZE(i) > 1 ? CVT_BLUES_SIZE(i) - 2 : 0); } *(bufp++) = num_used_styles; COPY_PREP(loop_cvt_c); if (font->x_height_snapping_exceptions) COPY_PREP(test_exception_b); COPY_PREP(store_vwidth_data_a); *(bufp++) = (unsigned char)CVT_VWIDTH_OFFSET_DATA(0); COPY_PREP(store_vwidth_data_b); if (num_used_styles > 6) { BCI(NPUSHW); BCI(num_used_styles + 2); } else BCI(PUSHW_1 - 1 + num_used_styles + 2); for (i = TA_STYLE_MAX - 1; i >= 0; i--) { if (data->style_ids[i] == 0xFFFFU) continue; *(bufp++) = HIGH(CVT_VERT_WIDTHS_OFFSET(i) * 64); *(bufp++) = LOW(CVT_VERT_WIDTHS_OFFSET(i) * 64); } *(bufp++) = HIGH(num_used_styles); *(bufp++) = LOW(num_used_styles); COPY_PREP(store_vwidth_data_c); *(bufp++) = (unsigned char)CVT_VWIDTH_SIZE_DATA(0); COPY_PREP(store_vwidth_data_d); if (num_used_styles > 6) { BCI(NPUSHW); BCI(num_used_styles + 2); } else BCI(PUSHW_1 - 1 + num_used_styles + 2); for (i = TA_STYLE_MAX - 1; i >= 0; i--) { if (data->style_ids[i] == 0xFFFFU) continue; *(bufp++) = HIGH(CVT_VERT_WIDTHS_SIZE(i) * 64); *(bufp++) = LOW(CVT_VERT_WIDTHS_SIZE(i) * 64); } *(bufp++) = HIGH(num_used_styles); *(bufp++) = LOW(num_used_styles); COPY_PREP(store_vwidth_data_e); COPY_PREP(set_smooth_or_strong_a); *(bufp++) = font->gray_strong_stem_width ? 100 : 0; COPY_PREP(set_smooth_or_strong_b); *(bufp++) = font->gdi_cleartype_strong_stem_width ? 100 : 0; COPY_PREP(set_smooth_or_strong_c); *(bufp++) = font->dw_cleartype_strong_stem_width ? 100 : 0; COPY_PREP(set_smooth_or_strong_d); if (num_used_styles > 3) { BCI(NPUSHB); BCI(2 * num_used_styles + 2); } else BCI(PUSHB_1 - 1 + 2 * num_used_styles + 2); /* XXX: make this work for offsets > 255 */ for (i = TA_STYLE_MAX - 1; i >= 0; i--) { if (data->style_ids[i] == 0xFFFFU) continue; *(bufp++) = (unsigned char)CVT_BLUE_REFS_OFFSET(i); *(bufp++) = (unsigned char)CVT_BLUES_SIZE(i); } *(bufp++) = num_used_styles; COPY_PREP(round_blues); COPY_PREP(set_dropout_mode); COPY_PREP(reset_component_counter); if (font->control_data_head) COPY_PREP(adjust_delta_exceptions); COPY_PREP(set_default_cvs_values); *prep = buf; *prep_len = buf_new_len; return FT_Err_Ok; }