Code

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