1 /*
2 * This file is part of LibCSS.
3 * Licensed under the MIT License,
4 * http://www.opensource.org/licenses/mit-license.php
5 * Copyright 2009 John-Mark Bell <jmb@netsurf-browser.org>
6 */
7
8 #include <assert.h>
9 #include <string.h>
10
11 #include "bytecode/bytecode.h"
12 #include "bytecode/opcodes.h"
13 #include "parse/properties/properties.h"
14 #include "parse/properties/utils.h"
15
16
parse_system_font(css_language * c,css_style * result,css_system_font * system_font)17 static css_error parse_system_font(css_language *c,
18 css_style *result, css_system_font *system_font)
19 {
20 css_error error;
21 bool match;
22
23 /* style */
24 switch (system_font->style) {
25 case CSS_FONT_STYLE_NORMAL:
26 error = css__stylesheet_style_appendOPV(result, CSS_PROP_FONT_STYLE, 0, FONT_STYLE_NORMAL);
27 break;
28
29 case CSS_FONT_STYLE_ITALIC:
30 error = css__stylesheet_style_appendOPV(result, CSS_PROP_FONT_STYLE, 0, FONT_STYLE_ITALIC);
31 break;
32
33 case CSS_FONT_STYLE_OBLIQUE:
34 error = css__stylesheet_style_appendOPV(result, CSS_PROP_FONT_STYLE, 0, FONT_STYLE_OBLIQUE);
35 break;
36
37 default:
38 error = CSS_BADPARM;
39 break;
40 }
41 if (error != CSS_OK)
42 return error;
43
44 /* variant */
45 switch (system_font->variant) {
46 case CSS_FONT_VARIANT_NORMAL:
47 error = css__stylesheet_style_appendOPV(result, CSS_PROP_FONT_VARIANT, 0, FONT_VARIANT_NORMAL);
48 break;
49
50 case CSS_FONT_VARIANT_SMALL_CAPS:
51 error = css__stylesheet_style_appendOPV(result, CSS_PROP_FONT_VARIANT, 0, FONT_VARIANT_SMALL_CAPS);
52 break;
53
54 default:
55 error = CSS_BADPARM;
56 break;
57 }
58 if (error != CSS_OK)
59 return error;
60
61 /* weight */
62 switch(system_font->weight) {
63 case CSS_FONT_WEIGHT_NORMAL:
64 error = css__stylesheet_style_appendOPV(result, CSS_PROP_FONT_WEIGHT, 0, FONT_WEIGHT_NORMAL);
65 break;
66
67 case CSS_FONT_WEIGHT_BOLD:
68 error = css__stylesheet_style_appendOPV(result, CSS_PROP_FONT_WEIGHT, 0, FONT_WEIGHT_BOLD);
69 break;
70
71 case CSS_FONT_WEIGHT_BOLDER:
72 error = css__stylesheet_style_appendOPV(result, CSS_PROP_FONT_WEIGHT, 0, FONT_WEIGHT_BOLDER);
73 break;
74
75 case CSS_FONT_WEIGHT_LIGHTER:
76 error = css__stylesheet_style_appendOPV(result, CSS_PROP_FONT_WEIGHT, 0, FONT_WEIGHT_LIGHTER);
77 break;
78
79 case CSS_FONT_WEIGHT_100:
80 error = css__stylesheet_style_appendOPV(result, CSS_PROP_FONT_WEIGHT, 0, FONT_WEIGHT_100);
81 break;
82
83 case CSS_FONT_WEIGHT_200:
84 error = css__stylesheet_style_appendOPV(result, CSS_PROP_FONT_WEIGHT, 0, FONT_WEIGHT_200);
85 break;
86
87 case CSS_FONT_WEIGHT_300:
88 error = css__stylesheet_style_appendOPV(result, CSS_PROP_FONT_WEIGHT, 0, FONT_WEIGHT_300);
89 break;
90
91 case CSS_FONT_WEIGHT_400:
92 error = css__stylesheet_style_appendOPV(result, CSS_PROP_FONT_WEIGHT, 0, FONT_WEIGHT_400);
93 break;
94
95 case CSS_FONT_WEIGHT_500:
96 error = css__stylesheet_style_appendOPV(result, CSS_PROP_FONT_WEIGHT, 0, FONT_WEIGHT_500);
97 break;
98
99 case CSS_FONT_WEIGHT_600:
100 error = css__stylesheet_style_appendOPV(result, CSS_PROP_FONT_WEIGHT, 0, FONT_WEIGHT_600);
101 break;
102
103 case CSS_FONT_WEIGHT_700:
104 error = css__stylesheet_style_appendOPV(result, CSS_PROP_FONT_WEIGHT, 0, FONT_WEIGHT_700);
105 break;
106
107 case CSS_FONT_WEIGHT_800:
108 error = css__stylesheet_style_appendOPV(result, CSS_PROP_FONT_WEIGHT, 0, FONT_WEIGHT_800);
109 break;
110
111 case CSS_FONT_WEIGHT_900:
112 error = css__stylesheet_style_appendOPV(result, CSS_PROP_FONT_WEIGHT, 0, FONT_WEIGHT_900);
113 break;
114
115 default:
116 error = CSS_BADPARM;
117 break;
118 }
119 if (error != CSS_OK)
120 return error;
121
122 /* size */
123 error = css__stylesheet_style_appendOPV(result, CSS_PROP_FONT_SIZE, 0, FONT_SIZE_DIMENSION);
124 if (error != CSS_OK)
125 return error;
126
127 error = css__stylesheet_style_vappend(result, 2, system_font->size.size, system_font->size.unit);
128 if (error != CSS_OK)
129 return error;
130
131 /* line height */
132 error = css__stylesheet_style_appendOPV(result, CSS_PROP_LINE_HEIGHT, 0, LINE_HEIGHT_DIMENSION);
133 if (error != CSS_OK)
134 return error;
135
136 error = css__stylesheet_style_vappend(result, 2, system_font->line_height.size, system_font->line_height.unit);
137 if (error != CSS_OK)
138 return error;
139
140 /* font family */
141 if ((lwc_string_caseless_isequal(system_font->family, c->strings[SERIF], &match) == lwc_error_ok && match))
142 error = css__stylesheet_style_appendOPV(result, CSS_PROP_FONT_FAMILY, 0, FONT_FAMILY_SERIF);
143 else if ((lwc_string_caseless_isequal(system_font->family, c->strings[SANS_SERIF], &match) == lwc_error_ok && match))
144 error = css__stylesheet_style_appendOPV(result, CSS_PROP_FONT_FAMILY, 0, FONT_FAMILY_SANS_SERIF);
145 else if ((lwc_string_caseless_isequal(system_font->family, c->strings[CURSIVE], &match) == lwc_error_ok && match))
146 error = css__stylesheet_style_appendOPV(result, CSS_PROP_FONT_FAMILY, 0, FONT_FAMILY_CURSIVE);
147 else if ((lwc_string_caseless_isequal(system_font->family, c->strings[FANTASY], &match) == lwc_error_ok && match))
148 error = css__stylesheet_style_appendOPV(result, CSS_PROP_FONT_FAMILY, 0, FONT_FAMILY_FANTASY);
149 else if ((lwc_string_caseless_isequal(system_font->family, c->strings[MONOSPACE], &match) == lwc_error_ok && match))
150 error = css__stylesheet_style_appendOPV(result, CSS_PROP_FONT_FAMILY, 0, FONT_FAMILY_MONOSPACE);
151 else {
152 uint32_t snumber;
153
154 error = css__stylesheet_string_add(c->sheet, lwc_string_ref(system_font->family), &snumber);
155 if (error != CSS_OK)
156 return error;
157
158 error = css__stylesheet_style_appendOPV(result, CSS_PROP_FONT_FAMILY, 0, FONT_FAMILY_STRING);
159 if (error != CSS_OK)
160 return error;
161
162 error = css__stylesheet_style_append(result, snumber);
163 }
164 if (error != CSS_OK)
165 return error;
166
167 error = css__stylesheet_style_append(result, FONT_FAMILY_END);
168
169 return error;
170 }
171
172 /**
173 * Parse font
174 *
175 * \param c Parsing context
176 * \param vector Vector of tokens to process
177 * \param ctx Pointer to vector iteration context
178 * \param result Pointer to location to receive resulting style
179 * \return CSS_OK on success,
180 * CSS_NOMEM on memory exhaustion,
181 * CSS_INVALID if the input is not valid
182 *
183 * Post condition: \a *ctx is updated with the next token to process
184 * If the input is invalid, then \a *ctx remains unchanged.
185 */
css__parse_font(css_language * c,const parserutils_vector * vector,int * ctx,css_style * result)186 css_error css__parse_font(css_language *c,
187 const parserutils_vector *vector, int *ctx,
188 css_style *result)
189 {
190 const css_token *token;
191 css_error error;
192 int orig_ctx = *ctx;
193 int prev_ctx;
194 css_system_font system_font;
195
196 bool style = true;
197 bool variant = true;
198 bool weight = true;
199 bool line_height = true;
200 css_style *style_style;
201 css_style *variant_style;
202 css_style *weight_style;
203 css_style *size_style;
204 css_style *line_height_style;
205 css_style *family_style;
206 int svw;
207
208 /* Firstly, handle inherit */
209 token = parserutils_vector_peek(vector, *ctx);
210 if (token == NULL)
211 return CSS_INVALID;
212
213 if (is_css_inherit(c, token)) {
214 error = css_stylesheet_style_inherit(result, CSS_PROP_FONT_STYLE);
215 if (error != CSS_OK)
216 return error;
217
218 error = css_stylesheet_style_inherit(result, CSS_PROP_FONT_VARIANT);
219 if (error != CSS_OK)
220 return error;
221
222 error = css_stylesheet_style_inherit(result, CSS_PROP_FONT_WEIGHT);
223 if (error != CSS_OK)
224 return error;
225
226 error = css_stylesheet_style_inherit(result, CSS_PROP_FONT_SIZE);
227 if (error != CSS_OK)
228 return error;
229
230 error = css_stylesheet_style_inherit(result, CSS_PROP_LINE_HEIGHT);
231 if (error != CSS_OK)
232 return error;
233
234 error = css_stylesheet_style_inherit(result, CSS_PROP_FONT_FAMILY);
235 if (error == CSS_OK)
236 parserutils_vector_iterate(vector, ctx);
237
238 return error;
239 }
240
241 /* Perhaps an unknown font name; ask the client */
242 if ((token->type == CSS_TOKEN_IDENT) &&
243 (c->sheet->font != NULL) &&
244 (c->sheet->font(c->sheet->font_pw,
245 token->idata,
246 &system_font) == CSS_OK)) {
247
248 error = parse_system_font(c, result, &system_font);
249
250 if (error == CSS_OK)
251 parserutils_vector_iterate(vector, ctx);
252
253 return error;
254 }
255
256
257 /* allocate styles */
258 error = css__stylesheet_style_create(c->sheet, &style_style);
259 if (error != CSS_OK)
260 return error;
261
262 error = css__stylesheet_style_create(c->sheet, &variant_style);
263 if (error != CSS_OK) {
264 css__stylesheet_style_destroy(style_style);
265 return error;
266 }
267
268 error = css__stylesheet_style_create(c->sheet, &weight_style);
269 if (error != CSS_OK) {
270 css__stylesheet_style_destroy(style_style);
271 css__stylesheet_style_destroy(variant_style);
272 return error;
273 }
274
275 error = css__stylesheet_style_create(c->sheet, &size_style);
276 if (error != CSS_OK) {
277 css__stylesheet_style_destroy(style_style);
278 css__stylesheet_style_destroy(variant_style);
279 css__stylesheet_style_destroy(weight_style);
280 return error;
281 }
282
283 error = css__stylesheet_style_create(c->sheet, &line_height_style);
284 if (error != CSS_OK) {
285 css__stylesheet_style_destroy(style_style);
286 css__stylesheet_style_destroy(variant_style);
287 css__stylesheet_style_destroy(weight_style);
288 css__stylesheet_style_destroy(size_style);
289 return error;
290 }
291
292 error = css__stylesheet_style_create(c->sheet, &family_style);
293 if (error != CSS_OK) {
294 css__stylesheet_style_destroy(style_style);
295 css__stylesheet_style_destroy(variant_style);
296 css__stylesheet_style_destroy(weight_style);
297 css__stylesheet_style_destroy(size_style);
298 css__stylesheet_style_destroy(line_height_style);
299 return error;
300 }
301
302
303 /* Attempt to parse the optional style, variant, and weight */
304 for (svw = 0; svw < 3; svw++) {
305 prev_ctx = *ctx;
306 error = CSS_OK;
307
308 /* Ensure that we're not about to parse another inherit */
309 token = parserutils_vector_peek(vector, *ctx);
310 if ((token != NULL) && is_css_inherit(c, token)) {
311 error = CSS_INVALID;
312 goto css__parse_font_cleanup;
313 }
314
315 if ((style) &&
316 (error = css__parse_font_style(c, vector,
317 ctx, style_style)) == CSS_OK) {
318 style = false;
319 } else if ((variant) &&
320 (error = css__parse_font_variant(c, vector, ctx,
321 variant_style)) == CSS_OK) {
322 variant = false;
323 } else if ((weight) &&
324 (error = css__parse_font_weight(c, vector, ctx,
325 weight_style)) == CSS_OK) {
326 weight = false;
327 }
328
329 if (error == CSS_OK) {
330 consumeWhitespace(vector, ctx);
331 } else {
332 break;
333 }
334
335 if (*ctx == prev_ctx)
336 break;
337 }
338
339 consumeWhitespace(vector, ctx);
340
341 /* Ensure that we're not about to parse another inherit */
342 token = parserutils_vector_peek(vector, *ctx);
343 if ((token != NULL) && is_css_inherit(c, token)) {
344 error = CSS_INVALID;
345 goto css__parse_font_cleanup;
346 }
347
348 /* Now expect a font-size */
349 error = css__parse_font_size(c, vector, ctx, size_style);
350 if (error != CSS_OK)
351 goto css__parse_font_cleanup;
352
353 consumeWhitespace(vector, ctx);
354
355 /* Potential line-height */
356 token = parserutils_vector_peek(vector, *ctx);
357 if ((token != NULL) && tokenIsChar(token, '/')) {
358 parserutils_vector_iterate(vector, ctx);
359
360 consumeWhitespace(vector, ctx);
361
362 /* Ensure that we're not about to parse another inherit */
363 token = parserutils_vector_peek(vector, *ctx);
364 if ((token != NULL) && is_css_inherit(c, token)) {
365 error = CSS_INVALID;
366 goto css__parse_font_cleanup;
367 }
368
369 error = css__parse_line_height(c, vector, ctx, line_height_style);
370 if (error != CSS_OK)
371 goto css__parse_font_cleanup;
372
373 line_height = false;
374 }
375
376 consumeWhitespace(vector, ctx);
377
378 /* Ensure that we're not about to parse another inherit */
379 token = parserutils_vector_peek(vector, *ctx);
380 if ((token != NULL) && is_css_inherit(c, token)) {
381 error = CSS_INVALID;
382 goto css__parse_font_cleanup;
383 }
384
385 /* Now expect a font-family */
386 error = css__parse_font_family(c, vector, ctx, family_style);
387 if (error != CSS_OK)
388 goto css__parse_font_cleanup;
389
390 /* defaults */
391 if (style) {
392 error = css__stylesheet_style_appendOPV(style_style,
393 CSS_PROP_FONT_STYLE, 0,
394 FONT_STYLE_NORMAL);
395 if (error != CSS_OK)
396 goto css__parse_font_cleanup;
397 }
398
399 if (variant) {
400 error = css__stylesheet_style_appendOPV(variant_style,
401 CSS_PROP_FONT_VARIANT, 0,
402 FONT_VARIANT_NORMAL);
403 if (error != CSS_OK)
404 goto css__parse_font_cleanup;
405 }
406
407 if (weight) {
408 error = css__stylesheet_style_appendOPV(weight_style,
409 CSS_PROP_FONT_WEIGHT,
410 0, FONT_WEIGHT_NORMAL);
411 if (error != CSS_OK)
412 goto css__parse_font_cleanup;
413 }
414
415 if (line_height) {
416 error = css__stylesheet_style_appendOPV(line_height_style,
417 CSS_PROP_LINE_HEIGHT,
418 0, LINE_HEIGHT_NORMAL);
419 if (error != CSS_OK)
420 goto css__parse_font_cleanup;
421 }
422
423 /* merge final output */
424 error = css__stylesheet_merge_style(result, style_style);
425 if (error != CSS_OK)
426 goto css__parse_font_cleanup;
427
428 error = css__stylesheet_merge_style(result, variant_style);
429 if (error != CSS_OK)
430 goto css__parse_font_cleanup;
431
432 error = css__stylesheet_merge_style(result, weight_style);
433 if (error != CSS_OK)
434 goto css__parse_font_cleanup;
435
436 error = css__stylesheet_merge_style(result, size_style);
437 if (error != CSS_OK)
438 goto css__parse_font_cleanup;
439
440 error = css__stylesheet_merge_style(result, line_height_style);
441 if (error != CSS_OK)
442 goto css__parse_font_cleanup;
443
444 error = css__stylesheet_merge_style(result, family_style);
445
446
447
448 css__parse_font_cleanup:
449 css__stylesheet_style_destroy(style_style);
450 css__stylesheet_style_destroy(variant_style);
451 css__stylesheet_style_destroy(weight_style);
452 css__stylesheet_style_destroy(size_style);
453 css__stylesheet_style_destroy(line_height_style);
454 css__stylesheet_style_destroy(family_style);
455
456 if (error != CSS_OK)
457 *ctx = orig_ctx;
458
459 return error;
460 }
461
462
463
464
465
466
467