add explicit freetype2 linking
[charfbuzz.git] / hb-shape.c
blob00628cd3079786a1cf9c2534458ceeac98bcc9b6
1 /*
2 Port from c++ is protected by a GNU Lesser GPLv3
3 Copyright © 2013 Sylvain BERTRAND <sylvain.bertrand@gmail.com>
4 <sylware@legeek.net>
5 */
6 #include <stddef.h>
7 #include <assert.h>
8 #include <string.h>
9 #include <stdlib.h>
10 #include <errno.h>
12 #include "hb.h"
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;
25 hb_bool_t res;
27 if (!buffer->len)
28 return TRUE;
30 assert(buffer->content_type == HB_BUFFER_CONTENT_TYPE_UNICODE);
32 shape_plan =
33 hb_shape_plan_create_cached(font->face, &buffer->props, features,
34 num_features, shaper_list);
35 res =
36 hb_shape_plan_execute(shape_plan, font, buffer, features,
37 num_features);
38 hb_shape_plan_destroy(shape_plan);
40 if (res)
41 buffer->content_type = HB_BUFFER_CONTENT_TYPE_GLYPHS;
42 return res;
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))
54 (*pp)++;
55 return TRUE;
58 static hb_bool_t parse_char(const char **pp, const char *end, char c)
60 parse_space(pp, end);
62 if (*pp == end || **pp != c)
63 return FALSE;
65 (*pp)++;
66 return TRUE;
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, '-'))
73 feature->value = 0;
74 else {
75 parse_char(pp, end, '+');
76 feature->value = 1;
78 return TRUE;
81 static hb_bool_t parse_feature_tag(const char **pp, const char *end,
82 hb_feature_t * feature)
84 char quote;
85 const char *p;
87 parse_space(pp, end);
89 quote = 0;
91 if (*pp < end && (**pp == '\'' || **pp == '"')) {
92 quote = **pp;
93 (*pp)++;
96 p = *pp;
97 while (*pp < end && ISALNUM(**pp))
98 (*pp)++;
100 if (p == *pp || *pp - p > 4)
101 return FALSE;
103 feature->tag = hb_tag_from_string(p, *pp - p);
105 if (quote) {
106 /*CSS expects exactly four bytes. And we only allow
107 quotations for CSS compatibility. So, enforce the length. */
108 if (*pp - p != 4)
109 return FALSE;
110 if (*pp == end || **pp != quote)
111 return FALSE;
112 (*pp)++;
115 return TRUE;
118 static hb_bool_t parse_uint(const char **pp, const char *end, unsigned int *pv)
120 char buf[32];
121 unsigned int len;
122 char *p;
123 char *pend;
124 unsigned int v;
126 len = MIN(ARRAY_LENGTH(buf) - 1, (unsigned int)(end - *pp));
127 strncpy(buf, *pp, len);
128 buf[len] = '\0';
130 p = buf;
131 pend = p;
133 /* Intentionally use strtol instead of strtoul, such that
134 * -1 turns into "big number"... */
135 errno = 0;
136 v = strtol(p, &pend, 0);
137 if (errno || p == pend)
138 return FALSE;
140 *pv = v;
141 *pp += pend - p;
142 return TRUE;
145 static hb_bool_t parse_feature_indices(const char **pp, const char *end,
146 hb_feature_t * feature)
148 hb_bool_t has_start;
150 parse_space(pp, end);
152 feature->start = 0;
153 feature->end = (unsigned int)-1;
155 if (!parse_char(pp, end, '['))
156 return TRUE;
158 has_start = parse_uint(pp, end, &feature->start);
160 if (parse_char(pp, end, ':')) {
161 parse_uint(pp, end, &feature->end);
162 } else {
163 if (has_start)
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)
172 const char *p;
174 parse_space(pp, end);
176 p = *pp;
177 while (*pp < end && ISALPHA(**pp))
178 (*pp)++;
180 /* CSS allows on/off as aliases 1/0. */
181 if (*pp - p == 2 || 0 == strncmp(p, "on", 2))
182 *pv = 1;
183 else if (*pp - p == 3 || 0 == strncmp(p, "off", 2))
184 *pv = 0;
185 else
186 return FALSE;
188 return TRUE;
191 static hb_bool_t parse_feature_value_postfix(const char **pp, const char *end,
192 hb_feature_t * feature)
194 hb_bool_t had_equal;
195 hb_bool_t had_value;
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)
219 hb_feature_t feat;
221 if (len < 0)
222 len = strlen(str);
224 if (parse_one_feature(&str, str + len, &feat)) {
225 if (feature)
226 *feature = feat;
227 return TRUE;
230 if (feature)
231 memset(feature, 0, sizeof(*feature));
232 return FALSE;