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_Segment_Left
:
60 case Control_Segment_Right
:
61 case Control_Segment_None
:
67 control
->ppems
= number_set_reverse(ppem_set
);
75 TA_control_prepend(Control
* list
,
88 TA_control_reverse(Control
* list
)
112 TA_control_free(Control
* control
)
119 number_set_free(control
->points
);
120 number_set_free(control
->ppems
);
123 control
= control
->next
;
130 control_show_line(FONT
* font
,
133 char glyph_name_buf
[64];
134 char* points_buf
= NULL
;
135 char* ppems_buf
= NULL
;
147 if (control
->font_idx
>= font
->num_sfnts
)
150 face
= font
->sfnts
[control
->font_idx
].face
;
151 glyph_name_buf
[0] = '\0';
152 if (FT_HAS_GLYPH_NAMES(face
))
153 FT_Get_Glyph_Name(face
, control
->glyph_idx
, glyph_name_buf
, 64);
155 points_buf
= number_set_show(control
->points
, -1, -1);
158 ppems_buf
= number_set_show(control
->ppems
, -1, -1);
162 switch (control
->type
)
164 case Control_Delta_before_IUP
:
165 /* not implemented yet */
168 case Control_Delta_after_IUP
:
169 /* display glyph index if we don't have a glyph name */
171 s
= sdscatprintf(s
, "%ld %s p %s x %.20g y %.20g @ %s",
175 (double)control
->x_shift
/ CONTROL_DELTA_FACTOR
,
176 (double)control
->y_shift
/ CONTROL_DELTA_FACTOR
,
179 s
= sdscatprintf(s
, "%ld %ld p %s x %.20g y %.20g @ %s",
183 (double)control
->x_shift
/ CONTROL_DELTA_FACTOR
,
184 (double)control
->y_shift
/ CONTROL_DELTA_FACTOR
,
188 case Control_Segment_Left
:
189 case Control_Segment_Right
:
190 case Control_Segment_None
:
191 /* display glyph index if we don't have a glyph name */
193 s
= sdscatprintf(s
, "%ld %s %c %s",
196 control
->type
== Control_Segment_Left
? 'l'
197 : control
->type
== Control_Segment_Right
? 'r'
201 s
= sdscatprintf(s
, "%ld %ld %c %s",
204 control
->type
== Control_Segment_Left
? 'l'
205 : control
->type
== Control_Segment_Right
? 'r'
220 TA_control_show(FONT
* font
)
226 Control
* control
= font
->control
;
236 /* append current line to buffer, followed by a newline character */
237 d
= control_show_line(font
, control
);
247 control
= control
->next
;
253 /* we return an empty string if there is no data */
255 res
= (char*)malloc(len
);
265 /* Parse control instructions in `font->control_buf'. */
268 TA_control_parse_buffer(FONT
* font
,
269 char** error_string_p
,
270 unsigned int* errlinenum_p
,
276 Control_Context context
;
279 /* nothing to do if no data */
280 if (!font
->control_buf
)
282 font
->control
= NULL
;
286 TA_control_scanner_init(&context
, font
);
289 /* this is `yyparse' in disguise */
290 bison_error
= TA_control_parse(&context
);
291 TA_control_scanner_done(&context
);
295 if (bison_error
== 2)
296 context
.error
= TA_Err_Control_Allocation_Error
;
299 font
->control
= NULL
;
301 if (context
.error
== TA_Err_Control_Allocation_Error
302 || context
.error
== TA_Err_Control_Flex_Error
)
308 *error_string_p
= strdup(context
.errmsg
);
310 *error_string_p
= strdup(TA_get_error_message(context
.error
));
322 /* construct data for `errline_p' */
323 buf_end
= font
->control_buf
+ font
->control_len
;
325 p_start
= font
->control_buf
;
326 if (context
.errline_num
> 1)
329 while (p_start
< buf_end
)
331 if (*p_start
++ == '\n')
334 if (i
== context
.errline_num
)
341 while (p_end
< buf_end
)
347 *errline_p
= strndup(p_start
, p_end
- p_start
);
349 /* construct data for `error_string_p' */
350 if (context
.error
== TA_Err_Control_Invalid_Font_Index
)
351 sprintf(auxbuf
, " (valid range is [%ld;%ld])",
354 else if (context
.error
== TA_Err_Control_Invalid_Glyph_Index
)
355 sprintf(auxbuf
, " (valid range is [%ld;%ld])",
357 font
->sfnts
[context
.font_idx
].face
->num_glyphs
);
358 else if (context
.error
== TA_Err_Control_Invalid_Shift
)
359 sprintf(auxbuf
, " (valid interval is [%g;%g])",
360 CONTROL_DELTA_SHIFT_MIN
,
361 CONTROL_DELTA_SHIFT_MAX
);
362 else if (context
.error
== TA_Err_Control_Invalid_Range
)
363 sprintf(auxbuf
, " (values must be within [%ld;%ld])",
364 context
.number_set_min
,
365 context
.number_set_max
);
369 ret
= asprintf(error_string_p
, "%s%s",
370 *context
.errmsg
? context
.errmsg
371 : TA_get_error_message(context
.error
),
374 *error_string_p
= NULL
;
377 *errpos_p
= *errline_p
+ context
.errline_pos_left
- 1;
381 *errlinenum_p
= context
.errline_num
;
385 font
->control
= context
.result
;
387 return context
.error
;
391 /* node structure for control instruction data */
393 typedef struct Node Node
;
396 LLRB_ENTRY(Node
) entry
;
401 /* comparison function for our red-black tree */
410 /* sort by font index ... */
411 diff
= e1
->ctrl
.font_idx
- e2
->ctrl
.font_idx
;
415 /* ... then by glyph index ... */
416 diff
= e1
->ctrl
.glyph_idx
- e2
->ctrl
.glyph_idx
;
420 /* ... then by ppem ... */
421 diff
= e1
->ctrl
.ppem
- e2
->ctrl
.ppem
;
425 /* ... then by point index */
426 diff
= e1
->ctrl
.point_idx
- e2
->ctrl
.point_idx
;
429 /* https://graphics.stanford.edu/~seander/bithacks.html#CopyIntegerSign */
430 return (diff
> 0) - (diff
< 0);
434 /* the red-black tree function body */
435 typedef struct control_data control_data
;
437 LLRB_HEAD(control_data
, Node
);
439 /* no trailing semicolon in the next line */
440 LLRB_GENERATE_STATIC(control_data
, Node
, entry
, nodecmp
)
444 TA_control_free_tree(FONT
* font
)
446 control_data
* control_data_head
= (control_data
*)font
->control_data_head
;
447 number_range
* control_point_dirs
= font
->control_point_dirs
;
453 if (!control_data_head
)
456 for (node
= LLRB_MIN(control_data
, control_data_head
);
460 next_node
= LLRB_NEXT(control_data
, control_data_head
, node
);
461 LLRB_REMOVE(control_data
, control_data_head
, node
);
465 free(control_data_head
);
466 number_set_free(control_point_dirs
);
471 TA_control_build_tree(FONT
* font
)
473 Control
* control
= font
->control
;
474 control_data
* control_data_head
;
475 int emit_newline
= 0;
478 font
->control_point_dirs
= NULL
;
479 font
->control_point_dir_iter
.range
= NULL
;
481 /* nothing to do if no data */
484 font
->control_data_head
= NULL
;
485 font
->control_data_cur
= NULL
;
489 control_data_head
= (control_data
*)malloc(sizeof (control_data
));
490 if (!control_data_head
)
491 return FT_Err_Out_Of_Memory
;
493 LLRB_INIT(control_data_head
);
497 Control_Type type
= control
->type
;
498 long font_idx
= control
->font_idx
;
499 long glyph_idx
= control
->glyph_idx
;
500 char x_shift
= control
->x_shift
;
501 char y_shift
= control
->y_shift
;
503 number_set_iter ppems_iter
;
507 ppems_iter
.range
= control
->ppems
;
508 ppem
= number_set_get_first(&ppems_iter
);
510 if (type
== Control_Segment_Left
511 || type
== Control_Segment_Right
512 || type
== Control_Segment_None
)
515 while (ppems_iter
.range
)
517 number_set_iter points_iter
;
522 points_iter
.range
= control
->points
;
523 point_idx
= number_set_get_first(&points_iter
);
525 while (points_iter
.range
)
531 node
= (Node
*)malloc(sizeof (Node
));
533 return FT_Err_Out_Of_Memory
;
535 node
->ctrl
.type
= type
;
536 node
->ctrl
.font_idx
= font_idx
;
537 node
->ctrl
.glyph_idx
= glyph_idx
;
538 node
->ctrl
.ppem
= ppem
;
539 node
->ctrl
.point_idx
= point_idx
;
540 node
->ctrl
.x_shift
= x_shift
;
541 node
->ctrl
.y_shift
= y_shift
;
543 val
= LLRB_INSERT(control_data
, control_data_head
, node
);
546 if (val
&& font
->debug
)
548 /* entry is already present; we ignore it */
556 /* construct Control entry for debugging output */
560 points
.start
= point_idx
;
561 points
.end
= point_idx
;
565 d
.font_idx
= font_idx
;
566 d
.glyph_idx
= glyph_idx
;
573 s
= control_show_line(font
, &d
);
576 fprintf(stderr
, "Control instruction %s ignored.\n", s
);
583 point_idx
= number_set_get_next(&points_iter
);
586 ppem
= number_set_get_next(&ppems_iter
);
589 control
= control
->next
;
592 if (font
->debug
&& emit_newline
)
593 fprintf(stderr
, "\n");
595 font
->control_data_head
= control_data_head
;
596 font
->control_data_cur
= LLRB_MIN(control_data
, control_data_head
);
602 /* the next functions are intended to restrict the use of LLRB stuff */
603 /* related to control instructions to this file, */
604 /* providing a means to access the data sequentially */
607 TA_control_get_next(FONT
* font
)
609 Node
* node
= (Node
*)font
->control_data_cur
;
615 node
= LLRB_NEXT(control_data
, /* unused */, node
);
617 font
->control_data_cur
= node
;
622 TA_control_get_ctrl(FONT
* font
)
624 Node
* node
= (Node
*)font
->control_data_cur
;
627 return node
? &node
->ctrl
: NULL
;
632 TA_control_point_dir_collect(FONT
* font
,
636 number_range
* control_point_dirs
= font
->control_point_dirs
;
639 /* nothing to do if no data */
640 if (!font
->control_data_head
)
643 if (control_point_dirs
)
645 number_set_free(control_point_dirs
);
646 control_point_dirs
= NULL
;
650 * The PPEM value for one-point segments is always zero; such control
651 * instructions are thus sorted before other control instructions for the
652 * same glyph index -- this fits nicely with the call to
653 * `TA_control_get_next' in the loop of `TA_sfnt_build_delta_exceptions',
654 * assuring proper sequential access to the red-black tree.
658 const Ctrl
* ctrl
= TA_control_get_ctrl(font
);
667 if (!(ctrl
->type
== Control_Segment_Left
668 || ctrl
->type
== Control_Segment_Right
669 || ctrl
->type
== Control_Segment_None
))
672 /* too large values of font and glyph indices in `ctrl' */
673 /* are handled by later calls of this function */
674 if (font_idx
< ctrl
->font_idx
675 || glyph_idx
< ctrl
->glyph_idx
)
678 /* we store point index and direction together */
679 point_idx
= (ctrl
->point_idx
<< 2)
680 + (ctrl
->type
== Control_Segment_Left
? 0
681 : ctrl
->type
== Control_Segment_Right
? 1
684 /* don't care about checking valid point indices */
685 elem
= number_set_new(point_idx
, point_idx
, point_idx
, point_idx
);
686 if (elem
== NUMBERSET_ALLOCATION_ERROR
)
688 number_set_free(control_point_dirs
);
689 return TA_Err_Control_Allocation_Error
;
691 control_point_dirs
= number_set_prepend(control_point_dirs
, elem
);
693 TA_control_get_next(font
);
696 font
->control_point_dirs
= number_set_reverse(control_point_dirs
);
703 TA_control_point_dir_get_next(FONT
* font
,
707 number_range
* control_point_dirs
= font
->control_point_dirs
;
708 number_set_iter
* control_point_dir_iter
= &font
->control_point_dir_iter
;
712 if (!control_point_dir_iter
->range
)
714 control_point_dir_iter
->range
= control_point_dirs
;
715 pd_idx
= number_set_get_first(control_point_dir_iter
);
718 pd_idx
= number_set_get_next(control_point_dir_iter
);
720 *point_idx
= pd_idx
>> 2;
721 *dir
= pd_idx
% 4 == 0 ? TA_DIR_LEFT
722 : pd_idx
% 4 == 1 ? TA_DIR_RIGHT
725 return control_point_dir_iter
->range
!= NULL
;
728 /* end of tacontrol.c */