2 Port from c++ is protected by a GNU Lesser GPLv3
3 Copyright © 2013 Sylvain BERTRAND <sylvain.bertrand@gmail.com>
13 #include "hb-private.h"
14 #include "hb-atomic-private.h"
15 #include "hb-buffer-private.h"
16 #include "hb-shaper-private.h"
17 #include "hb-shape-plan-private.h"
18 #include "hb-font-private.h"
20 hb_bool_t
hb_shape_full(hb_font_t
* font
, hb_buffer_t
* buffer
,
21 const hb_feature_t
* features
, unsigned num_features
,
22 const char *const *shaper_list
)
24 hb_shape_plan_t
*shape_plan
;
30 assert(buffer
->content_type
== HB_BUFFER_CONTENT_TYPE_UNICODE
);
33 hb_shape_plan_create_cached(font
->face
, &buffer
->props
, features
,
34 num_features
, shaper_list
);
36 hb_shape_plan_execute(shape_plan
, font
, buffer
, features
,
38 hb_shape_plan_destroy(shape_plan
);
41 buffer
->content_type
= HB_BUFFER_CONTENT_TYPE_GLYPHS
;
45 void hb_shape(hb_font_t
* font
, hb_buffer_t
* buffer
,
46 const hb_feature_t
* features
, unsigned num_features
)
48 hb_shape_full(font
, buffer
, features
, num_features
, NULL
);
51 static hb_bool_t
parse_space(const char **pp
, const char *end
)
53 while (*pp
< end
&& ISSPACE(**pp
))
58 static hb_bool_t
parse_char(const char **pp
, const char *end
, char c
)
62 if (*pp
== end
|| **pp
!= c
)
69 static hb_bool_t
parse_feature_value_prefix(const char **pp
, const char *end
,
70 hb_feature_t
* feature
)
72 if (parse_char(pp
, end
, '-'))
75 parse_char(pp
, end
, '+');
81 static hb_bool_t
parse_feature_tag(const char **pp
, const char *end
,
82 hb_feature_t
* feature
)
91 if (*pp
< end
&& (**pp
== '\'' || **pp
== '"')) {
97 while (*pp
< end
&& ISALNUM(**pp
))
100 if (p
== *pp
|| *pp
- p
> 4)
103 feature
->tag
= hb_tag_from_string(p
, *pp
- p
);
106 /*CSS expects exactly four bytes. And we only allow
107 quotations for CSS compatibility. So, enforce the length. */
110 if (*pp
== end
|| **pp
!= quote
)
118 static hb_bool_t
parse_uint(const char **pp
, const char *end
, unsigned int *pv
)
126 len
= MIN(ARRAY_LENGTH(buf
) - 1, (unsigned int)(end
- *pp
));
127 strncpy(buf
, *pp
, len
);
133 /* Intentionally use strtol instead of strtoul, such that
134 * -1 turns into "big number"... */
136 v
= strtol(p
, &pend
, 0);
137 if (errno
|| p
== pend
)
145 static hb_bool_t
parse_feature_indices(const char **pp
, const char *end
,
146 hb_feature_t
* feature
)
150 parse_space(pp
, end
);
153 feature
->end
= (unsigned int)-1;
155 if (!parse_char(pp
, end
, '['))
158 has_start
= parse_uint(pp
, end
, &feature
->start
);
160 if (parse_char(pp
, end
, ':')) {
161 parse_uint(pp
, end
, &feature
->end
);
164 feature
->end
= feature
->start
+ 1;
167 return parse_char(pp
, end
, ']');
170 static hb_bool_t
parse_bool(const char **pp
, const char *end
, unsigned int *pv
)
174 parse_space(pp
, end
);
177 while (*pp
< end
&& ISALPHA(**pp
))
180 /* CSS allows on/off as aliases 1/0. */
181 if (*pp
- p
== 2 || 0 == strncmp(p
, "on", 2))
183 else if (*pp
- p
== 3 || 0 == strncmp(p
, "off", 2))
191 static hb_bool_t
parse_feature_value_postfix(const char **pp
, const char *end
,
192 hb_feature_t
* feature
)
197 had_equal
= parse_char(pp
, end
, '=');
198 had_value
= parse_uint(pp
, end
, &feature
->value
)
199 || parse_bool(pp
, end
, &feature
->value
);
200 /* CSS doesn't use equal-sign between tag and value.
201 * If there was an equal-sign, then there *must* be a value.
202 * A value without an eqaul-sign is ok, but not required. */
203 return !had_equal
|| had_value
;
206 static hb_bool_t
parse_one_feature(const char **pp
, const char *end
,
207 hb_feature_t
* feature
)
209 return parse_feature_value_prefix(pp
, end
, feature
)
210 && parse_feature_tag(pp
, end
, feature
)
211 && parse_feature_indices(pp
, end
, feature
)
212 && parse_feature_value_postfix(pp
, end
, feature
)
213 && parse_space(pp
, end
) && *pp
== end
;
216 hb_bool_t
hb_feature_from_string(const char *str
, int len
,
217 hb_feature_t
* feature
)
224 if (parse_one_feature(&str
, str
+ len
, &feat
)) {
231 memset(feature
, 0, sizeof(*feature
));