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 /* a test to check the validity of the first character */
23 /* in a PostScript glyph name -- for simplicity, we include `.' also */
25 const char* namestart_chars
= "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
26 "abcdefghijklmnopqrstuvwxyz"
32 return strchr(namestart_chars
, c
) != NULL
;
37 get_token(char** string_p
)
39 const char* s
= *string_p
;
40 const char* p
= *string_p
;
43 while (*p
&& !isspace(*p
))
51 /* in the following functions, `*string_p' is never '\0'; */
52 /* in case of error, `*string_p' should be set to a meaningful position */
55 get_font_idx(FONT
* font
,
59 const char* s
= *string_p
;
65 font_idx
= strtol(s
, &endptr
, 0);
70 return TA_Err_Deltas_Invalid_Font_Index
;
73 /* there must be a whitespace character after the number */
74 if (errno
|| !isspace(*endptr
))
77 return TA_Err_Deltas_Syntax_Error
;
80 /* we have already tested that the first character in `s' is a digit, */
81 /* so `font_idx' can't be negative */
82 if (font_idx
>= font
->num_sfnts
)
85 return TA_Err_Deltas_Invalid_Font_Index
;
89 *font_idx_p
= font_idx
;
96 get_glyph_idx(FONT
* font
,
101 const char* s
= *string_p
;
105 FT_Face face
= font
->sfnts
[font_idx
].face
;
113 glyph_idx
= strtol(s
, &endptr
, 0);
118 return TA_Err_Deltas_Invalid_Glyph_Index
;
121 /* there must be a whitespace character after the number */
122 if (errno
|| !isspace(*endptr
))
125 return TA_Err_Deltas_Syntax_Error
;
128 /* we have already tested that the first character in `s' is a digit, */
129 /* so `glyph_idx' can't be negative */
130 if (glyph_idx
>= face
->num_glyphs
)
133 return TA_Err_Deltas_Invalid_Glyph_Index
;
136 else if (isnamestart(*s
))
144 s
= get_token(&endptr
);
146 token
= strndup(s
, endptr
- s
);
150 return TA_Err_Deltas_Allocation_Error
;
153 /* explicitly compare with `.notdef' */
154 /* since `FT_Get_Name_Index' returns glyph index 0 */
155 /* for both this glyph name and invalid ones */
156 if (!strcmp(token
, ".notdef"))
160 glyph_idx
= FT_Get_Name_Index(face
, token
);
170 return TA_Err_Deltas_Invalid_Glyph_Name
;
178 return TA_Err_Deltas_Syntax_Error
;
182 *glyph_idx_p
= glyph_idx
;
189 get_range(char** string_p
,
190 number_range
** number_set_p
,
195 const char* s
= *string_p
;
196 number_range
* number_set
= *number_set_p
;
198 size_t s_len
= strcspn(s
, delims
);
203 /* there must be a whitespace character before the delimiter */
204 /* if it is not \0 */
206 && (!s_len
|| !isspace(s
[s_len
- 1])))
208 *string_p
= (char*)(s
+ s_len
);
209 return TA_Err_Deltas_Syntax_Error
;
212 token
= strndup(s
, s_len
);
216 return TA_Err_Deltas_Allocation_Error
;
219 endptr
= (char*)number_set_parse(token
, &number_set
, min
, max
);
221 /* use offset relative to `s' */
222 endptr
= (char*)s
+ (endptr
- token
);
225 if (number_set
== NUMBERSET_ALLOCATION_ERROR
)
228 return TA_Err_Deltas_Allocation_Error
;
233 if (number_set
== NUMBERSET_INVALID_CHARACTER
)
234 return TA_Err_Deltas_Invalid_Character
;
235 else if (number_set
== NUMBERSET_OVERFLOW
)
236 return TA_Err_Deltas_Overflow
;
237 else if (number_set
== NUMBERSET_INVALID_RANGE
)
238 /* this error code should be adjusted by the caller if necessary */
239 return TA_Err_Deltas_Invalid_Point_Range
;
240 else if (number_set
== NUMBERSET_OVERLAPPING_RANGES
)
241 return TA_Err_Deltas_Overlapping_Ranges
;
242 else if (number_set
== NUMBERSET_NOT_ASCENDING
)
243 return TA_Err_Deltas_Ranges_Not_Ascending
;
245 *number_set_p
= number_set
;
252 get_shift(char** string_p
,
255 const char* s
= *string_p
;
261 shift
= strtod(s
, &endptr
);
266 /* this error code should be adjusted by the caller if necessary */
267 return TA_Err_Deltas_Invalid_X_Range
;
270 /* there must be a whitespace character after the number */
271 if (errno
|| !isspace(*endptr
))
274 return TA_Err_Deltas_Syntax_Error
;
277 if (shift
< DELTA_SHIFT_MIN
|| shift
> DELTA_SHIFT_MAX
)
280 return TA_Err_Deltas_Invalid_X_Range
;
285 /* we round the value to a multiple of 1/(2^DELTA_SHIFT) */
286 *shift_p
= (char)(shift
* DELTA_FACTOR
+ (shift
> 0 ? 0.5 : -0.5));
293 * Parse a delta exceptions line.
295 * In case of success (this is, the delta exceptions description in `s' is
296 * valid), `pos' is a pointer to the final zero byte in string `s'. In case
297 * of an error, it points to the offending character in string `s'.
299 * If s is NULL, the function exits immediately, with NULL as the value of
302 * If the user provides a non-NULL `deltas' value, `deltas_parse' stores the
303 * parsed result in `*deltas', allocating the necessary memory. If there is
304 * no data (for example, an empty string or whitespace only) nothing gets
305 * allocated, and `*deltas' is set to NULL.
310 deltas_parse_line(FONT
* font
,
314 int ppem_min
, int ppem_max
)
336 char* pos
= (char*)s
;
343 number_range
* points
= NULL
;
346 number_range
* ppems
= NULL
;
359 State old_state
= state
;
364 while (isspace(*pos
))
377 next_is_space
= isspace(*(pos
+ 1));
382 token1
= get_token(&pos
);
387 token2
= get_token(&pos
);
394 /* possibility 1: <font idx> <glyph name> `p' */
396 && (isdigit(*token2
) || isnamestart(*token2
))
397 && (c
== 'p' && next_is_space
))
399 if (!(error
= get_font_idx(font
, &pos
, &font_idx
)))
400 state
= HAD_FONT_IDX
;
402 /* possibility 2: <glyph name> `p' */
403 else if ((isdigit(*token1
) || isnamestart(*token1
))
404 && (c
== 'p' && next_is_space
))
406 if (!(error
= get_glyph_idx(font
, font_idx
,
408 state
= HAD_GLYPH_IDX
;
414 if (!(error
= get_glyph_idx(font
, font_idx
,
416 state
= HAD_GLYPH_IDX
;
421 if (c
== 'p' && next_is_space
)
432 FT_Face face
= font
->sfnts
[font_idx
].face
;
436 ft_error
= FT_Load_Glyph(face
, glyph_idx
, FT_LOAD_NO_SCALE
);
439 error
= TA_Err_Deltas_Invalid_Glyph
;
443 num_points
= face
->glyph
->outline
.n_points
;
444 if (!(error
= get_range(&pos
, deltas_p
? &points
: NULL
,
445 0, num_points
- 1, "xy@")))
451 /* `x' or `y' or `@' */
468 if (!(error
= get_shift(&pos
, &x_shift
)))
488 if (!(error
= get_shift(&pos
, &y_shift
)))
490 if (error
== TA_Err_Deltas_Invalid_X_Range
)
491 error
= TA_Err_Deltas_Invalid_Y_Range
;
496 if (c
== '@' && next_is_space
)
505 if (!(error
= get_range(&pos
, deltas_p
? &ppems
: NULL
,
506 ppem_min
, ppem_max
, "")))
508 if (error
== TA_Err_Deltas_Invalid_Point_Range
)
509 error
= TA_Err_Deltas_Invalid_Ppem_Range
;
513 /* to make compiler happy */
517 if (old_state
== state
)
521 if (state
== HAD_PPEMS
)
526 Deltas
* deltas
= (Deltas
*)malloc(sizeof (Deltas
));
531 number_set_free(points
);
532 number_set_free(ppems
);
536 return TA_Err_Deltas_Allocation_Error
;
539 deltas
->font_idx
= font_idx
;
540 deltas
->glyph_idx
= glyph_idx
;
541 deltas
->points
= points
;
542 deltas
->x_shift
= x_shift
;
543 deltas
->y_shift
= y_shift
;
544 deltas
->ppems
= ppems
;
554 number_set_free(points
);
555 number_set_free(ppems
);
560 if (!error
&& state
!= START
)
561 error
= TA_Err_Deltas_Syntax_Error
;
571 TA_deltas_free(Deltas
* deltas
)
578 number_set_free(deltas
->points
);
579 number_set_free(deltas
->ppems
);
582 deltas
= deltas
->next
;
588 /* `len' is the length of the returned string */
591 deltas_show_line(FONT
* font
,
596 char glyph_name_buf
[64];
597 char* points_buf
= NULL
;
598 char* ppems_buf
= NULL
;
599 char* deltas_buf
= NULL
;
607 if (deltas
->font_idx
>= font
->num_sfnts
)
610 face
= font
->sfnts
[deltas
->font_idx
].face
;
611 glyph_name_buf
[0] = '\0';
612 if (FT_HAS_GLYPH_NAMES(face
))
613 FT_Get_Glyph_Name(face
, deltas
->glyph_idx
, glyph_name_buf
, 64);
615 points_buf
= number_set_show(deltas
->points
, -1, -1);
618 ppems_buf
= number_set_show(deltas
->ppems
, -1, -1);
622 /* display glyph index if we don't have a glyph name */
624 ret
= asprintf(&deltas_buf
, "%ld %s p %s x %.20g y %.20g @ %s",
628 (double)deltas
->x_shift
/ DELTA_FACTOR
,
629 (double)deltas
->y_shift
/ DELTA_FACTOR
,
632 ret
= asprintf(&deltas_buf
, "%ld %ld p %s x %.20g y %.20g @ %s",
636 (double)deltas
->x_shift
/ DELTA_FACTOR
,
637 (double)deltas
->y_shift
/ DELTA_FACTOR
,
654 TA_deltas_show(FONT
* font
,
661 /* we return an empty string if there is no data */
662 s
= (char*)malloc(1);
677 tmp
= deltas_show_line(font
, &tmp_len
, deltas
);
684 /* append current line to buffer, followed by a newline character */
685 s_len_new
= s_len
+ tmp_len
+ 1;
686 s_new
= (char*)realloc(s
, s_len_new
);
694 strcpy(s_new
+ s_len
- 1, tmp
);
695 s_new
[s_len_new
- 2] = '\n';
696 s_new
[s_len_new
- 1] = '\0';
703 deltas
= deltas
->next
;
710 /* Get a line from a buffer, starting at `pos'. The final EOL */
711 /* character (or character pair) of the line (if existing) gets removed. */
712 /* After the call, `pos' points to the position right after the line in */
713 /* the buffer. The line is allocated with `malloc'; it returns NULL for */
714 /* end of data and allocation errors; the latter can be recognized by a */
715 /* changed value of `pos'. */
720 const char* start
= *pos
;
721 const char* p
= start
;
731 if (*p
== '\n' || *p
== '\r')
755 s
= (char*)malloc(len
+ 1);
760 strncpy(s
, start
, len
);
768 TA_deltas_parse(FONT
* font
,
770 unsigned int* errlinenum_p
,
781 unsigned int linenum
;
787 /* nothing to do if no data */
788 if (!font
->deltas_buf
)
791 bufpos
= font
->deltas_buf
;
797 /* parse line by line */
804 line
= get_line(&bufpos
);
807 if (bufpos
== bufpos_old
) /* end of data */
810 *errlinenum_p
= linenum
;
814 return FT_Err_Out_Of_Memory
;
817 error
= deltas_parse_line(font
,
820 deltas
? &new_deltas
: NULL
,
821 DELTA_PPEM_MIN
, DELTA_PPEM_MAX
);
824 *errlinenum_p
= linenum
;
833 if (deltas
&& new_deltas
)
835 new_deltas
->next
= cur
;
844 /* success; now reverse list to have elements in original order */
868 * the possible shift values in the instructions are indexed as follows:
879 * (note that there is no index for a zero shift).
883 /* end of tadeltas.c */