1 /* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
2
3 /* libcroco - Library for parsing and applying CSS
4 * Copyright (C) 2006-2019 Free Software Foundation, Inc.
5 *
6 * This file is not part of the GNU gettext program, but is used with
7 * GNU gettext.
8 *
9 * The original copyright notice is as follows:
10 */
11
12 /*
13 * This file is part of The Croco Library
14 *
15 * Copyright (C) 2003-2004 Dodji Seketeli. All Rights Reserved.
16 *
17 * This program is free software; you can redistribute it and/or
18 * modify it under the terms of version 3 of
19 * the GNU General Public
20 * License as published by the Free Software Foundation.
21 *
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * You should have received a copy of the
28 * GNU General Public License
29 * along with this program; if not, write to the Free Software
30 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
31 * USA
32 *
33 * Author: Dodji Seketeli.
34 */
35
36 #include <config.h>
37 #include <string.h>
38 #include "cr-style.h"
39
40 /**
41 *@file
42 *The definition of the #CRStyle class.
43 */
44
45 /**
46 *A property ID.
47 *Each supported css property has an ID which is
48 *an entry into a property "population" jump table.
49 *each entry of the property population jump table
50 *contains code to tranform the literal form of
51 *a property value into a strongly typed value.
52 */
53 enum CRPropertyID {
54 PROP_ID_NOT_KNOWN = 0,
55 PROP_ID_PADDING_TOP,
56 PROP_ID_PADDING_RIGHT,
57 PROP_ID_PADDING_BOTTOM,
58 PROP_ID_PADDING_LEFT,
59 PROP_ID_PADDING,
60 PROP_ID_BORDER_TOP_WIDTH,
61 PROP_ID_BORDER_RIGHT_WIDTH,
62 PROP_ID_BORDER_BOTTOM_WIDTH,
63 PROP_ID_BORDER_LEFT_WIDTH,
64 PROP_ID_BORDER_WIDTH,
65 PROP_ID_BORDER_TOP_STYLE,
66 PROP_ID_BORDER_RIGHT_STYLE,
67 PROP_ID_BORDER_BOTTOM_STYLE,
68 PROP_ID_BORDER_LEFT_STYLE,
69 PROP_ID_BORDER_STYLE,
70 PROP_ID_BORDER_TOP_COLOR,
71 PROP_ID_BORDER_RIGHT_COLOR,
72 PROP_ID_BORDER_BOTTOM_COLOR,
73 PROP_ID_BORDER_LEFT_COLOR,
74 PROP_ID_BORDER_TOP,
75 PROP_ID_BORDER_RIGHT,
76 PROP_ID_BORDER_BOTTOM,
77 PROP_ID_BORDER_LEFT,
78 PROP_ID_BORDER,
79 PROP_ID_MARGIN_TOP,
80 PROP_ID_MARGIN_RIGHT,
81 PROP_ID_MARGIN_BOTTOM,
82 PROP_ID_MARGIN_LEFT,
83 PROP_ID_MARGIN,
84 PROP_ID_DISPLAY,
85 PROP_ID_POSITION,
86 PROP_ID_TOP,
87 PROP_ID_RIGHT,
88 PROP_ID_BOTTOM,
89 PROP_ID_LEFT,
90 PROP_ID_FLOAT,
91 PROP_ID_WIDTH,
92 PROP_ID_COLOR,
93 PROP_ID_BACKGROUND_COLOR,
94 PROP_ID_FONT_FAMILY,
95 PROP_ID_FONT_SIZE,
96 PROP_ID_FONT_STYLE,
97 PROP_ID_FONT_WEIGHT,
98 PROP_ID_WHITE_SPACE,
99 /*should be the last one. */
100 NB_PROP_IDS
101 };
102
103 typedef struct _CRPropertyDesc CRPropertyDesc;
104
105 struct _CRPropertyDesc {
106 const gchar *name;
107 enum CRPropertyID prop_id;
108 };
109
110 static CRPropertyDesc gv_prop_table[] = {
111 {"padding-top", PROP_ID_PADDING_TOP},
112 {"padding-right", PROP_ID_PADDING_RIGHT},
113 {"padding-bottom", PROP_ID_PADDING_BOTTOM},
114 {"padding-left", PROP_ID_PADDING_LEFT},
115 {"padding", PROP_ID_PADDING},
116 {"border-top-width", PROP_ID_BORDER_TOP_WIDTH},
117 {"border-right-width", PROP_ID_BORDER_RIGHT_WIDTH},
118 {"border-bottom-width", PROP_ID_BORDER_BOTTOM_WIDTH},
119 {"border-left-width", PROP_ID_BORDER_LEFT_WIDTH},
120 {"border-width", PROP_ID_BORDER_WIDTH},
121 {"border-top-style", PROP_ID_BORDER_TOP_STYLE},
122 {"border-right-style", PROP_ID_BORDER_RIGHT_STYLE},
123 {"border-bottom-style", PROP_ID_BORDER_BOTTOM_STYLE},
124 {"border-left-style", PROP_ID_BORDER_LEFT_STYLE},
125 {"border-style", PROP_ID_BORDER_STYLE},
126 {"border-top", PROP_ID_BORDER_TOP},
127 {"border-right", PROP_ID_BORDER_RIGHT},
128 {"border-bottom", PROP_ID_BORDER_BOTTOM},
129 {"border-left", PROP_ID_BORDER_LEFT},
130 {"border", PROP_ID_BORDER},
131 {"margin-top", PROP_ID_MARGIN_TOP},
132 {"margin-right", PROP_ID_MARGIN_RIGHT},
133 {"margin-bottom", PROP_ID_MARGIN_BOTTOM},
134 {"margin-left", PROP_ID_MARGIN_LEFT},
135 {"margin", PROP_ID_MARGIN},
136 {"display", PROP_ID_DISPLAY},
137 {"position", PROP_ID_POSITION},
138 {"top", PROP_ID_TOP},
139 {"right", PROP_ID_RIGHT},
140 {"bottom", PROP_ID_BOTTOM},
141 {"left", PROP_ID_LEFT},
142 {"float", PROP_ID_FLOAT},
143 {"width", PROP_ID_WIDTH},
144 {"color", PROP_ID_COLOR},
145 {"border-top-color", PROP_ID_BORDER_TOP_COLOR},
146 {"border-right-color", PROP_ID_BORDER_RIGHT_COLOR},
147 {"border-bottom-color", PROP_ID_BORDER_BOTTOM_COLOR},
148 {"border-left-color", PROP_ID_BORDER_LEFT_COLOR},
149 {"background-color", PROP_ID_BACKGROUND_COLOR},
150 {"font-family", PROP_ID_FONT_FAMILY},
151 {"font-size", PROP_ID_FONT_SIZE},
152 {"font-style", PROP_ID_FONT_STYLE},
153 {"font-weight", PROP_ID_FONT_WEIGHT},
154 {"white-space", PROP_ID_WHITE_SPACE},
155 /*must be the last one */
156 {NULL, 0}
157 };
158
159 /**
160 *A the key/value pair of this hash table
161 *are:
162 *key => name of the the css propertie found in gv_prop_table
163 *value => matching property id found in gv_prop_table.
164 *So this hash table is here just to retrieval of a property id
165 *from a property name.
166 */
167 static GHashTable *gv_prop_hash = NULL;
168
169 /**
170 *incremented by each new instance of #CRStyle
171 *and decremented at the it destroy time.
172 *When this reaches zero, gv_prop_hash is destroyed.
173 */
174 static gulong gv_prop_hash_ref_count = 0;
175
176 struct CRNumPropEnumDumpInfo {
177 enum CRNumProp code;
178 const gchar *str;
179 };
180
181 static struct CRNumPropEnumDumpInfo gv_num_props_dump_infos[] = {
182 {NUM_PROP_TOP, "top"},
183 {NUM_PROP_RIGHT, "right"},
184 {NUM_PROP_BOTTOM, "bottom"},
185 {NUM_PROP_LEFT, "left"},
186 {NUM_PROP_PADDING_TOP, "padding-top"},
187 {NUM_PROP_PADDING_RIGHT, "padding-right"},
188 {NUM_PROP_PADDING_BOTTOM, "padding-bottom"},
189 {NUM_PROP_PADDING_LEFT, "padding-left"},
190 {NUM_PROP_BORDER_TOP, "border-top"},
191 {NUM_PROP_BORDER_RIGHT, "border-right"},
192 {NUM_PROP_BORDER_BOTTOM, "border-bottom"},
193 {NUM_PROP_BORDER_LEFT, "border-left"},
194 {NUM_PROP_MARGIN_TOP, "margin-top"},
195 {NUM_PROP_MARGIN_RIGHT, "margin-right"},
196 {NUM_PROP_MARGIN_BOTTOM, "margin-bottom"},
197 {NUM_PROP_MARGIN_LEFT, "margin-left"},
198 {NUM_PROP_WIDTH, "width"},
199 {0, NULL}
200 };
201
202 struct CRRgbPropEnumDumpInfo {
203 enum CRRgbProp code;
204 const gchar *str;
205 };
206
207 static struct CRRgbPropEnumDumpInfo gv_rgb_props_dump_infos[] = {
208 {RGB_PROP_BORDER_TOP_COLOR, "border-top-color"},
209 {RGB_PROP_BORDER_RIGHT_COLOR, "border-right-color"},
210 {RGB_PROP_BORDER_BOTTOM_COLOR, "bottom-color"},
211 {RGB_PROP_BORDER_LEFT_COLOR, "left-color"},
212 {RGB_PROP_COLOR, "color"},
213 {RGB_PROP_BACKGROUND_COLOR, "background-color"},
214 {0, NULL}
215 };
216
217 struct CRBorderStylePropEnumDumpInfo {
218 enum CRBorderStyleProp code;
219 const gchar *str;
220
221 };
222
223 static struct CRBorderStylePropEnumDumpInfo gv_border_style_props_dump_infos[]
224 = {
225 {BORDER_STYLE_PROP_TOP, "border-style-top"},
226 {BORDER_STYLE_PROP_RIGHT, "border-style-right"},
227 {BORDER_STYLE_PROP_BOTTOM, "boder-style-bottom"},
228 {BORDER_STYLE_PROP_LEFT, "border-style-left"},
229 {0, NULL}
230 };
231
232 static enum CRStatus
233 cr_style_init_properties (void);
234
235 enum CRDirection {
236 DIR_TOP = 0,
237 DIR_RIGHT,
238 DIR_BOTTOM,
239 DIR_LEFT,
240
241 /*must be the last one */
242 NB_DIRS
243 };
244
245 static const gchar *num_prop_code_to_string (enum CRNumProp a_code);
246
247 static const gchar *rgb_prop_code_to_string (enum CRRgbProp a_code);
248
249 static const gchar *border_style_prop_code_to_string (enum CRBorderStyleProp
250 a_code);
251
252 static enum CRStatus
253 set_prop_padding_x_from_value (CRStyle * a_style,
254 CRTerm * a_value, enum CRDirection a_dir);
255
256 static enum CRStatus
257 set_prop_border_x_width_from_value (CRStyle * a_style,
258 CRTerm * a_value,
259 enum CRDirection a_dir);
260 static enum CRStatus
261 set_prop_border_width_from_value (CRStyle *a_style,
262 CRTerm *a_value) ;
263
264 static enum CRStatus
265 set_prop_border_x_style_from_value (CRStyle * a_style,
266 CRTerm * a_value,
267 enum CRDirection a_dir);
268 static enum CRStatus
269 set_prop_border_style_from_value (CRStyle *a_style,
270 CRTerm *a_value) ;
271
272 static enum CRStatus
273 set_prop_margin_x_from_value (CRStyle * a_style, CRTerm * a_value,
274 enum CRDirection a_dir);
275
276 static enum CRStatus
277 set_prop_display_from_value (CRStyle * a_style, CRTerm * a_value);
278
279 static enum CRStatus
280 set_prop_position_from_value (CRStyle * a_style, CRTerm * a_value);
281
282 static enum CRStatus
283 set_prop_x_from_value (CRStyle * a_style, CRTerm * a_value,
284 enum CRDirection a_dir);
285
286 static enum CRStatus
287 set_prop_float (CRStyle * a_style, CRTerm * a_value);
288
289 static enum CRStatus
290 set_prop_width (CRStyle * a_style, CRTerm * a_value);
291
292 static enum CRStatus
293 set_prop_color (CRStyle * a_style, CRTerm * a_value);
294
295 static enum CRStatus
296 set_prop_background_color (CRStyle * a_style, CRTerm * a_value);
297
298 static enum CRStatus
299 set_prop_border_x_color_from_value (CRStyle * a_style, CRTerm * a_value,
300 enum CRDirection a_dir);
301
302 static enum CRStatus
303 set_prop_border_x_from_value (CRStyle * a_style, CRTerm * a_value,
304 enum CRDirection a_dir);
305
306 static enum CRStatus
307 set_prop_border_from_value (CRStyle * a_style, CRTerm * a_value);
308
309 static enum CRStatus
310 set_prop_padding_from_value (CRStyle * a_style, CRTerm * a_value);
311
312 static enum CRStatus
313 set_prop_margin_from_value (CRStyle * a_style, CRTerm * a_value);
314
315 static enum CRStatus
316 set_prop_font_family_from_value (CRStyle * a_style, CRTerm * a_value);
317
318 static enum CRStatus
319 init_style_font_size_field (CRStyle * a_style);
320
321 static enum CRStatus
322 set_prop_font_size_from_value (CRStyle * a_style, CRTerm * a_value);
323
324 static enum CRStatus
325 set_prop_font_style_from_value (CRStyle * a_style, CRTerm * a_value);
326
327 static enum CRStatus
328 set_prop_font_weight_from_value (CRStyle * a_style, CRTerm * a_value);
329
330 static const gchar *
num_prop_code_to_string(enum CRNumProp a_code)331 num_prop_code_to_string (enum CRNumProp a_code)
332 {
333 guint len = sizeof (gv_num_props_dump_infos) /
334 sizeof (struct CRNumPropEnumDumpInfo);
335 if (a_code >= len) {
336 cr_utils_trace_info ("A field has been added "
337 "to 'enum CRNumProp' and no matching"
338 " entry has been "
339 "added to gv_num_prop_dump_infos table.\n"
340 "Please add the missing matching entry");
341 return NULL;
342 }
343 if (gv_num_props_dump_infos[a_code].code != a_code) {
344 cr_utils_trace_info ("mismatch between the order of fields in"
345 " 'enum CRNumProp' and "
346 "the order of entries in "
347 "the gv_num_prop_dump_infos table");
348 return NULL;
349 }
350 return gv_num_props_dump_infos[a_code].str;
351 }
352
353 static const gchar *
rgb_prop_code_to_string(enum CRRgbProp a_code)354 rgb_prop_code_to_string (enum CRRgbProp a_code)
355 {
356 guint len = sizeof (gv_rgb_props_dump_infos) /
357 sizeof (struct CRRgbPropEnumDumpInfo);
358
359 if (a_code >= len) {
360 cr_utils_trace_info ("A field has been added "
361 "to 'enum CRRgbProp' and no matching"
362 " entry has been "
363 "added to gv_rgb_prop_dump_infos table.\n"
364 "Please add the missing matching entry");
365 return NULL;
366 }
367 if (gv_rgb_props_dump_infos[a_code].code != a_code) {
368 cr_utils_trace_info ("mismatch between the order of fields in"
369 " 'enum CRRgbProp' and "
370 "the order of entries in "
371 "the gv_rgb_props_dump_infos table");
372 return NULL;
373 }
374 return gv_rgb_props_dump_infos[a_code].str;
375 }
376
377 static const gchar *
border_style_prop_code_to_string(enum CRBorderStyleProp a_code)378 border_style_prop_code_to_string (enum CRBorderStyleProp a_code)
379 {
380 guint len = sizeof (gv_border_style_props_dump_infos) /
381 sizeof (struct CRBorderStylePropEnumDumpInfo);
382
383 if (a_code >= len) {
384 cr_utils_trace_info ("A field has been added "
385 "to 'enum CRBorderStyleProp' and no matching"
386 " entry has been "
387 "added to gv_border_style_prop_dump_infos table.\n"
388 "Please add the missing matching entry");
389 return NULL;
390 }
391 if (gv_border_style_props_dump_infos[a_code].code != a_code) {
392 cr_utils_trace_info ("mismatch between the order of fields in"
393 " 'enum CRBorderStyleProp' and "
394 "the order of entries in "
395 "the gv_border_style_props_dump_infos table");
396 return NULL;
397 }
398 return gv_border_style_props_dump_infos[a_code].str;
399 }
400
401 static enum CRStatus
cr_style_init_properties(void)402 cr_style_init_properties (void)
403 {
404
405 if (!gv_prop_hash) {
406 gulong i = 0;
407
408 gv_prop_hash = g_hash_table_new (g_str_hash, g_str_equal);
409 if (!gv_prop_hash) {
410 cr_utils_trace_info ("Out of memory");
411 return CR_ERROR;
412 }
413
414 /*load gv_prop_hash from gv_prop_table */
415 for (i = 0; gv_prop_table[i].name; i++) {
416 g_hash_table_insert
417 (gv_prop_hash,
418 (gpointer) gv_prop_table[i].name,
419 GINT_TO_POINTER (gv_prop_table[i].prop_id));
420 }
421 }
422
423 return CR_OK;
424 }
425
426 static enum CRPropertyID
cr_style_get_prop_id(const guchar * a_prop)427 cr_style_get_prop_id (const guchar * a_prop)
428 {
429 gpointer *raw_id = NULL;
430
431 if (!gv_prop_hash) {
432 cr_style_init_properties ();
433 }
434
435 raw_id = g_hash_table_lookup (gv_prop_hash, a_prop);
436 if (!raw_id) {
437 return PROP_ID_NOT_KNOWN;
438 }
439 return GPOINTER_TO_INT (raw_id);
440 }
441
442 static enum CRStatus
set_prop_padding_x_from_value(CRStyle * a_style,CRTerm * a_value,enum CRDirection a_dir)443 set_prop_padding_x_from_value (CRStyle * a_style,
444 CRTerm * a_value, enum CRDirection a_dir)
445 {
446 enum CRStatus status = CR_OK;
447 CRNum *num_val = NULL;
448
449 g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
450
451 if (a_value->type != TERM_NUMBER && a_value->type != TERM_IDENT)
452 return CR_BAD_PARAM_ERROR;
453
454 switch (a_dir) {
455 case DIR_TOP:
456 num_val = &a_style->num_props[NUM_PROP_PADDING_TOP].sv;
457 break;
458
459 case DIR_RIGHT:
460 num_val = &a_style->num_props[NUM_PROP_PADDING_RIGHT].sv;
461 break;
462
463 case DIR_BOTTOM:
464 num_val = &a_style->num_props[NUM_PROP_PADDING_BOTTOM].sv;
465 break;
466
467 case DIR_LEFT:
468 num_val = &a_style->num_props[NUM_PROP_PADDING_LEFT].sv;
469 break;
470
471 default:
472 return CR_BAD_PARAM_ERROR;
473 }
474
475 if (a_value->type == TERM_IDENT) {
476 if (a_value->content.str
477 && a_value->content.str->stryng
478 && a_value->content.str->stryng->str
479 && !strncmp ((const char *) "inherit",
480 a_value->content.str->stryng->str,
481 sizeof ("inherit")-1)) {
482 status = cr_num_set (num_val, 0.0, NUM_INHERIT);
483 return CR_OK;
484 } else
485 return CR_UNKNOWN_TYPE_ERROR;
486 }
487
488 g_return_val_if_fail (a_value->type == TERM_NUMBER
489 && a_value->content.num, CR_UNKNOWN_TYPE_ERROR);
490
491 switch (a_value->content.num->type) {
492 case NUM_LENGTH_EM:
493 case NUM_LENGTH_EX:
494 case NUM_LENGTH_PX:
495 case NUM_LENGTH_IN:
496 case NUM_LENGTH_CM:
497 case NUM_LENGTH_MM:
498 case NUM_LENGTH_PT:
499 case NUM_LENGTH_PC:
500 case NUM_PERCENTAGE:
501 status = cr_num_copy (num_val, a_value->content.num);
502 break;
503 default:
504 status = CR_UNKNOWN_TYPE_ERROR;
505 break;
506 }
507
508 return status;
509 }
510
511 static enum CRStatus
set_prop_border_x_width_from_value(CRStyle * a_style,CRTerm * a_value,enum CRDirection a_dir)512 set_prop_border_x_width_from_value (CRStyle * a_style,
513 CRTerm * a_value,
514 enum CRDirection a_dir)
515 {
516 enum CRStatus status = CR_OK;
517 CRNum *num_val = NULL;
518
519 g_return_val_if_fail (a_value && a_style, CR_BAD_PARAM_ERROR);
520
521 switch (a_dir) {
522 case DIR_TOP:
523 num_val = &a_style->num_props[NUM_PROP_BORDER_TOP].sv;
524 break;
525
526 case DIR_RIGHT:
527 num_val = &a_style->num_props[NUM_PROP_BORDER_RIGHT].sv;
528 break;
529
530 case DIR_BOTTOM:
531 num_val = &a_style->num_props[NUM_PROP_BORDER_BOTTOM].sv;
532 break;
533
534 case DIR_LEFT:
535 num_val = &a_style->num_props[NUM_PROP_BORDER_LEFT].sv;
536 break;
537
538 default:
539 return CR_BAD_PARAM_ERROR;
540 break;
541 }
542
543 if (a_value->type == TERM_IDENT) {
544 if (a_value->content.str
545 && a_value->content.str->stryng
546 && a_value->content.str->stryng->str) {
547 if (!strncmp ("thin",
548 a_value->content.str->stryng->str,
549 sizeof ("thin")-1)) {
550 cr_num_set (num_val, BORDER_THIN,
551 NUM_LENGTH_PX);
552 } else if (!strncmp
553 ("medium",
554 a_value->content.str->stryng->str,
555 sizeof ("medium")-1)) {
556 cr_num_set (num_val, BORDER_MEDIUM,
557 NUM_LENGTH_PX);
558 } else if (!strncmp ("thick",
559 a_value->content.str->stryng->str,
560 sizeof ("thick")-1)) {
561 cr_num_set (num_val, BORDER_THICK,
562 NUM_LENGTH_PX);
563 } else {
564 return CR_UNKNOWN_TYPE_ERROR;
565 }
566 }
567 } else if (a_value->type == TERM_NUMBER) {
568 if (a_value->content.num) {
569 cr_num_copy (num_val, a_value->content.num);
570 }
571 } else if (a_value->type != TERM_NUMBER
572 || a_value->content.num == NULL) {
573 return CR_UNKNOWN_TYPE_ERROR;
574 }
575
576 return status;
577 }
578
579 static enum CRStatus
set_prop_border_width_from_value(CRStyle * a_style,CRTerm * a_value)580 set_prop_border_width_from_value (CRStyle *a_style,
581 CRTerm *a_value)
582 {
583 CRTerm *cur_term = NULL ;
584 enum CRDirection direction = DIR_TOP ;
585
586 g_return_val_if_fail (a_style && a_value,
587 CR_BAD_PARAM_ERROR) ;
588 cur_term = a_value ;
589
590 if (!cur_term)
591 return CR_ERROR ;
592
593 for (direction = DIR_TOP ;
594 direction < NB_DIRS ; direction ++) {
595 set_prop_border_x_width_from_value (a_style,
596 cur_term,
597 direction) ;
598 }
599
600 cur_term = cur_term->next ;
601 if (!cur_term)
602 return CR_OK ;
603 set_prop_border_x_width_from_value (a_style, cur_term,
604 DIR_RIGHT) ;
605 set_prop_border_x_width_from_value (a_style, cur_term,
606 DIR_LEFT) ;
607
608 cur_term = cur_term->next ;
609 if (!cur_term)
610 return CR_OK ;
611 set_prop_border_x_width_from_value (a_style, cur_term,
612 DIR_BOTTOM) ;
613
614 cur_term = cur_term->next ;
615 if (!cur_term)
616 return CR_OK ;
617 set_prop_border_x_width_from_value (a_style, cur_term,
618 DIR_LEFT) ;
619
620 return CR_OK ;
621 }
622
623 static enum CRStatus
set_prop_border_x_style_from_value(CRStyle * a_style,CRTerm * a_value,enum CRDirection a_dir)624 set_prop_border_x_style_from_value (CRStyle * a_style,
625 CRTerm * a_value, enum CRDirection a_dir)
626 {
627 enum CRStatus status = CR_OK;
628 enum CRBorderStyle *border_style_ptr = NULL;
629
630 g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
631
632 switch (a_dir) {
633 case DIR_TOP:
634 border_style_ptr = &a_style->
635 border_style_props[BORDER_STYLE_PROP_TOP];
636 break;
637
638 case DIR_RIGHT:
639 border_style_ptr =
640 &a_style->border_style_props[BORDER_STYLE_PROP_RIGHT];
641 break;
642
643 case DIR_BOTTOM:
644 border_style_ptr = &a_style->
645 border_style_props[BORDER_STYLE_PROP_BOTTOM];
646 break;
647
648 case DIR_LEFT:
649 border_style_ptr = &a_style->
650 border_style_props[BORDER_STYLE_PROP_LEFT];
651 break;
652
653 default:
654 break;
655 }
656
657 if (a_value->type != TERM_IDENT || !a_value->content.str) {
658 return CR_UNKNOWN_TYPE_ERROR;
659 }
660
661 if (!strncmp ("none",
662 a_value->content.str->stryng->str,
663 sizeof ("none")-1)) {
664 *border_style_ptr = BORDER_STYLE_NONE;
665 } else if (!strncmp ("hidden",
666 a_value->content.str->stryng->str,
667 sizeof ("hidden")-1)) {
668 *border_style_ptr = BORDER_STYLE_HIDDEN;
669 } else if (!strncmp ("dotted",
670 a_value->content.str->stryng->str,
671 sizeof ("dotted")-1)) {
672 *border_style_ptr = BORDER_STYLE_DOTTED;
673 } else if (!strncmp ("dashed",
674 a_value->content.str->stryng->str, sizeof ("dashed")-1)) {
675 *border_style_ptr = BORDER_STYLE_DASHED;
676 } else if (!strncmp ("solid",
677 a_value->content.str->stryng->str, sizeof ("solid")-1)) {
678 *border_style_ptr = BORDER_STYLE_SOLID;
679 } else if (!strncmp ("double",
680 a_value->content.str->stryng->str, sizeof ("double")-1)) {
681 *border_style_ptr = BORDER_STYLE_DOUBLE;
682 } else if (!strncmp ("groove",
683 a_value->content.str->stryng->str, sizeof ("groove")-1)) {
684 *border_style_ptr = BORDER_STYLE_GROOVE;
685 } else if (!strncmp ("ridge",
686 a_value->content.str->stryng->str,
687 sizeof ("ridge")-1)) {
688 *border_style_ptr = BORDER_STYLE_RIDGE;
689 } else if (!strncmp ("inset",
690 a_value->content.str->stryng->str,
691 sizeof ("inset")-1)) {
692 *border_style_ptr = BORDER_STYLE_INSET;
693 } else if (!strncmp ("outset",
694 a_value->content.str->stryng->str,
695 sizeof ("outset")-1)) {
696 *border_style_ptr = BORDER_STYLE_OUTSET;
697 } else if (!strncmp ("inherit",
698 a_value->content.str->stryng->str,
699 sizeof ("inherit")-1)) {
700 *border_style_ptr = BORDER_STYLE_INHERIT;
701 } else {
702 status = CR_UNKNOWN_TYPE_ERROR;
703 }
704
705 return status;
706 }
707
708 static enum CRStatus
set_prop_border_style_from_value(CRStyle * a_style,CRTerm * a_value)709 set_prop_border_style_from_value (CRStyle *a_style,
710 CRTerm *a_value)
711 {
712 CRTerm *cur_term = NULL ;
713 enum CRDirection direction = DIR_TOP ;
714
715 g_return_val_if_fail (a_style && a_value,
716 CR_BAD_PARAM_ERROR) ;
717
718 cur_term = a_value ;
719 if (!cur_term || cur_term->type != TERM_IDENT) {
720 return CR_ERROR ;
721 }
722
723 for (direction = DIR_TOP ;
724 direction < NB_DIRS ;
725 direction ++) {
726 set_prop_border_x_style_from_value (a_style,
727 cur_term,
728 direction) ;
729 }
730
731 cur_term = cur_term->next ;
732 if (!cur_term || cur_term->type != TERM_IDENT) {
733 return CR_OK ;
734 }
735
736 set_prop_border_x_style_from_value (a_style, cur_term,
737 DIR_RIGHT) ;
738 set_prop_border_x_style_from_value (a_style, cur_term,
739 DIR_LEFT) ;
740
741 cur_term = cur_term->next ;
742 if (!cur_term || cur_term->type != TERM_IDENT) {
743 return CR_OK ;
744 }
745 set_prop_border_x_style_from_value (a_style, cur_term,
746 DIR_BOTTOM) ;
747
748 cur_term = cur_term->next ;
749 if (!cur_term || cur_term->type != TERM_IDENT) {
750 return CR_OK ;
751 }
752 set_prop_border_x_style_from_value (a_style, cur_term,
753 DIR_LEFT) ;
754 return CR_OK ;
755 }
756
757 static enum CRStatus
set_prop_margin_x_from_value(CRStyle * a_style,CRTerm * a_value,enum CRDirection a_dir)758 set_prop_margin_x_from_value (CRStyle * a_style, CRTerm * a_value,
759 enum CRDirection a_dir)
760 {
761 enum CRStatus status = CR_OK;
762 CRNum *num_val = NULL;
763
764 g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
765
766 switch (a_dir) {
767 case DIR_TOP:
768 num_val = &a_style->num_props[NUM_PROP_MARGIN_TOP].sv;
769 break;
770
771 case DIR_RIGHT:
772 num_val = &a_style->num_props[NUM_PROP_MARGIN_RIGHT].sv;
773 break;
774
775 case DIR_BOTTOM:
776 num_val = &a_style->num_props[NUM_PROP_MARGIN_BOTTOM].sv;
777 break;
778
779 case DIR_LEFT:
780 num_val = &a_style->num_props[NUM_PROP_MARGIN_LEFT].sv;
781 break;
782
783 default:
784 break;
785 }
786
787 switch (a_value->type) {
788 case TERM_IDENT:
789 if (a_value->content.str
790 && a_value->content.str->stryng
791 && a_value->content.str->stryng->str
792 && !strcmp (a_value->content.str->stryng->str,
793 "inherit")) {
794 status = cr_num_set (num_val, 0.0, NUM_INHERIT);
795 } else if (a_value->content.str
796 && a_value->content.str->stryng
797 && !strcmp (a_value->content.str->stryng->str,
798 "auto")) {
799 status = cr_num_set (num_val, 0.0, NUM_AUTO);
800 } else {
801 status = CR_UNKNOWN_TYPE_ERROR;
802 }
803 break ;
804
805 case TERM_NUMBER:
806 status = cr_num_copy (num_val, a_value->content.num);
807 break;
808
809 default:
810 status = CR_UNKNOWN_TYPE_ERROR;
811 break;
812 }
813
814 return status;
815 }
816
817 struct CRPropDisplayValPair {
818 const gchar *prop_name;
819 enum CRDisplayType type;
820 };
821
822 static enum CRStatus
set_prop_display_from_value(CRStyle * a_style,CRTerm * a_value)823 set_prop_display_from_value (CRStyle * a_style, CRTerm * a_value)
824 {
825 static const struct CRPropDisplayValPair disp_vals_map[] = {
826 {"none", DISPLAY_NONE},
827 {"inline", DISPLAY_INLINE},
828 {"block", DISPLAY_BLOCK},
829 {"run-in", DISPLAY_RUN_IN},
830 {"compact", DISPLAY_COMPACT},
831 {"marker", DISPLAY_MARKER},
832 {"table", DISPLAY_TABLE},
833 {"inline-table", DISPLAY_INLINE_TABLE},
834 {"table-row-group", DISPLAY_TABLE_ROW_GROUP},
835 {"table-header-group", DISPLAY_TABLE_HEADER_GROUP},
836 {"table-footer-group", DISPLAY_TABLE_FOOTER_GROUP},
837 {"table-row", DISPLAY_TABLE_ROW},
838 {"table-column-group", DISPLAY_TABLE_COLUMN_GROUP},
839 {"table-column", DISPLAY_TABLE_COLUMN},
840 {"table-cell", DISPLAY_TABLE_CELL},
841 {"table-caption", DISPLAY_TABLE_CAPTION},
842 {"inherit", DISPLAY_INHERIT},
843 {NULL, DISPLAY_NONE}
844 };
845
846 g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
847
848 switch (a_value->type) {
849 case TERM_IDENT:
850 {
851 int i = 0;
852
853 if (!a_value->content.str
854 || !a_value->content.str->stryng
855 || !a_value->content.str->stryng->str)
856 break;
857
858 for (i = 0; disp_vals_map[i].prop_name; i++) {
859 if (!strncmp
860 (disp_vals_map[i].prop_name,
861 a_value->content.str->stryng->str,
862 strlen (disp_vals_map[i].prop_name))) {
863 a_style->display =
864 disp_vals_map[i].type;
865 break;
866 }
867 }
868 }
869 break;
870
871 default:
872 break;
873 }
874
875 return CR_OK;
876 }
877
878 struct CRPropPositionValPair {
879 const gchar *name;
880 enum CRPositionType type;
881 };
882
883 static enum CRStatus
set_prop_position_from_value(CRStyle * a_style,CRTerm * a_value)884 set_prop_position_from_value (CRStyle * a_style, CRTerm * a_value)
885 {
886 enum CRStatus status = CR_UNKNOWN_PROP_VAL_ERROR;
887 static const struct CRPropPositionValPair position_vals_map[] = {
888 {"static", POSITION_STATIC},
889 {"relative", POSITION_RELATIVE},
890 {"absolute", POSITION_ABSOLUTE},
891 {"fixed", POSITION_FIXED},
892 {"inherit", POSITION_INHERIT},
893 {NULL, POSITION_STATIC}
894 /*must alwas be the last one */
895 };
896
897 g_return_val_if_fail (a_value, CR_BAD_PARAM_ERROR);
898
899 switch (a_value->type) {
900 case TERM_IDENT:
901 {
902 int i = 0;
903
904 if (!a_value->content.str
905 || !a_value->content.str->stryng
906 || !a_value->content.str->stryng->str)
907 break;
908
909 for (i = 0; position_vals_map[i].name; i++) {
910 if (!strncmp (position_vals_map[i].name,
911 a_value->content.str->stryng->str,
912 strlen (position_vals_map[i].
913 name))) {
914 a_style->position =
915 position_vals_map[i].type;
916 status = CR_OK;
917 break;
918 }
919 }
920 }
921 break;
922
923 default:
924 break;
925 }
926
927 return status;
928 }
929
930 static enum CRStatus
set_prop_x_from_value(CRStyle * a_style,CRTerm * a_value,enum CRDirection a_dir)931 set_prop_x_from_value (CRStyle * a_style, CRTerm * a_value,
932 enum CRDirection a_dir)
933 {
934 CRNum *box_offset = NULL;
935
936 g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
937
938 if (!(a_value->type == TERM_NUMBER)
939 && !(a_value->type == TERM_IDENT)) {
940 return CR_UNKNOWN_PROP_VAL_ERROR;
941 }
942
943 switch (a_dir) {
944 case DIR_TOP:
945 box_offset = &a_style->num_props[NUM_PROP_TOP].sv;
946 break;
947
948 case DIR_RIGHT:
949 box_offset = &a_style->num_props[NUM_PROP_RIGHT].sv;
950 break;
951
952 case DIR_BOTTOM:
953 box_offset = &a_style->num_props[NUM_PROP_BOTTOM].sv;
954 break;
955 case DIR_LEFT:
956 box_offset = &a_style->num_props[NUM_PROP_LEFT].sv;
957 break;
958
959 default:
960 break;
961 }
962
963 box_offset->type = NUM_AUTO;
964
965 if (a_value->type == TERM_NUMBER && a_value->content.num) {
966 cr_num_copy (box_offset, a_value->content.num);
967 } else if (a_value->type == TERM_IDENT
968 && a_value->content.str
969 && a_value->content.str->stryng
970 && a_value->content.str->stryng->str) {
971 if (!strncmp ("inherit",
972 a_value->content.str->stryng->str,
973 sizeof ("inherit")-1)) {
974 cr_num_set (box_offset, 0.0, NUM_INHERIT);
975 } else if (!strncmp ("auto",
976 a_value->content.str->stryng->str,
977 sizeof ("auto")-1)) {
978 box_offset->type = NUM_AUTO;
979 }
980 }
981
982 return CR_OK;
983 }
984
985 static enum CRStatus
set_prop_float(CRStyle * a_style,CRTerm * a_value)986 set_prop_float (CRStyle * a_style, CRTerm * a_value)
987 {
988 g_return_val_if_fail (a_style && a_value,
989 CR_BAD_PARAM_ERROR);
990
991 /*the default float type as specified by the css2 spec */
992 a_style->float_type = FLOAT_NONE;
993
994 if (a_value->type != TERM_IDENT
995 || !a_value->content.str
996 || !a_value->content.str->stryng
997 || !a_value->content.str->stryng->str) {
998 /*unknown type, the float type is set to it's default value */
999 return CR_OK;
1000 }
1001
1002 if (!strncmp ("none",
1003 a_value->content.str->stryng->str,
1004 sizeof ("none")-1)) {
1005 a_style->float_type = FLOAT_NONE;
1006 } else if (!strncmp ("left",
1007 a_value->content.str->stryng->str,
1008 sizeof ("left")-1)) {
1009 a_style->float_type = FLOAT_LEFT;
1010 } else if (!strncmp ("right",
1011 a_value->content.str->stryng->str,
1012 sizeof ("right")-1)) {
1013 a_style->float_type = FLOAT_RIGHT;
1014 } else if (!strncmp ("inherit",
1015 a_value->content.str->stryng->str,
1016 sizeof ("inherit")-1)) {
1017 a_style->float_type = FLOAT_INHERIT;
1018 }
1019 return CR_OK;
1020 }
1021
1022 static enum CRStatus
set_prop_width(CRStyle * a_style,CRTerm * a_value)1023 set_prop_width (CRStyle * a_style, CRTerm * a_value)
1024 {
1025 CRNum *width = NULL;
1026 g_return_val_if_fail (a_style
1027 && a_value,
1028 CR_BAD_PARAM_ERROR);
1029
1030 width = &a_style->num_props[NUM_PROP_WIDTH].sv;
1031 cr_num_set (width, 0.0, NUM_AUTO);
1032
1033 if (a_value->type == TERM_IDENT) {
1034 if (a_value->content.str
1035 && a_value->content.str->stryng
1036 && a_value->content.str->stryng->str) {
1037 if (!strncmp ("auto",
1038 a_value->content.str->stryng->str,
1039 sizeof ("auto")-1)) {
1040 cr_num_set (width, 0.0, NUM_AUTO);
1041 } else if (!strncmp ("inherit",
1042 a_value->content.str->stryng->str,
1043 sizeof ("inherit")-1)) {
1044 cr_num_set (width, 0.0, NUM_INHERIT);
1045 }
1046 }
1047 } else if (a_value->type == TERM_NUMBER) {
1048 if (a_value->content.num) {
1049 cr_num_copy (&a_style->num_props[NUM_PROP_WIDTH].sv,
1050 a_value->content.num);
1051 }
1052 }
1053 return CR_OK;
1054 }
1055
1056 static enum CRStatus
set_prop_color(CRStyle * a_style,CRTerm * a_value)1057 set_prop_color (CRStyle * a_style, CRTerm * a_value)
1058 {
1059 enum CRStatus status = CR_OK;
1060 CRRgb *a_rgb = &a_style->rgb_props[RGB_PROP_COLOR].sv;
1061
1062 g_return_val_if_fail (a_style
1063 && a_value, CR_BAD_PARAM_ERROR);
1064
1065 status = cr_rgb_set_from_term (a_rgb, a_value);
1066
1067 return status;
1068 }
1069
1070 static enum CRStatus
set_prop_background_color(CRStyle * a_style,CRTerm * a_value)1071 set_prop_background_color (CRStyle * a_style, CRTerm * a_value)
1072 {
1073 enum CRStatus status = CR_OK;
1074 CRRgb *rgb = &a_style->rgb_props[RGB_PROP_BACKGROUND_COLOR].sv;
1075
1076 g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
1077
1078 status = cr_rgb_set_from_term (rgb, a_value);
1079 return status;
1080 }
1081
1082 /**
1083 *Sets border-top-color, border-right-color,
1084 *border-bottom-color or border-left-color properties
1085 *in the style structure. The value is taken from a
1086 *css2 term of type IDENT or RGB.
1087 *@param a_style the style structure to set.
1088 *@param a_value the css2 term to take the color information from.
1089 *@param a_dir the direction (TOP, LEFT, RIGHT, or BOTTOM).
1090 *@return CR_OK upon successfull completion, an error code otherwise.
1091 */
1092 static enum CRStatus
set_prop_border_x_color_from_value(CRStyle * a_style,CRTerm * a_value,enum CRDirection a_dir)1093 set_prop_border_x_color_from_value (CRStyle * a_style, CRTerm * a_value,
1094 enum CRDirection a_dir)
1095 {
1096 CRRgb *rgb_color = NULL;
1097 enum CRStatus status = CR_OK;
1098
1099 g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
1100
1101 switch (a_dir) {
1102 case DIR_TOP:
1103 rgb_color = &a_style->rgb_props[RGB_PROP_BORDER_TOP_COLOR].sv;
1104 break;
1105
1106 case DIR_RIGHT:
1107 rgb_color =
1108 &a_style->rgb_props[RGB_PROP_BORDER_RIGHT_COLOR].sv;
1109 break;
1110
1111 case DIR_BOTTOM:
1112 rgb_color =
1113 &a_style->rgb_props[RGB_PROP_BORDER_BOTTOM_COLOR].sv;
1114 break;
1115
1116 case DIR_LEFT:
1117 rgb_color =
1118 &a_style->rgb_props[RGB_PROP_BORDER_LEFT_COLOR].sv;
1119 break;
1120
1121 default:
1122 cr_utils_trace_info ("unknown DIR type");
1123 return CR_BAD_PARAM_ERROR;
1124 }
1125
1126 status = CR_UNKNOWN_PROP_VAL_ERROR;
1127
1128 if (a_value->type == TERM_IDENT) {
1129 if (a_value->content.str
1130 && a_value->content.str->stryng
1131 && a_value->content.str->stryng->str) {
1132 status = cr_rgb_set_from_name
1133 (rgb_color,
1134 (const guchar *) a_value->content.str->stryng->str);
1135
1136 }
1137 if (status != CR_OK) {
1138 cr_rgb_set_from_name (rgb_color, (const guchar *) "black");
1139 }
1140 } else if (a_value->type == TERM_RGB) {
1141 if (a_value->content.rgb) {
1142 status = cr_rgb_set_from_rgb
1143 (rgb_color, a_value->content.rgb);
1144 }
1145 }
1146 return status;
1147 }
1148
1149 static enum CRStatus
set_prop_border_x_from_value(CRStyle * a_style,CRTerm * a_value,enum CRDirection a_dir)1150 set_prop_border_x_from_value (CRStyle * a_style, CRTerm * a_value,
1151 enum CRDirection a_dir)
1152 {
1153 CRTerm *cur_term = NULL;
1154
1155 enum CRStatus status = CR_OK;
1156
1157 g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
1158
1159 for (cur_term = a_value;
1160 cur_term;
1161 cur_term = cur_term->next) {
1162 status = set_prop_border_x_width_from_value (a_style,
1163 cur_term, a_dir);
1164
1165 if (status != CR_OK) {
1166 status = set_prop_border_x_style_from_value
1167 (a_style, cur_term, a_dir);
1168 }
1169 if (status != CR_OK) {
1170 status = set_prop_border_x_color_from_value
1171 (a_style, cur_term, a_dir);
1172 }
1173 }
1174 return CR_OK;
1175 }
1176
1177 static enum CRStatus
set_prop_border_from_value(CRStyle * a_style,CRTerm * a_value)1178 set_prop_border_from_value (CRStyle * a_style, CRTerm * a_value)
1179 {
1180 enum CRDirection direction = 0;
1181
1182 g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
1183
1184 for (direction = 0; direction < NB_DIRS; direction++) {
1185 set_prop_border_x_from_value (a_style,
1186 a_value,
1187 direction);
1188 }
1189
1190 return CR_OK;
1191 }
1192
1193 static enum CRStatus
set_prop_padding_from_value(CRStyle * a_style,CRTerm * a_value)1194 set_prop_padding_from_value (CRStyle * a_style, CRTerm * a_value)
1195 {
1196 CRTerm *cur_term = NULL;
1197 enum CRDirection direction = 0;
1198 enum CRStatus status = CR_OK;
1199
1200 g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
1201
1202 cur_term = a_value;
1203
1204 /*filter the eventual non NUMBER terms some user can have written here*/
1205 while (cur_term && cur_term->type != TERM_NUMBER) {
1206 cur_term = cur_term->next;
1207 }
1208 if (!cur_term)
1209 return CR_ERROR ;
1210
1211 for (direction = 0; direction < NB_DIRS; direction++) {
1212 set_prop_padding_x_from_value (a_style, cur_term, direction);
1213 }
1214 cur_term = cur_term->next;
1215
1216 /*filter non NUMBER terms that some users can have written here...*/
1217 while (cur_term && cur_term->type != TERM_NUMBER) {
1218 cur_term = cur_term->next;
1219 }
1220 /*the user can have just written padding: 1px*/
1221 if (!cur_term)
1222 return CR_OK;
1223
1224 set_prop_padding_x_from_value (a_style, cur_term, DIR_RIGHT);
1225 set_prop_padding_x_from_value (a_style, cur_term, DIR_LEFT);
1226
1227 while (cur_term && cur_term->type != TERM_NUMBER) {
1228 cur_term = cur_term->next;
1229 }
1230 if (!cur_term)
1231 return CR_OK;
1232
1233 set_prop_padding_x_from_value (a_style, cur_term, DIR_BOTTOM);
1234
1235 while (cur_term && cur_term->type != TERM_NUMBER) {
1236 cur_term = cur_term->next;
1237 }
1238 if (!cur_term)
1239 return CR_OK;
1240 status = set_prop_padding_x_from_value (a_style, cur_term, DIR_LEFT);
1241 return status;
1242 }
1243
1244 static enum CRStatus
set_prop_margin_from_value(CRStyle * a_style,CRTerm * a_value)1245 set_prop_margin_from_value (CRStyle * a_style, CRTerm * a_value)
1246 {
1247 CRTerm *cur_term = NULL;
1248 enum CRDirection direction = 0;
1249 enum CRStatus status = CR_OK;
1250
1251 g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
1252
1253 cur_term = a_value;
1254
1255 while (cur_term && cur_term->type != TERM_NUMBER) {
1256 cur_term = cur_term->next;
1257 }
1258
1259 if (!cur_term)
1260 return CR_OK;
1261
1262 for (direction = 0; direction < NB_DIRS; direction++) {
1263 set_prop_margin_x_from_value (a_style, cur_term, direction);
1264 }
1265 cur_term = cur_term->next;
1266
1267 while (cur_term && cur_term->type != TERM_NUMBER) {
1268 cur_term = cur_term->next;
1269 }
1270 if (!cur_term)
1271 return CR_OK;
1272
1273 set_prop_margin_x_from_value (a_style, cur_term, DIR_RIGHT);
1274 set_prop_margin_x_from_value (a_style, cur_term, DIR_LEFT);
1275
1276 while (cur_term && cur_term->type != TERM_NUMBER) {
1277 cur_term = cur_term->next;
1278 }
1279 if (!cur_term)
1280 return CR_OK;
1281
1282 set_prop_margin_x_from_value (a_style, cur_term, DIR_BOTTOM);
1283
1284 while (cur_term && cur_term->type != TERM_NUMBER) {
1285 cur_term = cur_term->next;
1286 }
1287 if (!cur_term)
1288 return CR_OK;
1289
1290 status = set_prop_margin_x_from_value (a_style, cur_term, DIR_LEFT);
1291
1292 return status;
1293 }
1294
1295 static enum CRStatus
set_prop_font_family_from_value(CRStyle * a_style,CRTerm * a_value)1296 set_prop_font_family_from_value (CRStyle * a_style, CRTerm * a_value)
1297 {
1298 CRTerm *cur_term = NULL;
1299 CRFontFamily *font_family = NULL,
1300 *cur_ff = NULL,
1301 *cur_ff2 = NULL;
1302
1303 g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
1304
1305 if (a_value->type == TERM_IDENT &&
1306 a_value->content.str &&
1307 a_value->content.str->stryng &&
1308 a_value->content.str->stryng->str &&
1309 !strcmp ("inherit", a_value->content.str->stryng->str))
1310 {
1311 font_family = cr_font_family_new (FONT_FAMILY_INHERIT, NULL);
1312 goto out;
1313 }
1314
1315 for (cur_term = a_value; cur_term; cur_term = cur_term->next) {
1316 switch (cur_term->type) {
1317 case TERM_IDENT:
1318 {
1319 enum CRFontFamilyType font_type;
1320
1321 if (cur_term->content.str
1322 && cur_term->content.str->stryng
1323 && cur_term->content.str->stryng->str
1324 && !strcmp
1325 (cur_term->content.str->stryng->str,
1326 "sans-serif")) {
1327 font_type = FONT_FAMILY_SANS_SERIF;
1328 } else if (cur_term->content.str
1329 && cur_term->content.str->stryng
1330 && cur_term->content.str->stryng->str
1331 && !strcmp
1332 (cur_term->content.str->stryng->str,
1333 "serif")) {
1334 font_type = FONT_FAMILY_SERIF;
1335 } else if (cur_term->content.str
1336 && cur_term->content.str->stryng
1337 && cur_term->content.str->stryng->str
1338 && !strcmp (cur_term->content.str->stryng->str,
1339 "cursive")) {
1340 font_type = FONT_FAMILY_CURSIVE;
1341 } else if (cur_term->content.str
1342 && cur_term->content.str->stryng
1343 && cur_term->content.str->stryng->str
1344 && !strcmp (cur_term->content.str->stryng->str,
1345 "fantasy")) {
1346 font_type = FONT_FAMILY_FANTASY;
1347 } else if (cur_term->content.str
1348 && cur_term->content.str->stryng
1349 && cur_term->content.str->stryng->str
1350 && !strcmp (cur_term->content.str->stryng->str,
1351 "monospace")) {
1352 font_type = FONT_FAMILY_MONOSPACE;
1353 } else {
1354 /*
1355 *unknown property value.
1356 *ignore it.
1357 */
1358 continue;
1359 }
1360
1361 cur_ff = cr_font_family_new (font_type, NULL);
1362 }
1363 break;
1364
1365 case TERM_STRING:
1366 {
1367 if (cur_term->content.str
1368 && cur_term->content.str->stryng
1369 && cur_term->content.str->stryng->str) {
1370 cur_ff = cr_font_family_new
1371 (FONT_FAMILY_NON_GENERIC,
1372 (guchar *) cur_term->content.str->stryng->str);
1373 }
1374 }
1375 break;
1376
1377 default:
1378 break;
1379 }
1380
1381 cur_ff2 = cr_font_family_append (font_family, cur_ff);
1382 if (cur_ff2) {
1383 font_family = cur_ff2;
1384 }
1385 }
1386
1387 out:
1388 if (font_family) {
1389 if (a_style->font_family) {
1390 cr_font_family_destroy (a_style->font_family);
1391 a_style->font_family = NULL ;
1392 }
1393 a_style->font_family = font_family;
1394 font_family = NULL ;
1395 }
1396
1397 return CR_OK;
1398 }
1399
1400 static enum CRStatus
init_style_font_size_field(CRStyle * a_style)1401 init_style_font_size_field (CRStyle * a_style)
1402 {
1403 g_return_val_if_fail (a_style, CR_BAD_PARAM_ERROR);
1404
1405 memset (&a_style->font_size, 0,
1406 sizeof (CRFontSizeVal)) ;
1407 /*
1408 if (!a_style->font_size) {
1409 a_style->font_size = cr_font_size_new ();
1410 if (!a_style->font_size) {
1411 return CR_INSTANCIATION_FAILED_ERROR;
1412 }
1413 } else {
1414 cr_font_size_clear (a_style->font_size);
1415 }
1416 */
1417 return CR_OK;
1418 }
1419
1420 static enum CRStatus
set_prop_font_size_from_value(CRStyle * a_style,CRTerm * a_value)1421 set_prop_font_size_from_value (CRStyle * a_style, CRTerm * a_value)
1422 {
1423 enum CRStatus status = CR_OK;
1424
1425 g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
1426
1427 switch (a_value->type) {
1428 case TERM_IDENT:
1429 if (a_value->content.str
1430 && a_value->content.str->stryng
1431 && a_value->content.str->stryng->str
1432 && !strcmp (a_value->content.str->stryng->str,
1433 "xx-small")) {
1434 status = init_style_font_size_field (a_style);
1435 g_return_val_if_fail (status == CR_OK, status);
1436
1437 a_style->font_size.sv.type =
1438 PREDEFINED_ABSOLUTE_FONT_SIZE;
1439 a_style->font_size.sv.value.predefined =
1440 FONT_SIZE_XX_SMALL;
1441
1442 } else if (a_value->content.str
1443 && a_value->content.str->stryng
1444 && a_value->content.str->stryng->str
1445 && !strcmp (a_value->content.str->stryng->str,
1446 "x-small")) {
1447 status = init_style_font_size_field (a_style);
1448 g_return_val_if_fail (status == CR_OK, status);
1449
1450 a_style->font_size.sv.type =
1451 PREDEFINED_ABSOLUTE_FONT_SIZE;
1452 a_style->font_size.sv.value.predefined =
1453 FONT_SIZE_X_SMALL;
1454 } else if (a_value->content.str
1455 && a_value->content.str->stryng
1456 && a_value->content.str->stryng->str
1457 && !strcmp (a_value->content.str->stryng->str,
1458 "small")) {
1459 status = init_style_font_size_field (a_style);
1460 g_return_val_if_fail (status == CR_OK, status);
1461
1462 a_style->font_size.sv.type =
1463 PREDEFINED_ABSOLUTE_FONT_SIZE;
1464 a_style->font_size.sv.value.predefined =
1465 FONT_SIZE_SMALL;
1466 } else if (a_value->content.str
1467 && a_value->content.str->stryng
1468 && a_value->content.str->stryng->str
1469 && !strcmp (a_value->content.str->stryng->str, "medium")) {
1470 status = init_style_font_size_field (a_style);
1471 g_return_val_if_fail (status == CR_OK, status);
1472
1473 a_style->font_size.sv.type =
1474 PREDEFINED_ABSOLUTE_FONT_SIZE;
1475 a_style->font_size.sv.value.predefined =
1476 FONT_SIZE_MEDIUM;
1477 } else if (a_value->content.str
1478 && a_value->content.str->stryng
1479 && a_value->content.str->stryng->str
1480 && !strcmp (a_value->content.str->stryng->str,
1481 "large")) {
1482 status = init_style_font_size_field (a_style);
1483 g_return_val_if_fail (status == CR_OK, status);
1484
1485 a_style->font_size.sv.type =
1486 PREDEFINED_ABSOLUTE_FONT_SIZE;
1487 a_style->font_size.sv.value.predefined =
1488 FONT_SIZE_LARGE;
1489 } else if (a_value->content.str
1490 && a_value->content.str->stryng
1491 && a_value->content.str->stryng->str
1492 && !strcmp (a_value->content.str->stryng->str,
1493 "x-large")) {
1494 status = init_style_font_size_field (a_style);
1495 g_return_val_if_fail (status == CR_OK, status);
1496
1497 a_style->font_size.sv.type =
1498 PREDEFINED_ABSOLUTE_FONT_SIZE;
1499 a_style->font_size.sv.value.predefined =
1500 FONT_SIZE_X_LARGE;
1501 } else if (a_value->content.str
1502 && a_value->content.str->stryng
1503 && a_value->content.str->stryng->str
1504 && !strcmp (a_value->content.str->stryng->str,
1505 "xx-large")) {
1506 status = init_style_font_size_field (a_style);
1507 g_return_val_if_fail (status == CR_OK, status);
1508
1509 a_style->font_size.sv.type =
1510 PREDEFINED_ABSOLUTE_FONT_SIZE;
1511 a_style->font_size.sv.value.predefined =
1512 FONT_SIZE_XX_LARGE;
1513 } else if (a_value->content.str
1514 && a_value->content.str->stryng
1515 && a_value->content.str->stryng->str
1516 && !strcmp (a_value->content.str->stryng->str,
1517 "larger")) {
1518 status = init_style_font_size_field (a_style);
1519 g_return_val_if_fail (status == CR_OK, status);
1520
1521 a_style->font_size.sv.type = RELATIVE_FONT_SIZE;
1522 a_style->font_size.sv.value.relative = FONT_SIZE_LARGER;
1523 } else if (a_value->content.str
1524 && a_value->content.str->stryng
1525 && a_value->content.str->stryng->str
1526 && !strcmp (a_value->content.str->stryng->str,
1527 "smaller")) {
1528 status = init_style_font_size_field (a_style);
1529 g_return_val_if_fail (status == CR_OK, status);
1530
1531 a_style->font_size.sv.type = RELATIVE_FONT_SIZE;
1532 a_style->font_size.sv.value.relative =
1533 FONT_SIZE_SMALLER;
1534 } else if (a_value->content.str
1535 && a_value->content.str->stryng
1536 && a_value->content.str->stryng->str
1537 && !strcmp (a_value->content.str->stryng->str, "inherit")) {
1538 status = init_style_font_size_field (a_style);
1539 g_return_val_if_fail (status == CR_OK, status);
1540 a_style->font_size.sv.type = INHERITED_FONT_SIZE;
1541
1542 } else {
1543 cr_utils_trace_info ("Unknown value of font-size") ;
1544 status = init_style_font_size_field (a_style);
1545 return CR_UNKNOWN_PROP_VAL_ERROR;
1546 }
1547 break;
1548
1549 case TERM_NUMBER:
1550 if (a_value->content.num) {
1551 status = init_style_font_size_field (a_style);
1552 g_return_val_if_fail (status == CR_OK, status);
1553
1554 a_style->font_size.sv.type = ABSOLUTE_FONT_SIZE;
1555 cr_num_copy (&a_style->font_size.sv.value.absolute,
1556 a_value->content.num) ;
1557 }
1558 break;
1559
1560 default:
1561 status = init_style_font_size_field (a_style);
1562 return CR_UNKNOWN_PROP_VAL_ERROR;
1563 }
1564 return CR_OK;
1565 }
1566
1567 static enum CRStatus
set_prop_font_style_from_value(CRStyle * a_style,CRTerm * a_value)1568 set_prop_font_style_from_value (CRStyle * a_style, CRTerm * a_value)
1569 {
1570 enum CRStatus status = CR_OK;
1571
1572 g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
1573
1574 switch (a_value->type) {
1575 case TERM_IDENT:
1576 if (a_value->content.str
1577 && a_value->content.str->stryng
1578 && a_value->content.str->stryng->str) {
1579 if (!strcmp (a_value->content.str->stryng->str, "normal")) {
1580 a_style->font_style = FONT_STYLE_NORMAL;
1581 } else if (!strcmp
1582 (a_value->content.str->stryng->str,
1583 "italic")) {
1584 a_style->font_style = FONT_STYLE_ITALIC;
1585 } else if (!strcmp
1586 (a_value->content.str->stryng->str,
1587 "oblique")) {
1588 a_style->font_style = FONT_STYLE_OBLIQUE;
1589 } else if (!strcmp
1590 (a_value->content.str->stryng->str,
1591 "inherit")) {
1592 a_style->font_style = FONT_STYLE_INHERIT;
1593 } else {
1594 status = CR_UNKNOWN_PROP_VAL_ERROR;
1595 }
1596 }
1597 break;
1598
1599 default:
1600 status = CR_UNKNOWN_PROP_VAL_ERROR;
1601 break;
1602 }
1603
1604 return status;
1605 }
1606
1607 static enum CRStatus
set_prop_font_weight_from_value(CRStyle * a_style,CRTerm * a_value)1608 set_prop_font_weight_from_value (CRStyle * a_style, CRTerm * a_value)
1609 {
1610 enum CRStatus status = CR_OK;
1611
1612 g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
1613
1614 switch (a_value->type) {
1615 case TERM_IDENT:
1616 if (a_value->content.str
1617 && a_value->content.str->stryng
1618 && a_value->content.str->stryng->str) {
1619 if (!strcmp (a_value->content.str->stryng->str,
1620 "normal")) {
1621 a_style->font_weight = FONT_WEIGHT_NORMAL;
1622 } else if (!strcmp (a_value->content.str->stryng->str,
1623 "bold")) {
1624 a_style->font_weight = FONT_WEIGHT_BOLD;
1625 } else if (!strcmp (a_value->content.str->stryng->str,
1626 "bolder")) {
1627 a_style->font_weight = FONT_WEIGHT_BOLDER;
1628 } else if (!strcmp (a_value->content.str->stryng->str,
1629 "lighter")) {
1630 a_style->font_weight = FONT_WEIGHT_LIGHTER;
1631 } else if (!strcmp (a_value->content.str->stryng->str,
1632 "inherit")) {
1633 a_style->font_weight = FONT_WEIGHT_INHERIT;
1634
1635 } else {
1636 status = CR_UNKNOWN_PROP_VAL_ERROR;
1637 }
1638
1639 }
1640 break;
1641
1642 case TERM_NUMBER:
1643 if (a_value->content.num
1644 && (a_value->content.num->type == NUM_GENERIC
1645 || a_value->content.num->type == NUM_AUTO)) {
1646 if (a_value->content.num->val <= 150) {
1647 a_style->font_weight = FONT_WEIGHT_100;
1648 } else if (a_value->content.num->val <= 250) {
1649 a_style->font_weight = FONT_WEIGHT_200;
1650 } else if (a_value->content.num->val <= 350) {
1651 a_style->font_weight = FONT_WEIGHT_300;
1652 } else if (a_value->content.num->val <= 450) {
1653 a_style->font_weight = FONT_WEIGHT_400;
1654 } else if (a_value->content.num->val <= 550) {
1655 a_style->font_weight = FONT_WEIGHT_500;
1656 } else if (a_value->content.num->val <= 650) {
1657 a_style->font_weight = FONT_WEIGHT_600;
1658 } else if (a_value->content.num->val <= 750) {
1659 a_style->font_weight = FONT_WEIGHT_700;
1660 } else if (a_value->content.num->val <= 850) {
1661 a_style->font_weight = FONT_WEIGHT_800;
1662 } else {
1663 a_style->font_weight = FONT_WEIGHT_900;
1664 }
1665 }
1666 break;
1667
1668 default:
1669 status = CR_UNKNOWN_PROP_VAL_ERROR;
1670 break;
1671 }
1672
1673 return status;
1674 }
1675
1676 static enum CRStatus
set_prop_white_space_from_value(CRStyle * a_style,CRTerm * a_value)1677 set_prop_white_space_from_value (CRStyle * a_style, CRTerm * a_value)
1678 {
1679 enum CRStatus status = CR_OK;
1680
1681 g_return_val_if_fail (a_style && a_value, CR_BAD_PARAM_ERROR);
1682
1683 switch (a_value->type) {
1684 case TERM_IDENT:
1685 if (a_value->content.str && a_value->content.str->stryng) {
1686 if (!strcmp (a_value->content.str->stryng->str, "normal")) {
1687 a_style->white_space = WHITE_SPACE_NORMAL;
1688 } else if (!strcmp (a_value->content.str->stryng->str,
1689 "pre")) {
1690 a_style->white_space = WHITE_SPACE_PRE;
1691 } else if (!strcmp (a_value->content.str->stryng->str,
1692 "nowrap")) {
1693 a_style->white_space = WHITE_SPACE_NOWRAP;
1694 } else if (!strcmp (a_value->content.str->stryng->str,
1695 "inherit")) {
1696 a_style->white_space = WHITE_SPACE_INHERIT;
1697 } else {
1698 status = CR_UNKNOWN_PROP_VAL_ERROR;
1699 }
1700 }
1701 break;
1702 default:
1703 status = CR_UNKNOWN_PROP_VAL_ERROR;
1704 break;
1705 }
1706
1707 return status;
1708 }
1709
1710 /******************
1711 *Public methods
1712 ******************/
1713
1714 /**
1715 *Default constructor of #CRStyle.
1716 *@param a_set_props_to_initial_values if TRUE, the style properties
1717 *will be set to the default values. Only the style properties of the
1718 *root box should be set to their initial values.
1719 *Otherwise, the style values are set to their default value.
1720 *Read the CSS2 spec, chapters 6.1.1 to 6.2.
1721 */
1722 CRStyle *
cr_style_new(gboolean a_set_props_to_initial_values)1723 cr_style_new (gboolean a_set_props_to_initial_values)
1724 {
1725 CRStyle *result = NULL;
1726
1727 result = g_try_malloc (sizeof (CRStyle));
1728 if (!result) {
1729 cr_utils_trace_info ("Out of memory");
1730 return NULL;
1731 }
1732 memset (result, 0, sizeof (CRStyle));
1733 gv_prop_hash_ref_count++;
1734
1735 if (a_set_props_to_initial_values == TRUE) {
1736 cr_style_set_props_to_initial_values (result);
1737 } else {
1738 cr_style_set_props_to_default_values (result);
1739 }
1740
1741 return result;
1742 }
1743
1744 /**
1745 *Sets the style properties to their default values according to the css2 spec
1746 * i.e inherit if the property is inherited, its initial value otherwise.
1747 *@param a_this the current instance of #CRStyle.
1748 *@return CR_OK upon successfull completion, an error code otherwise.
1749 */
1750 enum CRStatus
cr_style_set_props_to_default_values(CRStyle * a_this)1751 cr_style_set_props_to_default_values (CRStyle * a_this)
1752 {
1753 glong i = 0;
1754
1755 g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
1756
1757 for (i = 0; i < NB_NUM_PROPS; i++)
1758 {
1759 switch (i)
1760 {
1761 case NUM_PROP_WIDTH:
1762 case NUM_PROP_TOP:
1763 case NUM_PROP_RIGHT:
1764 case NUM_PROP_BOTTOM:
1765 case NUM_PROP_LEFT:
1766 cr_num_set (&a_this->num_props[i].sv, 0, NUM_AUTO);
1767 break;
1768
1769 case NUM_PROP_PADDING_TOP:
1770 case NUM_PROP_PADDING_RIGHT:
1771 case NUM_PROP_PADDING_BOTTOM:
1772 case NUM_PROP_PADDING_LEFT:
1773 case NUM_PROP_BORDER_TOP:
1774 case NUM_PROP_BORDER_RIGHT:
1775 case NUM_PROP_BORDER_BOTTOM:
1776 case NUM_PROP_BORDER_LEFT:
1777 case NUM_PROP_MARGIN_TOP:
1778 case NUM_PROP_MARGIN_RIGHT:
1779 case NUM_PROP_MARGIN_BOTTOM:
1780 case NUM_PROP_MARGIN_LEFT:
1781 cr_num_set (&a_this->num_props[i].sv,
1782 0, NUM_LENGTH_PX);
1783 break;
1784
1785 default:
1786 cr_utils_trace_info ("Unknown property");
1787 break;
1788 }
1789 }
1790
1791 for (i = 0; i < NB_RGB_PROPS; i++) {
1792
1793 switch (i) {
1794 /*default foreground color is black */
1795 case RGB_PROP_COLOR:
1796 /*
1797 *REVIEW: color is inherited and the default value is
1798 *ua dependant.
1799 */
1800 cr_rgb_set_to_inherit (&a_this->rgb_props[i].sv,
1801 TRUE) ;
1802 break;
1803
1804 /*default background color is white */
1805 case RGB_PROP_BACKGROUND_COLOR:
1806 /* TODO: the default value should be transparent */
1807 cr_rgb_set (&a_this->rgb_props[i].sv,
1808 255, 255, 255, FALSE);
1809 cr_rgb_set_to_transparent (&a_this->rgb_props[i].sv,
1810 TRUE) ;
1811 break;
1812
1813 default:
1814 /*
1815 *TODO: for BORDER_COLOR the initial value should
1816 * be the same as COLOR
1817 */
1818 cr_rgb_set (&a_this->rgb_props[i].sv, 0, 0, 0,
1819 FALSE);
1820 break;
1821 }
1822 }
1823
1824 for (i = 0; i < NB_BORDER_STYLE_PROPS; i++) {
1825 a_this->border_style_props[i] = BORDER_STYLE_NONE;
1826 }
1827
1828 a_this->display = DISPLAY_INLINE;
1829 a_this->position = POSITION_STATIC;
1830 a_this->float_type = FLOAT_NONE;
1831 a_this->parent_style = NULL;
1832 a_this->font_style = FONT_STYLE_INHERIT;
1833 a_this->font_variant = FONT_VARIANT_INHERIT;
1834 a_this->font_weight = FONT_WEIGHT_INHERIT;
1835 a_this->font_family = NULL;
1836
1837 cr_font_size_set_to_inherit (&a_this->font_size.sv) ;
1838 cr_font_size_clear (&a_this->font_size.cv) ;
1839 cr_font_size_clear (&a_this->font_size.av) ;
1840
1841 /* To make the inheritance resolution possible and efficient */
1842 a_this->inherited_props_resolved = FALSE ;
1843 return CR_OK;
1844 }
1845
1846 /**
1847 *Sets the style properties to their initial value according to the css2 spec.
1848 *This function should be used to initialize the style of the root element
1849 *of an xml tree.
1850 *Some properties are user agent dependant like font-family, and
1851 *are not initialized, read the spec to make you renderer compliant.
1852 *@param a_this the current instance of #CRStyle.
1853 *@return CR_OK upon successfull completion, an error code otherwise.
1854 */
1855 enum CRStatus
cr_style_set_props_to_initial_values(CRStyle * a_this)1856 cr_style_set_props_to_initial_values (CRStyle *a_this)
1857 {
1858 glong i = 0;
1859
1860 g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
1861
1862 for (i = 0; i < NB_NUM_PROPS; i++) {
1863 switch (i) {
1864 case NUM_PROP_WIDTH:
1865 cr_num_set (&a_this->num_props[i].sv, 800,
1866 NUM_LENGTH_PX) ;
1867 break ;
1868 case NUM_PROP_TOP:
1869 case NUM_PROP_RIGHT:
1870 case NUM_PROP_BOTTOM:
1871 case NUM_PROP_LEFT:
1872 cr_num_set (&a_this->num_props[i].sv, 0, NUM_AUTO);
1873 break;
1874
1875 case NUM_PROP_PADDING_TOP:
1876 case NUM_PROP_PADDING_RIGHT:
1877 case NUM_PROP_PADDING_BOTTOM:
1878 case NUM_PROP_PADDING_LEFT:
1879 case NUM_PROP_BORDER_TOP:
1880 case NUM_PROP_BORDER_RIGHT:
1881 case NUM_PROP_BORDER_BOTTOM:
1882 case NUM_PROP_BORDER_LEFT:
1883 case NUM_PROP_MARGIN_TOP:
1884 case NUM_PROP_MARGIN_RIGHT:
1885 case NUM_PROP_MARGIN_BOTTOM:
1886 case NUM_PROP_MARGIN_LEFT:
1887 cr_num_set (&a_this->num_props[i].sv,
1888 0, NUM_LENGTH_PX);
1889 break;
1890
1891 default:
1892 cr_utils_trace_info ("Unknown property");
1893 break;
1894 }
1895 }
1896
1897 for (i = 0; i < NB_RGB_PROPS; i++) {
1898
1899 switch (i) {
1900 /*default foreground color is black */
1901 case RGB_PROP_COLOR:
1902 cr_rgb_set (&a_this->rgb_props[i].sv, 0, 0, 0, FALSE);
1903 break;
1904
1905 /*default background color is white */
1906 case RGB_PROP_BACKGROUND_COLOR:
1907 cr_rgb_set (&a_this->rgb_props[i].sv,
1908 255, 255, 255, FALSE);
1909 cr_rgb_set_to_transparent (&a_this->rgb_props[i].sv,
1910 TRUE) ;
1911 break;
1912 default:
1913 cr_rgb_set (&a_this->rgb_props[i].sv, 0, 0, 0, FALSE);
1914 break;
1915 }
1916 }
1917
1918 for (i = 0; i < NB_BORDER_STYLE_PROPS; i++) {
1919 a_this->border_style_props[i] = BORDER_STYLE_NONE;
1920 }
1921
1922 a_this->display = DISPLAY_BLOCK;
1923 a_this->position = POSITION_STATIC;
1924 a_this->float_type = FLOAT_NONE;
1925 a_this->font_style = FONT_STYLE_NORMAL;
1926 a_this->font_variant = FONT_VARIANT_NORMAL;
1927 a_this->font_weight = FONT_WEIGHT_NORMAL;
1928 a_this->font_stretch = FONT_STRETCH_NORMAL;
1929 a_this->white_space = WHITE_SPACE_NORMAL;
1930 cr_font_size_set_predefined_absolute_font_size
1931 (&a_this->font_size.sv, FONT_SIZE_MEDIUM) ;
1932 a_this->inherited_props_resolved = FALSE ;
1933
1934 return CR_OK;
1935 }
1936
1937 /**
1938 *Resolves the inherited properties.
1939 *The function sets the "inherited" properties to either the value of
1940 *their parent properties.
1941 *This function is *NOT* recursive. So the inherited properties of
1942 *the parent style must have been resolved prior to calling this function.
1943 *@param a_this the instance where
1944 *@return CR_OK if a root node is found and the propagation is successful,
1945 *an error code otherwise
1946 */
1947 enum CRStatus
cr_style_resolve_inherited_properties(CRStyle * a_this)1948 cr_style_resolve_inherited_properties (CRStyle *a_this)
1949 {
1950 enum CRStatus ret = CR_OK;
1951 glong i = 0;
1952
1953 g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
1954 g_return_val_if_fail (a_this->parent_style, CR_BAD_PARAM_ERROR) ;
1955
1956 if (a_this->inherited_props_resolved == TRUE)
1957 return CR_OK ;
1958
1959 for (i=0 ; i < NB_NUM_PROPS ;i++) {
1960 if (a_this->num_props[i].sv.type == NUM_INHERIT) {
1961 cr_num_copy (&a_this->num_props[i].cv,
1962 &a_this->parent_style->num_props[i].cv);
1963 }
1964 }
1965 for (i=0; i < NB_RGB_PROPS; i++) {
1966 if (cr_rgb_is_set_to_inherit (&a_this->rgb_props[i].sv) == TRUE) {
1967 cr_rgb_copy (
1968 &a_this->rgb_props[i].cv,
1969 &a_this->parent_style->rgb_props[i].cv);
1970 }
1971 }
1972 for (i = 0; i < NB_BORDER_STYLE_PROPS; i++) {
1973 if (a_this->border_style_props[i] == BORDER_STYLE_INHERIT) {
1974 a_this->border_style_props[i] =
1975 a_this->parent_style->border_style_props[i];
1976 }
1977 }
1978
1979 if (a_this->display == DISPLAY_INHERIT) {
1980 a_this->display = a_this->parent_style->display;
1981 }
1982 if (a_this->position == POSITION_INHERIT) {
1983 a_this->position = a_this->parent_style->position;
1984 }
1985 if (a_this->float_type == FLOAT_INHERIT) {
1986 a_this->float_type = a_this->parent_style->float_type;
1987 }
1988 if (a_this->font_style == FONT_STYLE_INHERIT) {
1989 a_this->font_style = a_this->parent_style->font_style;
1990 }
1991 if (a_this->font_variant == FONT_VARIANT_INHERIT) {
1992 a_this->font_variant = a_this->parent_style->font_variant;
1993 }
1994 if (a_this->font_weight == FONT_WEIGHT_INHERIT) {
1995 a_this->font_weight = a_this->parent_style->font_weight;
1996 }
1997 if (a_this->font_stretch == FONT_STRETCH_INHERIT) {
1998 a_this->font_stretch = a_this->parent_style->font_stretch;
1999 }
2000 /*NULL is inherit marker for font_famiy*/
2001 if (a_this->font_family == NULL) {
2002 a_this->font_family = a_this->parent_style->font_family;
2003 }
2004 if (a_this->font_size.sv.type == INHERITED_FONT_SIZE) {
2005 cr_font_size_copy (&a_this->font_size.cv,
2006 &a_this->parent_style->font_size.cv) ;
2007 }
2008 a_this->inherited_props_resolved = TRUE ;
2009 return ret;
2010 }
2011
2012 /**
2013 *Walks through a css2 property declaration, and populated the
2014 *according field(s) in the #CRStyle structure.
2015 *If the properties or their value(s) are/is not known,
2016 *sets the corresponding field(s) of #CRStyle to its/their default
2017 *value(s)
2018 *@param a_this the instance of #CRStyle to set.
2019 *@param a_decl the declaration from which the #CRStyle fields are set.
2020 *@return CR_OK upon successfull completion, an error code otherwise.
2021 */
2022 enum CRStatus
cr_style_set_style_from_decl(CRStyle * a_this,CRDeclaration * a_decl)2023 cr_style_set_style_from_decl (CRStyle * a_this, CRDeclaration * a_decl)
2024 {
2025 CRTerm *value = NULL;
2026 enum CRStatus status = CR_OK;
2027
2028 enum CRPropertyID prop_id = PROP_ID_NOT_KNOWN;
2029
2030 g_return_val_if_fail (a_this && a_decl
2031 && a_decl
2032 && a_decl->property
2033 && a_decl->property->stryng
2034 && a_decl->property->stryng->str,
2035 CR_BAD_PARAM_ERROR);
2036
2037 prop_id = cr_style_get_prop_id
2038 ((const guchar *) a_decl->property->stryng->str);
2039
2040 value = a_decl->value;
2041 switch (prop_id) {
2042 case PROP_ID_PADDING_TOP:
2043 status = set_prop_padding_x_from_value
2044 (a_this, value, DIR_TOP);
2045 break;
2046
2047 case PROP_ID_PADDING_RIGHT:
2048 status = set_prop_padding_x_from_value
2049 (a_this, value, DIR_RIGHT);
2050 break;
2051 case PROP_ID_PADDING_BOTTOM:
2052 status = set_prop_padding_x_from_value
2053 (a_this, value, DIR_BOTTOM);
2054 break;
2055
2056 case PROP_ID_PADDING_LEFT:
2057 status = set_prop_padding_x_from_value
2058 (a_this, value, DIR_LEFT);
2059 break;
2060
2061 case PROP_ID_PADDING:
2062 status = set_prop_padding_from_value (a_this, value) ;
2063 break;
2064
2065 case PROP_ID_BORDER_TOP_WIDTH:
2066 status = set_prop_border_x_width_from_value (a_this, value,
2067 DIR_TOP);
2068 break;
2069
2070 case PROP_ID_BORDER_RIGHT_WIDTH:
2071 status = set_prop_border_x_width_from_value (a_this, value,
2072 DIR_RIGHT);
2073 break;
2074
2075 case PROP_ID_BORDER_BOTTOM_WIDTH:
2076 status = set_prop_border_x_width_from_value (a_this, value,
2077 DIR_BOTTOM);
2078 break;
2079
2080 case PROP_ID_BORDER_LEFT_WIDTH:
2081 status = set_prop_border_x_width_from_value (a_this, value,
2082 DIR_LEFT);
2083 break;
2084
2085 case PROP_ID_BORDER_WIDTH:
2086 status = set_prop_border_width_from_value (a_this, value) ;
2087 break ;
2088
2089 case PROP_ID_BORDER_TOP_STYLE:
2090 status = set_prop_border_x_style_from_value (a_this, value,
2091 DIR_TOP);
2092 break;
2093
2094 case PROP_ID_BORDER_RIGHT_STYLE:
2095 status = set_prop_border_x_style_from_value (a_this, value,
2096 DIR_RIGHT);
2097 break;
2098
2099 case PROP_ID_BORDER_BOTTOM_STYLE:
2100 status = set_prop_border_x_style_from_value (a_this, value,
2101 DIR_BOTTOM);
2102 break;
2103
2104 case PROP_ID_BORDER_LEFT_STYLE:
2105 status = set_prop_border_x_style_from_value (a_this, value,
2106 DIR_LEFT);
2107 break;
2108
2109 case PROP_ID_BORDER_STYLE:
2110 status = set_prop_border_style_from_value (a_this, value) ;
2111 break ;
2112
2113 case PROP_ID_BORDER_TOP_COLOR:
2114 status = set_prop_border_x_color_from_value (a_this, value,
2115 DIR_TOP);
2116 break;
2117
2118 case PROP_ID_BORDER_RIGHT_COLOR:
2119 status = set_prop_border_x_color_from_value (a_this, value,
2120 DIR_RIGHT);
2121 break;
2122
2123 case PROP_ID_BORDER_BOTTOM_COLOR:
2124 status = set_prop_border_x_color_from_value (a_this, value,
2125 DIR_BOTTOM);
2126 break;
2127
2128 case PROP_ID_BORDER_LEFT_COLOR:
2129 status = set_prop_border_x_color_from_value (a_this, value,
2130 DIR_BOTTOM);
2131 break;
2132
2133 case PROP_ID_BORDER_TOP:
2134 status = set_prop_border_x_from_value (a_this, value,
2135 DIR_TOP);
2136 break;
2137
2138 case PROP_ID_BORDER_RIGHT:
2139 status = set_prop_border_x_from_value (a_this, value,
2140 DIR_RIGHT);
2141 break;
2142
2143 case PROP_ID_BORDER_BOTTOM:
2144 status = set_prop_border_x_from_value (a_this, value,
2145 DIR_BOTTOM);
2146 break;
2147
2148 case PROP_ID_BORDER_LEFT:
2149 status = set_prop_border_x_from_value (a_this, value,
2150 DIR_LEFT);
2151 break;
2152
2153 case PROP_ID_MARGIN_TOP:
2154 status = set_prop_margin_x_from_value (a_this, value,
2155 DIR_TOP);
2156 break;
2157
2158 case PROP_ID_BORDER:
2159 status = set_prop_border_from_value (a_this, value);
2160 break;
2161
2162 case PROP_ID_MARGIN_RIGHT:
2163 status = set_prop_margin_x_from_value (a_this, value,
2164 DIR_RIGHT);
2165 break;
2166
2167 case PROP_ID_MARGIN_BOTTOM:
2168 status = set_prop_margin_x_from_value (a_this, value,
2169 DIR_BOTTOM);
2170 break;
2171
2172 case PROP_ID_MARGIN_LEFT:
2173 status = set_prop_margin_x_from_value (a_this, value,
2174 DIR_LEFT);
2175 break;
2176
2177 case PROP_ID_MARGIN:
2178 status = set_prop_margin_from_value (a_this, value);
2179 break;
2180
2181 case PROP_ID_DISPLAY:
2182 status = set_prop_display_from_value (a_this, value);
2183 break;
2184
2185 case PROP_ID_POSITION:
2186 status = set_prop_position_from_value (a_this, value);
2187 break;
2188
2189 case PROP_ID_TOP:
2190 status = set_prop_x_from_value (a_this, value, DIR_TOP);
2191 break;
2192
2193 case PROP_ID_RIGHT:
2194 status = set_prop_x_from_value (a_this, value, DIR_RIGHT);
2195 break;
2196
2197 case PROP_ID_BOTTOM:
2198 status = set_prop_x_from_value (a_this, value, DIR_BOTTOM);
2199 break;
2200
2201 case PROP_ID_LEFT:
2202 status = set_prop_x_from_value (a_this, value, DIR_LEFT);
2203 break;
2204
2205 case PROP_ID_FLOAT:
2206 status = set_prop_float (a_this, value);
2207 break;
2208
2209 case PROP_ID_WIDTH:
2210 status = set_prop_width (a_this, value);
2211 break;
2212
2213 case PROP_ID_COLOR:
2214 status = set_prop_color (a_this, value);
2215 break;
2216
2217 case PROP_ID_BACKGROUND_COLOR:
2218 status = set_prop_background_color (a_this, value);
2219 break;
2220
2221 case PROP_ID_FONT_FAMILY:
2222 status = set_prop_font_family_from_value (a_this, value);
2223 break;
2224
2225 case PROP_ID_FONT_SIZE:
2226 status = set_prop_font_size_from_value (a_this, value);
2227 break;
2228
2229 case PROP_ID_FONT_STYLE:
2230 status = set_prop_font_style_from_value (a_this, value);
2231 break;
2232
2233 case PROP_ID_FONT_WEIGHT:
2234 status = set_prop_font_weight_from_value (a_this, value);
2235 break;
2236
2237 case PROP_ID_WHITE_SPACE:
2238 status = set_prop_white_space_from_value(a_this, value);
2239 break;
2240
2241 default:
2242 return CR_UNKNOWN_TYPE_ERROR;
2243
2244 }
2245
2246 return status;
2247 }
2248
2249 /**
2250 *Increases the reference count
2251 *of the current instance of #CRStyle.
2252 *@param a_this the current instance of #CRStyle.
2253 *@return CR_OK upon successfull completion, an error code
2254 *otherwise.
2255 */
2256 enum CRStatus
cr_style_ref(CRStyle * a_this)2257 cr_style_ref (CRStyle * a_this)
2258 {
2259 g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
2260
2261 a_this->ref_count++;
2262 return CR_OK;
2263 }
2264
2265 /**
2266 *Decreases the reference count of
2267 *the current instance of #CRStyle.
2268 *If the reference count reaches 0, the
2269 *instance of #CRStyle is destoyed.
2270 *@param a_this the current instance of #CRStyle.
2271 *@return TRUE if the instance has been destroyed, FALSE
2272 *otherwise.
2273 */
2274 gboolean
cr_style_unref(CRStyle * a_this)2275 cr_style_unref (CRStyle * a_this)
2276 {
2277 g_return_val_if_fail (a_this, FALSE);
2278
2279 if (a_this->ref_count)
2280 a_this->ref_count--;
2281
2282 if (!a_this->ref_count) {
2283 cr_style_destroy (a_this);
2284 return TRUE;
2285 }
2286
2287 return FALSE;
2288 }
2289
2290 /**
2291 *Duplicates the current instance of #CRStyle .
2292 *The newly created instance of #CRStyle must be
2293 *freed using cr_style_destroy ().
2294 *@param a_this the current instance of #CRStyle.
2295 *@return the newly duplicated instance of #CRStyle.
2296 */
2297 CRStyle *
cr_style_dup(CRStyle * a_this)2298 cr_style_dup (CRStyle * a_this)
2299 {
2300 CRStyle *result = NULL;
2301
2302 g_return_val_if_fail (a_this, NULL);
2303
2304 result = cr_style_new (FALSE);
2305 if (!result) {
2306 cr_utils_trace_info ("Out of memory");
2307 return NULL;
2308 }
2309 cr_style_copy (result, a_this);
2310 return result;
2311 }
2312
2313 /**
2314 *Copies a style data structure into another.
2315 *TODO: this is actually broken because it's based
2316 *on memcpy although some data stuctures of CRStyle should
2317 *be properly duplicated.
2318 *@param a_dest the destination style datastructure
2319 *@param a_src the source style datastructure.
2320 *@return CR_OK upon succesfull completion, an error code otherwise
2321 */
2322 enum CRStatus
cr_style_copy(CRStyle * a_dest,CRStyle * a_src)2323 cr_style_copy (CRStyle * a_dest, CRStyle * a_src)
2324 {
2325 g_return_val_if_fail (a_dest && a_src, CR_BAD_PARAM_ERROR);
2326
2327 memcpy (a_dest, a_src, sizeof (CRStyle));
2328 return CR_OK;
2329 }
2330
2331 /**
2332 *dump a CRNumpPropVal in a string.
2333 *@param a_prop_val the numerical property value to dump
2334 *@param a_str the string to dump the numerical propertie into.
2335 *Note that the string value is appended to a_str.
2336 *@param a_nb_indent the number white chars of indentation.
2337 */
2338 enum CRStatus
cr_style_num_prop_val_to_string(CRNumPropVal * a_prop_val,GString * a_str,guint a_nb_indent)2339 cr_style_num_prop_val_to_string (CRNumPropVal * a_prop_val,
2340 GString * a_str, guint a_nb_indent)
2341 {
2342 enum CRStatus status = CR_OK;
2343 guchar *tmp_str = NULL;
2344 GString *str = NULL;
2345
2346 g_return_val_if_fail (a_prop_val && a_str, CR_BAD_PARAM_ERROR);
2347
2348 str = g_string_new (NULL);
2349 cr_utils_dump_n_chars2 (' ', str, a_nb_indent);
2350 g_string_append (str, "NumPropVal {");
2351 tmp_str = cr_num_to_string (&a_prop_val->sv);
2352 if (!tmp_str) {
2353 status = CR_ERROR;
2354 goto cleanup;
2355 }
2356 g_string_append_printf (str, "sv: %s ", tmp_str);
2357 g_free (tmp_str);
2358 tmp_str = NULL;
2359
2360 tmp_str = cr_num_to_string (&a_prop_val->cv);
2361 if (!tmp_str) {
2362 status = CR_ERROR;
2363 goto cleanup;
2364 }
2365 g_string_append_printf (str, "cv: %s ", tmp_str);
2366 g_free (tmp_str);
2367 tmp_str = NULL;
2368
2369 tmp_str = cr_num_to_string (&a_prop_val->av);
2370 if (!tmp_str) {
2371 status = CR_ERROR;
2372 goto cleanup;
2373 }
2374 g_string_append_printf (str, "av: %s ", tmp_str);
2375 g_free (tmp_str);
2376 tmp_str = NULL;
2377 g_string_append (str, "}");
2378 g_string_append (a_str, str->str);
2379 status = CR_OK;
2380 cleanup:
2381
2382 if (tmp_str) {
2383 g_free (tmp_str);
2384 tmp_str = NULL;
2385 }
2386 if (str) {
2387 g_string_free (str, TRUE);
2388 }
2389 return status;
2390 }
2391
2392 enum CRStatus
cr_style_rgb_prop_val_to_string(CRRgbPropVal * a_prop_val,GString * a_str,guint a_nb_indent)2393 cr_style_rgb_prop_val_to_string (CRRgbPropVal * a_prop_val,
2394 GString * a_str, guint a_nb_indent)
2395 {
2396 enum CRStatus status = CR_OK;
2397 guchar *tmp_str = NULL;
2398 GString *str = NULL;
2399
2400 g_return_val_if_fail (a_prop_val && a_str, CR_BAD_PARAM_ERROR);
2401
2402 str = g_string_new (NULL);
2403
2404 cr_utils_dump_n_chars2 (' ', str, a_nb_indent);
2405 g_string_append (str, "RGBPropVal {");
2406 tmp_str = cr_rgb_to_string (&a_prop_val->sv);
2407 if (!tmp_str) {
2408 status = CR_ERROR;
2409 goto cleanup;
2410 }
2411 g_string_append_printf (str, "sv: %s ", tmp_str);
2412 g_free (tmp_str);
2413 tmp_str = NULL;
2414 tmp_str = cr_rgb_to_string (&a_prop_val->cv);
2415 if (!tmp_str) {
2416 status = CR_ERROR;
2417 goto cleanup;
2418 }
2419 g_string_append_printf (str, "cv: %s ", tmp_str);
2420 g_free (tmp_str);
2421 tmp_str = NULL;
2422 tmp_str = cr_rgb_to_string (&a_prop_val->av);
2423 if (!tmp_str) {
2424 status = CR_ERROR;
2425 goto cleanup;
2426 }
2427 g_string_append_printf (str, "av: %s ", tmp_str);
2428 g_free (tmp_str);
2429 tmp_str = NULL;
2430
2431 g_string_append (str, "}");
2432 g_string_append (a_str, str->str);
2433 status = CR_OK;
2434 cleanup:
2435
2436 if (tmp_str) {
2437 g_free (tmp_str);
2438 tmp_str = NULL;
2439 }
2440 if (str) {
2441 g_string_free (str, TRUE);
2442 }
2443 return status;
2444 }
2445
2446 enum CRStatus
cr_style_border_style_to_string(enum CRBorderStyle a_prop,GString * a_str,guint a_nb_indent)2447 cr_style_border_style_to_string (enum CRBorderStyle a_prop,
2448 GString * a_str, guint a_nb_indent)
2449 {
2450 gchar *str = NULL;
2451
2452 g_return_val_if_fail (a_str, CR_BAD_PARAM_ERROR);
2453
2454 switch (a_prop) {
2455 case BORDER_STYLE_NONE:
2456 str = (gchar *) "border-style-none";
2457 break;
2458 case BORDER_STYLE_HIDDEN:
2459 str = (gchar *) "border-style-hidden";
2460 break;
2461 case BORDER_STYLE_DOTTED:
2462 str = (gchar *) "border-style-dotted";
2463 break;
2464 case BORDER_STYLE_DASHED:
2465 str = (gchar *) "border-style-dashed";
2466 break;
2467 case BORDER_STYLE_SOLID:
2468 str = (gchar *) "border-style-solid";
2469 break;
2470 case BORDER_STYLE_DOUBLE:
2471 str = (gchar *) "border-style-double";
2472 break;
2473 case BORDER_STYLE_GROOVE:
2474 str = (gchar *) "border-style-groove";
2475 break;
2476 case BORDER_STYLE_RIDGE:
2477 str = (gchar *) "border-style-ridge";
2478 break;
2479 case BORDER_STYLE_INSET:
2480 str = (gchar *) "border-style-inset";
2481 break;
2482 case BORDER_STYLE_OUTSET:
2483 str = (gchar *) "border-style-outset";
2484 break;
2485 default:
2486 str = (gchar *) "unknown border style";
2487 break;
2488 }
2489 cr_utils_dump_n_chars2 (' ', a_str, a_nb_indent);
2490 g_string_append (a_str, str);
2491 return CR_OK;
2492 }
2493
2494 enum CRStatus
cr_style_display_type_to_string(enum CRDisplayType a_code,GString * a_str,guint a_nb_indent)2495 cr_style_display_type_to_string (enum CRDisplayType a_code,
2496 GString * a_str, guint a_nb_indent)
2497 {
2498 gchar *str = NULL;
2499
2500 g_return_val_if_fail (a_str, CR_BAD_PARAM_ERROR);
2501
2502 switch (a_code) {
2503 case DISPLAY_NONE:
2504 str = (gchar *) "display-none";
2505 break;
2506 case DISPLAY_INLINE:
2507 str = (gchar *) "display-inline";
2508 break;
2509 case DISPLAY_BLOCK:
2510 str = (gchar *) "display-block";
2511 break;
2512 case DISPLAY_LIST_ITEM:
2513 str = (gchar *) "display-list-item";
2514 break;
2515 case DISPLAY_RUN_IN:
2516 str = (gchar *) "display-run-in";
2517 break;
2518 case DISPLAY_COMPACT:
2519 str = (gchar *) "display-compact";
2520 break;
2521 case DISPLAY_MARKER:
2522 str = (gchar *) "display-marker";
2523 break;
2524 case DISPLAY_TABLE:
2525 str = (gchar *) "display-table";
2526 break;
2527 case DISPLAY_INLINE_TABLE:
2528 str = (gchar *) "display-inline-table";
2529 break;
2530 case DISPLAY_TABLE_ROW_GROUP:
2531 str = (gchar *) "display-table-row-group";
2532 break;
2533 case DISPLAY_TABLE_HEADER_GROUP:
2534 str = (gchar *) "display-table-header-group";
2535 break;
2536 case DISPLAY_TABLE_FOOTER_GROUP:
2537 str = (gchar *) "display-table-footer-group";
2538 break;
2539 case DISPLAY_TABLE_ROW:
2540 str = (gchar *) "display-table-row";
2541 break;
2542 case DISPLAY_TABLE_COLUMN_GROUP:
2543 str = (gchar *) "display-table-column-group";
2544 break;
2545 case DISPLAY_TABLE_COLUMN:
2546 str = (gchar *) "display-table-column";
2547 break;
2548 case DISPLAY_TABLE_CELL:
2549 str = (gchar *) "display-table-cell";
2550 break;
2551 case DISPLAY_TABLE_CAPTION:
2552 str = (gchar *) "display-table-caption";
2553 break;
2554 case DISPLAY_INHERIT:
2555 str = (gchar *) "display-inherit";
2556 break;
2557 default:
2558 str = (gchar *) "unknown display property";
2559 break;
2560 }
2561 cr_utils_dump_n_chars2 (' ', a_str, a_nb_indent);
2562 g_string_append (a_str, str);
2563 return CR_OK;
2564
2565 }
2566
2567 enum CRStatus
cr_style_position_type_to_string(enum CRPositionType a_code,GString * a_str,guint a_nb_indent)2568 cr_style_position_type_to_string (enum CRPositionType a_code,
2569 GString * a_str, guint a_nb_indent)
2570 {
2571 gchar *str = NULL;
2572
2573 g_return_val_if_fail (a_str, CR_BAD_PARAM_ERROR);
2574
2575 switch (a_code) {
2576 case POSITION_STATIC:
2577 str = (gchar *) "position-static";
2578 break;
2579 case POSITION_RELATIVE:
2580 str = (gchar *) "position-relative";
2581 break;
2582 case POSITION_ABSOLUTE:
2583 str = (gchar *) "position-absolute";
2584 break;
2585 case POSITION_FIXED:
2586 str = (gchar *) "position-fixed";
2587 break;
2588 case POSITION_INHERIT:
2589 str = (gchar *) "position-inherit";
2590 break;
2591 default:
2592 str = (gchar *) "unknown static property";
2593 }
2594 cr_utils_dump_n_chars2 (' ', a_str, a_nb_indent);
2595 g_string_append (a_str, str);
2596 return CR_OK;
2597 }
2598
2599 enum CRStatus
cr_style_float_type_to_string(enum CRFloatType a_code,GString * a_str,guint a_nb_indent)2600 cr_style_float_type_to_string (enum CRFloatType a_code,
2601 GString * a_str, guint a_nb_indent)
2602 {
2603 gchar *str = NULL;
2604
2605 g_return_val_if_fail (a_str, CR_BAD_PARAM_ERROR);
2606
2607 switch (a_code) {
2608 case FLOAT_NONE:
2609 str = (gchar *) "float-none";
2610 break;
2611 case FLOAT_LEFT:
2612 str = (gchar *) "float-left";
2613 break;
2614 case FLOAT_RIGHT:
2615 str = (gchar *) "float-right";
2616 break;
2617 case FLOAT_INHERIT:
2618 str = (gchar *) "float-inherit";
2619 break;
2620 default:
2621 str = (gchar *) "unknown float property value";
2622 break;
2623 }
2624 cr_utils_dump_n_chars2 (' ', a_str, a_nb_indent);
2625 g_string_append (a_str, str);
2626 return CR_OK;
2627 }
2628
2629 enum CRStatus
cr_style_white_space_type_to_string(enum CRWhiteSpaceType a_code,GString * a_str,guint a_nb_indent)2630 cr_style_white_space_type_to_string (enum CRWhiteSpaceType a_code,
2631 GString * a_str, guint a_nb_indent)
2632 {
2633 gchar *str = NULL;
2634
2635 g_return_val_if_fail (a_str, CR_BAD_PARAM_ERROR);
2636
2637 switch (a_code) {
2638 case WHITE_SPACE_NORMAL:
2639 str = (gchar *) "normal";
2640 break;
2641 case WHITE_SPACE_PRE:
2642 str = (gchar *) "pre";
2643 break;
2644 case WHITE_SPACE_NOWRAP:
2645 str = (gchar *) "nowrap";
2646 break;
2647 case WHITE_SPACE_INHERIT:
2648 str = (gchar *) "inherited";
2649 break;
2650 default:
2651 str = (gchar *) "unknown white space property value";
2652 break;
2653 }
2654 cr_utils_dump_n_chars2 (' ', a_str, a_nb_indent);
2655 g_string_append (a_str, str);
2656 return CR_OK;
2657 }
2658
2659 /**
2660 *Serializes in instance of #CRStyle into
2661 *a string
2662 *@param a_this the instance of #CRStyle to serialize
2663 *@param a_str the string to serialise the style into.
2664 *if *a_str is NULL, a new GString is instanciated, otherwise
2665 *the style serialisation is appended to the existed *a_str
2666 *@param the number of white space char to use for indentation.
2667 *@return CR_OK upon successful completion, an error code otherwise.
2668 */
2669 enum CRStatus
cr_style_to_string(CRStyle * a_this,GString ** a_str,guint a_nb_indent)2670 cr_style_to_string (CRStyle * a_this, GString ** a_str, guint a_nb_indent)
2671 {
2672 const gint INTERNAL_INDENT = 2;
2673 gint indent = a_nb_indent + INTERNAL_INDENT;
2674 gchar *tmp_str = NULL;
2675 GString *str = NULL;
2676 gint i = 0;
2677
2678 g_return_val_if_fail (a_this && a_str, CR_BAD_PARAM_ERROR);
2679
2680 if (!*a_str) {
2681 str = g_string_new (NULL);
2682 } else {
2683 str = *a_str;
2684 }
2685 cr_utils_dump_n_chars2 (' ', str, a_nb_indent);
2686 g_string_append (str, "style {\n");
2687
2688 /*loop over the num_props and to_string() them */
2689 for (i = NUM_PROP_TOP; i < NB_NUM_PROPS; i++) {
2690 /*
2691 *to_string() the name of the num_prop
2692 *(using num_prop_code_to_string)
2693 *before outputing it value
2694 */
2695 cr_utils_dump_n_chars2 (' ', str, indent);
2696 tmp_str = (gchar *) num_prop_code_to_string (i);
2697 if (tmp_str) {
2698 g_string_append_printf (str, "%s: ", tmp_str);
2699 } else {
2700 g_string_append (str, "NULL");
2701 }
2702 tmp_str = NULL;
2703 cr_style_num_prop_val_to_string (&a_this->num_props[i], str,
2704 a_nb_indent +
2705 INTERNAL_INDENT);
2706 g_string_append (str, "\n");
2707 }
2708 /*loop over the rgb_props and to_string() them all */
2709 for (i = RGB_PROP_BORDER_TOP_COLOR; i < NB_RGB_PROPS; i++) {
2710 tmp_str = (gchar *) rgb_prop_code_to_string (i);
2711 cr_utils_dump_n_chars2 (' ', str, indent);
2712 if (tmp_str) {
2713 g_string_append_printf (str, "%s: ", tmp_str);
2714 } else {
2715 g_string_append (str, "NULL: ");
2716 }
2717 tmp_str = NULL;
2718 cr_style_rgb_prop_val_to_string (&a_this->rgb_props[i], str,
2719 a_nb_indent +
2720 INTERNAL_INDENT);
2721 g_string_append (str, "\n");
2722 }
2723 /*loop over the border_style_props and to_string() them */
2724 for (i = BORDER_STYLE_PROP_TOP; i < NB_BORDER_STYLE_PROPS; i++) {
2725 tmp_str = (gchar *) border_style_prop_code_to_string (i);
2726 cr_utils_dump_n_chars2 (' ', str, indent);
2727 if (tmp_str) {
2728 g_string_append_printf (str, "%s: ", tmp_str);
2729 } else {
2730 g_string_append (str, "NULL: ");
2731 }
2732 tmp_str = NULL;
2733 cr_style_border_style_to_string (a_this->
2734 border_style_props[i], str,
2735 0);
2736 g_string_append (str, "\n");
2737 }
2738 cr_utils_dump_n_chars2 (' ', str, indent);
2739 g_string_append (str, "display: ");
2740 cr_style_display_type_to_string (a_this->display, str, 0);
2741 g_string_append (str, "\n");
2742
2743 cr_utils_dump_n_chars2 (' ', str, indent);
2744 g_string_append (str, "position: ");
2745 cr_style_position_type_to_string (a_this->position, str, 0);
2746 g_string_append (str, "\n");
2747
2748 cr_utils_dump_n_chars2 (' ', str, indent);
2749 g_string_append (str, "float-type: ");
2750 cr_style_float_type_to_string (a_this->float_type, str, 0);
2751 g_string_append (str, "\n");
2752
2753 cr_utils_dump_n_chars2 (' ', str, indent);
2754 g_string_append (str, "white-space: ");
2755 cr_style_white_space_type_to_string (a_this->white_space, str, 0);
2756 g_string_append (str, "\n");
2757
2758 cr_utils_dump_n_chars2 (' ', str, indent);
2759 g_string_append (str, "font-family: ");
2760 tmp_str = (gchar *) cr_font_family_to_string (a_this->font_family, TRUE);
2761 if (tmp_str) {
2762 g_string_append (str, tmp_str);
2763 g_free (tmp_str);
2764 tmp_str = NULL;
2765 } else {
2766 g_string_append (str, "NULL");
2767 }
2768 g_string_append (str, "\n");
2769
2770 cr_utils_dump_n_chars2 (' ', str, indent);
2771 tmp_str = cr_font_size_to_string (&a_this->font_size.sv);
2772 if (tmp_str) {
2773 g_string_append_printf (str, "font-size {sv:%s, ",
2774 tmp_str) ;
2775 } else {
2776 g_string_append (str, "font-size {sv:NULL, ");
2777 }
2778 tmp_str = cr_font_size_to_string (&a_this->font_size.cv);
2779 if (tmp_str) {
2780 g_string_append_printf (str, "cv:%s, ", tmp_str);
2781 } else {
2782 g_string_append (str, "cv:NULL, ");
2783 }
2784 tmp_str = cr_font_size_to_string (&a_this->font_size.av);
2785 if (tmp_str) {
2786 g_string_append_printf (str, "av:%s}", tmp_str);
2787 } else {
2788 g_string_append (str, "av:NULL}");
2789 }
2790
2791 tmp_str = NULL;
2792 g_string_append (str, "\n");
2793
2794 cr_utils_dump_n_chars2 (' ', str, indent);
2795 tmp_str = cr_font_size_adjust_to_string (a_this->font_size_adjust);
2796 if (tmp_str) {
2797 g_string_append_printf (str, "font-size-adjust: %s", tmp_str);
2798 } else {
2799 g_string_append (str, "font-size-adjust: NULL");
2800 }
2801 tmp_str = NULL;
2802 g_string_append (str, "\n");
2803
2804 cr_utils_dump_n_chars2 (' ', str, indent);
2805 tmp_str = (gchar *) cr_font_style_to_string (a_this->font_style);
2806 if (tmp_str) {
2807 g_string_append_printf (str, "font-style: %s", tmp_str);
2808 } else {
2809 g_string_append (str, "font-style: NULL");
2810 }
2811 tmp_str = NULL;
2812 g_string_append (str, "\n");
2813
2814 cr_utils_dump_n_chars2 (' ', str, indent);
2815 tmp_str = (gchar *) cr_font_variant_to_string (a_this->font_variant);
2816 if (tmp_str) {
2817 g_string_append_printf (str, "font-variant: %s", tmp_str);
2818 } else {
2819 g_string_append (str, "font-variant: NULL");
2820 }
2821 tmp_str = NULL;
2822 g_string_append (str, "\n");
2823
2824 cr_utils_dump_n_chars2 (' ', str, indent);
2825 tmp_str = (gchar *) cr_font_weight_to_string (a_this->font_weight);
2826 if (tmp_str) {
2827 g_string_append_printf (str, "font-weight: %s", tmp_str);
2828 } else {
2829 g_string_append (str, "font-weight: NULL");
2830 }
2831 tmp_str = NULL;
2832 g_string_append (str, "\n");
2833
2834 cr_utils_dump_n_chars2 (' ', str, indent);
2835 tmp_str = (gchar *) cr_font_stretch_to_string (a_this->font_stretch);
2836 if (tmp_str) {
2837 g_string_append_printf (str, "font-stretch: %s", tmp_str);
2838 } else {
2839 g_string_append (str, "font-stretch: NULL");
2840 }
2841 tmp_str = NULL;
2842 g_string_append (str, "\n");
2843
2844
2845 cr_utils_dump_n_chars2 (' ', str, a_nb_indent);
2846 g_string_append (str, "}");
2847
2848 return CR_OK;
2849 }
2850
2851 /**
2852 *Destructor of the #CRStyle class.
2853 *@param a_this the instance to destroy.
2854 */
2855 void
cr_style_destroy(CRStyle * a_this)2856 cr_style_destroy (CRStyle * a_this)
2857 {
2858 g_return_if_fail (a_this);
2859
2860 g_free (a_this);
2861 }
2862
2863