4 * Copyright (C) 2014 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.
21 #include <stdbool.h> /* for llrb.h */
23 #include "llrb.h" /* a red-black tree implementation */
24 #include "tacontrol-bison.h"
27 TA_control_new(Control_Type type
,
30 number_range
* point_set
,
33 number_range
* ppem_set
)
38 control
= (Control
*)malloc(sizeof (Control
));
44 control
->font_idx
= font_idx
;
45 control
->glyph_idx
= glyph_idx
;
46 control
->points
= number_set_reverse(point_set
);
48 switch (control
->type
)
50 case Control_Delta_before_IUP
:
51 case Control_Delta_after_IUP
:
52 /* we round shift values to multiples of 1/(2^CONTROL_DELTA_SHIFT) */
53 control
->x_shift
= (char)(x_shift
* CONTROL_DELTA_FACTOR
54 + (x_shift
> 0 ? 0.5 : -0.5));
55 control
->y_shift
= (char)(y_shift
* CONTROL_DELTA_FACTOR
56 + (y_shift
> 0 ? 0.5 : -0.5));
59 case Control_Point_Dir
:
60 /* values -1, 1, and 4 mean `left', `right', and `none', respectively */
61 control
->x_shift
= x_shift
;
66 control
->ppems
= number_set_reverse(ppem_set
);
74 TA_control_prepend(Control
* list
,
87 TA_control_reverse(Control
* list
)
111 TA_control_free(Control
* control
)
118 number_set_free(control
->points
);
119 number_set_free(control
->ppems
);
122 control
= control
->next
;
129 control_show_line(FONT
* font
,
132 char glyph_name_buf
[64];
133 char* points_buf
= NULL
;
134 char* ppems_buf
= NULL
;
146 if (control
->font_idx
>= font
->num_sfnts
)
149 face
= font
->sfnts
[control
->font_idx
].face
;
150 glyph_name_buf
[0] = '\0';
151 if (FT_HAS_GLYPH_NAMES(face
))
152 FT_Get_Glyph_Name(face
, control
->glyph_idx
, glyph_name_buf
, 64);
154 points_buf
= number_set_show(control
->points
, -1, -1);
157 ppems_buf
= number_set_show(control
->ppems
, -1, -1);
161 switch (control
->type
)
163 case Control_Delta_before_IUP
:
164 /* not implemented yet */
167 case Control_Delta_after_IUP
:
168 /* display glyph index if we don't have a glyph name */
170 s
= sdscatprintf(s
, "%ld %s p %s x %.20g y %.20g @ %s",
174 (double)control
->x_shift
/ CONTROL_DELTA_FACTOR
,
175 (double)control
->y_shift
/ CONTROL_DELTA_FACTOR
,
178 s
= sdscatprintf(s
, "%ld %ld p %s x %.20g y %.20g @ %s",
182 (double)control
->x_shift
/ CONTROL_DELTA_FACTOR
,
183 (double)control
->y_shift
/ CONTROL_DELTA_FACTOR
,
187 case Control_Point_Dir
:
188 /* display glyph index if we don't have a glyph name */
190 s
= sdscatprintf(s
, "%ld %s %c %s",
193 control
->x_shift
== TA_DIR_LEFT
? 'l'
194 : control
->x_shift
== TA_DIR_RIGHT
? 'r'
198 s
= sdscatprintf(s
, "%ld %ld %c %s",
201 control
->x_shift
== TA_DIR_LEFT
? 'l'
202 : control
->x_shift
== TA_DIR_RIGHT
? 'r'
217 TA_control_show(FONT
* font
)
223 Control
* control
= font
->control
;
233 /* append current line to buffer, followed by a newline character */
234 d
= control_show_line(font
, control
);
244 control
= control
->next
;
250 /* we return an empty string if there is no data */
252 res
= (char*)malloc(len
);
262 /* Parse control instructions in `font->control_buf'. */
265 TA_control_parse_buffer(FONT
* font
,
266 char** error_string_p
,
267 unsigned int* errlinenum_p
,
273 Control_Context context
;
276 /* nothing to do if no data */
277 if (!font
->control_buf
)
279 font
->control
= NULL
;
283 TA_control_scanner_init(&context
, font
);
286 /* this is `yyparse' in disguise */
287 bison_error
= TA_control_parse(&context
);
288 TA_control_scanner_done(&context
);
292 if (bison_error
== 2)
293 context
.error
= TA_Err_Control_Allocation_Error
;
296 font
->control
= NULL
;
298 if (context
.error
== TA_Err_Control_Allocation_Error
299 || context
.error
== TA_Err_Control_Flex_Error
)
305 *error_string_p
= strdup(context
.errmsg
);
307 *error_string_p
= strdup(TA_get_error_message(context
.error
));
319 /* construct data for `errline_p' */
320 buf_end
= font
->control_buf
+ font
->control_len
;
322 p_start
= font
->control_buf
;
323 if (context
.errline_num
> 1)
326 while (p_start
< buf_end
)
328 if (*p_start
++ == '\n')
331 if (i
== context
.errline_num
)
338 while (p_end
< buf_end
)
344 *errline_p
= strndup(p_start
, p_end
- p_start
);
346 /* construct data for `error_string_p' */
347 if (context
.error
== TA_Err_Control_Invalid_Font_Index
)
348 sprintf(auxbuf
, " (valid range is [%ld;%ld])",
351 else if (context
.error
== TA_Err_Control_Invalid_Glyph_Index
)
352 sprintf(auxbuf
, " (valid range is [%ld;%ld])",
354 font
->sfnts
[context
.font_idx
].face
->num_glyphs
);
355 else if (context
.error
== TA_Err_Control_Invalid_Shift
)
356 sprintf(auxbuf
, " (valid interval is [%g;%g])",
357 CONTROL_DELTA_SHIFT_MIN
,
358 CONTROL_DELTA_SHIFT_MAX
);
359 else if (context
.error
== TA_Err_Control_Invalid_Range
)
360 sprintf(auxbuf
, " (values must be within [%ld;%ld])",
361 context
.number_set_min
,
362 context
.number_set_max
);
366 ret
= asprintf(error_string_p
, "%s%s",
367 *context
.errmsg
? context
.errmsg
368 : TA_get_error_message(context
.error
),
371 *error_string_p
= NULL
;
374 *errpos_p
= *errline_p
+ context
.errline_pos_left
- 1;
378 *errlinenum_p
= context
.errline_num
;
382 font
->control
= context
.result
;
384 return context
.error
;
388 /* node structure for control instruction data */
390 typedef struct Node Node
;
393 LLRB_ENTRY(Node
) entry
;
398 /* comparison function for our red-black tree */
407 /* sort by font index ... */
408 diff
= e1
->ctrl
.font_idx
- e2
->ctrl
.font_idx
;
412 /* ... then by glyph index ... */
413 diff
= e1
->ctrl
.glyph_idx
- e2
->ctrl
.glyph_idx
;
417 /* ... then by ppem ... */
418 diff
= e1
->ctrl
.ppem
- e2
->ctrl
.ppem
;
422 /* ... then by point index */
423 diff
= e1
->ctrl
.point_idx
- e2
->ctrl
.point_idx
;
426 /* https://graphics.stanford.edu/~seander/bithacks.html#CopyIntegerSign */
427 return (diff
> 0) - (diff
< 0);
431 /* the red-black tree function body */
432 typedef struct control_data control_data
;
434 LLRB_HEAD(control_data
, Node
);
436 /* no trailing semicolon in the next line */
437 LLRB_GENERATE_STATIC(control_data
, Node
, entry
, nodecmp
)
441 TA_control_free_tree(FONT
* font
)
443 control_data
* control_data_head
= (control_data
*)font
->control_data_head
;
444 number_range
* control_point_dirs
= font
->control_point_dirs
;
450 if (!control_data_head
)
453 for (node
= LLRB_MIN(control_data
, control_data_head
);
457 next_node
= LLRB_NEXT(control_data
, control_data_head
, node
);
458 LLRB_REMOVE(control_data
, control_data_head
, node
);
462 free(control_data_head
);
463 number_set_free(control_point_dirs
);
468 TA_control_build_tree(FONT
* font
)
470 Control
* control
= font
->control
;
471 control_data
* control_data_head
;
472 int emit_newline
= 0;
475 font
->control_point_dirs
= NULL
;
476 font
->control_point_dir_iter
.range
= NULL
;
478 /* nothing to do if no data */
481 font
->control_data_head
= NULL
;
482 font
->control_data_cur
= NULL
;
486 control_data_head
= (control_data
*)malloc(sizeof (control_data
));
487 if (!control_data_head
)
488 return FT_Err_Out_Of_Memory
;
490 LLRB_INIT(control_data_head
);
494 Control_Type type
= control
->type
;
495 long font_idx
= control
->font_idx
;
496 long glyph_idx
= control
->glyph_idx
;
497 char x_shift
= control
->x_shift
;
498 char y_shift
= control
->y_shift
;
500 number_set_iter ppems_iter
;
504 ppems_iter
.range
= control
->ppems
;
505 ppem
= number_set_get_first(&ppems_iter
);
507 if (type
== Control_Point_Dir
)
510 while (ppems_iter
.range
)
512 number_set_iter points_iter
;
517 points_iter
.range
= control
->points
;
518 point_idx
= number_set_get_first(&points_iter
);
520 while (points_iter
.range
)
526 node
= (Node
*)malloc(sizeof (Node
));
528 return FT_Err_Out_Of_Memory
;
530 node
->ctrl
.type
= type
;
531 node
->ctrl
.font_idx
= font_idx
;
532 node
->ctrl
.glyph_idx
= glyph_idx
;
533 node
->ctrl
.ppem
= ppem
;
534 node
->ctrl
.point_idx
= point_idx
;
535 node
->ctrl
.x_shift
= x_shift
;
536 node
->ctrl
.y_shift
= y_shift
;
538 val
= LLRB_INSERT(control_data
, control_data_head
, node
);
541 if (val
&& font
->debug
)
543 /* entry is already present; we ignore it */
551 /* construct Control entry for debugging output */
555 points
.start
= point_idx
;
556 points
.end
= point_idx
;
560 d
.font_idx
= font_idx
;
561 d
.glyph_idx
= glyph_idx
;
568 s
= control_show_line(font
, &d
);
571 fprintf(stderr
, "Control instruction %s ignored.\n", s
);
578 point_idx
= number_set_get_next(&points_iter
);
581 ppem
= number_set_get_next(&ppems_iter
);
584 control
= control
->next
;
587 if (font
->debug
&& emit_newline
)
588 fprintf(stderr
, "\n");
590 font
->control_data_head
= control_data_head
;
591 font
->control_data_cur
= LLRB_MIN(control_data
, control_data_head
);
597 /* the next functions are intended to restrict the use of LLRB stuff */
598 /* related to control instructions to this file, */
599 /* providing a means to access the data sequentially */
602 TA_control_get_next(FONT
* font
)
604 Node
* node
= (Node
*)font
->control_data_cur
;
610 node
= LLRB_NEXT(control_data
, /* unused */, node
);
612 font
->control_data_cur
= node
;
617 TA_control_get_ctrl(FONT
* font
)
619 Node
* node
= (Node
*)font
->control_data_cur
;
622 return node
? &node
->ctrl
: NULL
;
627 TA_control_point_dir_collect(FONT
* font
,
631 number_range
* control_point_dirs
= font
->control_point_dirs
;
634 /* nothing to do if no data */
635 if (!font
->control_data_head
)
638 if (control_point_dirs
)
640 number_set_free(control_point_dirs
);
641 control_point_dirs
= NULL
;
645 * The PPEM value for one-point segments is always zero; such control
646 * instructions are thus sorted before other control instructions for the
647 * same glyph index -- this fits nicely with the call to
648 * `TA_control_get_next' in the loop of `TA_sfnt_build_delta_exceptions',
649 * assuring proper sequential access to the red-black tree.
653 const Ctrl
* ctrl
= TA_control_get_ctrl(font
);
662 if (ctrl
->type
!= Control_Point_Dir
)
665 /* too large values of font and glyph indices in `ctrl' */
666 /* are handled by later calls of this function */
667 if (font_idx
< ctrl
->font_idx
668 || glyph_idx
< ctrl
->glyph_idx
)
671 /* we store point index and direction together */
672 point_idx
= (ctrl
->point_idx
<< 2)
673 + (ctrl
->x_shift
== TA_DIR_LEFT
? 0
674 : ctrl
->x_shift
== TA_DIR_RIGHT
? 1
677 /* don't care about checking valid point indices */
678 elem
= number_set_new(point_idx
, point_idx
, point_idx
, point_idx
);
679 if (elem
== NUMBERSET_ALLOCATION_ERROR
)
681 number_set_free(control_point_dirs
);
682 return TA_Err_Control_Allocation_Error
;
684 control_point_dirs
= number_set_prepend(control_point_dirs
, elem
);
686 TA_control_get_next(font
);
689 font
->control_point_dirs
= number_set_reverse(control_point_dirs
);
696 TA_control_point_dir_get_next(FONT
* font
,
700 number_range
* control_point_dirs
= font
->control_point_dirs
;
701 number_set_iter
* control_point_dir_iter
= &font
->control_point_dir_iter
;
705 if (!control_point_dir_iter
->range
)
707 control_point_dir_iter
->range
= control_point_dirs
;
708 pd_idx
= number_set_get_first(control_point_dir_iter
);
711 pd_idx
= number_set_get_next(control_point_dir_iter
);
713 *point_idx
= pd_idx
>> 2;
714 *dir
= pd_idx
% 4 == 0 ? TA_DIR_LEFT
715 : pd_idx
% 4 == 1 ? TA_DIR_RIGHT
718 return control_point_dir_iter
->range
!= NULL
;
721 /* end of tacontrol.c */