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