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.
22 #include "llrb.h" /* a red-black tree implementation */
23 #include "tadeltas-bison.h"
26 TA_deltas_new(long font_idx
,
28 number_range
* point_set
,
31 number_range
* ppem_set
)
36 deltas
= (Deltas
*)malloc(sizeof (Deltas
));
40 deltas
->font_idx
= font_idx
;
41 deltas
->glyph_idx
= glyph_idx
;
42 deltas
->points
= number_set_reverse(point_set
);
44 /* we round shift values to multiples of 1/(2^DELTA_SHIFT) */
45 deltas
->x_shift
= (char)(x_shift
* DELTA_FACTOR
46 + (x_shift
> 0 ? 0.5 : -0.5));
47 deltas
->y_shift
= (char)(y_shift
* DELTA_FACTOR
48 + (y_shift
> 0 ? 0.5 : -0.5));
50 deltas
->ppems
= number_set_reverse(ppem_set
);
58 TA_deltas_prepend(Deltas
* list
,
71 TA_deltas_reverse(Deltas
* list
)
95 TA_deltas_free(Deltas
* deltas
)
102 number_set_free(deltas
->points
);
103 number_set_free(deltas
->ppems
);
106 deltas
= deltas
->next
;
112 /* `len' is the length of the returned string */
115 deltas_show_line(FONT
* font
,
120 char glyph_name_buf
[64];
121 char* points_buf
= NULL
;
122 char* ppems_buf
= NULL
;
123 char* deltas_buf
= NULL
;
131 if (deltas
->font_idx
>= font
->num_sfnts
)
134 face
= font
->sfnts
[deltas
->font_idx
].face
;
135 glyph_name_buf
[0] = '\0';
136 if (FT_HAS_GLYPH_NAMES(face
))
137 FT_Get_Glyph_Name(face
, deltas
->glyph_idx
, glyph_name_buf
, 64);
139 points_buf
= number_set_show(deltas
->points
, -1, -1);
142 ppems_buf
= number_set_show(deltas
->ppems
, -1, -1);
146 /* display glyph index if we don't have a glyph name */
148 ret
= asprintf(&deltas_buf
, "%ld %s p %s x %.20g y %.20g @ %s",
152 (double)deltas
->x_shift
/ DELTA_FACTOR
,
153 (double)deltas
->y_shift
/ DELTA_FACTOR
,
156 ret
= asprintf(&deltas_buf
, "%ld %ld p %s x %.20g y %.20g @ %s",
160 (double)deltas
->x_shift
/ DELTA_FACTOR
,
161 (double)deltas
->y_shift
/ DELTA_FACTOR
,
178 TA_deltas_show(FONT
* font
,
185 /* we return an empty string if there is no data */
186 s
= (char*)malloc(1);
201 tmp
= deltas_show_line(font
, &tmp_len
, deltas
);
208 /* append current line to buffer, followed by a newline character */
209 s_len_new
= s_len
+ tmp_len
+ 1;
210 s_new
= (char*)realloc(s
, s_len_new
);
218 strcpy(s_new
+ s_len
- 1, tmp
);
219 s_new
[s_len_new
- 2] = '\n';
220 s_new
[s_len_new
- 1] = '\0';
227 deltas
= deltas
->next
;
234 /* Parse delta exceptions in `font->deltas_buf'. */
237 TA_deltas_parse_buffer(FONT
* font
,
239 char** error_string_p
,
240 unsigned int* errlinenum_p
,
246 Deltas_Context context
;
249 /* nothing to do if no data */
250 if (!font
->deltas_buf
)
257 TA_deltas_scanner_init(&context
, font
);
260 /* this is `yyparse' in disguise */
261 bison_error
= TA_deltas_parse(&context
);
262 TA_deltas_scanner_done(&context
);
266 if (bison_error
== 2)
267 context
.error
= TA_Err_Deltas_Allocation_Error
;
273 if (context
.error
== TA_Err_Deltas_Allocation_Error
274 || context
.error
== TA_Err_Deltas_Flex_Error
)
280 *error_string_p
= strdup(context
.errmsg
);
282 *error_string_p
= strdup(TA_get_error_message(context
.error
));
294 /* construct data for `errline_p' */
295 buf_end
= font
->deltas_buf
+ font
->deltas_len
;
297 p_start
= font
->deltas_buf
;
298 if (context
.errline_num
> 1)
301 while (p_start
< buf_end
)
303 if (*p_start
++ == '\n')
306 if (i
== context
.errline_num
)
313 while (p_end
< buf_end
)
319 *errline_p
= strndup(p_start
, p_end
- p_start
);
321 /* construct data for `error_string_p' */
322 if (context
.error
== TA_Err_Deltas_Invalid_Font_Index
)
323 sprintf(auxbuf
, " (valid range is [%ld;%ld])",
326 else if (context
.error
== TA_Err_Deltas_Invalid_Glyph_Index
)
327 sprintf(auxbuf
, " (valid range is [%ld;%ld])",
329 font
->sfnts
[context
.font_idx
].face
->num_glyphs
);
330 else if (context
.error
== TA_Err_Deltas_Invalid_Shift
)
331 sprintf(auxbuf
, " (valid interval is [%g;%g])",
334 else if (context
.error
== TA_Err_Deltas_Invalid_Range
)
335 sprintf(auxbuf
, " (values must be within [%ld;%ld])",
336 context
.number_set_min
,
337 context
.number_set_max
);
341 ret
= asprintf(error_string_p
, "%s%s",
342 *context
.errmsg
? context
.errmsg
343 : TA_get_error_message(context
.error
),
346 *error_string_p
= NULL
;
349 *errpos_p
= *errline_p
+ context
.errline_pos_left
- 1;
353 *errlinenum_p
= context
.errline_num
;
359 *deltas
= context
.result
;
361 TA_deltas_free(context
.result
);
364 return context
.error
;
368 /* node structure for delta exception data */
370 typedef struct Node Node
;
373 LLRB_ENTRY(Node
) entry
;
378 /* comparison function for our red-black tree */
387 /* sort by font index ... */
388 diff
= e1
->delta
.font_idx
- e2
->delta
.font_idx
;
392 /* ... then by glyph index ... */
393 diff
= e1
->delta
.glyph_idx
- e2
->delta
.glyph_idx
;
397 /* ... then by ppem ... */
398 diff
= e1
->delta
.ppem
- e2
->delta
.ppem
;
402 /* ... then by point index */
403 diff
= e1
->delta
.point_idx
- e2
->delta
.point_idx
;
406 /* https://graphics.stanford.edu/~seander/bithacks.html#CopyIntegerSign */
407 return (diff
> 0) - (diff
< 0);
411 /* the red-black tree function body */
412 typedef struct deltas_data deltas_data
;
414 LLRB_HEAD(deltas_data
, Node
);
416 /* no trailing semicolon in the next line */
417 LLRB_GENERATE_STATIC(deltas_data
, Node
, entry
, nodecmp
)
421 TA_deltas_free_tree(FONT
* font
)
423 deltas_data
* deltas_data_head
= (deltas_data
*)font
->deltas_data_head
;
429 if (!deltas_data_head
)
432 for (node
= LLRB_MIN(deltas_data
, deltas_data_head
);
436 next_node
= LLRB_NEXT(deltas_data
, deltas_data_head
, node
);
437 LLRB_REMOVE(deltas_data
, deltas_data_head
, node
);
441 free(deltas_data_head
);
446 TA_deltas_build_tree(FONT
* font
,
449 deltas_data
* deltas_data_head
;
450 int emit_newline
= 0;
453 /* nothing to do if no data */
456 font
->deltas_data_head
= NULL
;
460 deltas_data_head
= (deltas_data
*)malloc(sizeof (deltas_data
));
461 if (!deltas_data_head
)
462 return FT_Err_Out_Of_Memory
;
464 LLRB_INIT(deltas_data_head
);
468 long font_idx
= deltas
->font_idx
;
469 long glyph_idx
= deltas
->glyph_idx
;
470 char x_shift
= deltas
->x_shift
;
471 char y_shift
= deltas
->y_shift
;
473 number_set_iter ppems_iter
;
477 ppems_iter
.range
= deltas
->ppems
;
478 ppem
= number_set_get_first(&ppems_iter
);
480 while (ppems_iter
.range
)
482 number_set_iter points_iter
;
486 points_iter
.range
= deltas
->points
;
487 point_idx
= number_set_get_first(&points_iter
);
489 while (points_iter
.range
)
495 node
= (Node
*)malloc(sizeof (Node
));
497 return FT_Err_Out_Of_Memory
;
499 node
->delta
.font_idx
= font_idx
;
500 node
->delta
.glyph_idx
= glyph_idx
;
501 node
->delta
.ppem
= ppem
;
502 node
->delta
.point_idx
= point_idx
;
503 node
->delta
.x_shift
= x_shift
;
504 node
->delta
.y_shift
= y_shift
;
506 val
= LLRB_INSERT(deltas_data
, deltas_data_head
, node
);
509 if (val
&& font
->debug
)
511 /* entry is already present; we ignore it */
520 /* construct Deltas entry for debugging output */
524 points
.start
= point_idx
;
525 points
.end
= point_idx
;
528 deltas
.font_idx
= font_idx
;
529 deltas
.glyph_idx
= glyph_idx
;
530 deltas
.points
= &points
;
531 deltas
.x_shift
= x_shift
;
532 deltas
.y_shift
= y_shift
;
533 deltas
.ppems
= &ppems
;
536 s
= deltas_show_line(font
, &s_len
, &deltas
);
539 fprintf(stderr
, "Delta exception %s ignored.\n", s
);
546 point_idx
= number_set_get_next(&points_iter
);
549 ppem
= number_set_get_next(&ppems_iter
);
552 deltas
= deltas
->next
;
555 if (font
->debug
&& emit_newline
)
556 fprintf(stderr
, "\n");
558 font
->deltas_data_head
= deltas_data_head
;
559 font
->deltas_data_cur
= LLRB_MIN(deltas_data
, deltas_data_head
);
565 /* the next functions are intended to restrict the use of LLRB stuff */
566 /* related to delta exceptions to this file, */
567 /* providing a means to access the data sequentially */
570 TA_deltas_get_next(FONT
* font
)
572 Node
* node
= (Node
*)font
->deltas_data_cur
;
578 node
= LLRB_NEXT(deltas_data
, /* unused */, node
);
580 font
->deltas_data_cur
= node
;
585 TA_deltas_get_delta(FONT
* font
)
587 Node
* node
= (Node
*)font
->deltas_data_cur
;
590 return node
? &node
->delta
: NULL
;
593 /* end of tadeltas.c */