1 /* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
3 /*
4 * This file is part of The Croco Library
5 *
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of version 2.1 of
9 * the GNU Lesser General Public
10 * License as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the
18 * GNU Lesser General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
21 * USA
22 *
23 *See COPYRIGHTS file for copyright information
24 */
26 #include "cr-fonts.h"
27 #include <string.h>
29 static enum CRStatus
30 cr_font_family_to_string_real (CRFontFamily * a_this,
31 gboolean a_walk_list, GString ** a_string)
32 {
33 guchar *name = NULL;
34 enum CRStatus result = CR_OK;
36 if (!*a_string) {
37 *a_string = g_string_new (NULL);
38 g_return_val_if_fail (*a_string,
39 CR_INSTANCIATION_FAILED_ERROR);
40 }
42 if (!a_this) {
43 g_string_append (*a_string, "NULL");
44 return CR_OK;
45 }
47 switch (a_this->type) {
48 case FONT_FAMILY_SANS_SERIF:
49 name = (guchar *) "sans-serif";
50 break;
52 case FONT_FAMILY_SERIF:
53 name = (guchar *) "sans-serif";
54 break;
56 case FONT_FAMILY_CURSIVE:
57 name = (guchar *) "cursive";
58 break;
60 case FONT_FAMILY_FANTASY:
61 name = (guchar *) "fantasy";
62 break;
64 case FONT_FAMILY_MONOSPACE:
65 name = (guchar *) "monospace";
66 break;
68 case FONT_FAMILY_NON_GENERIC:
69 name = (guchar *) a_this->name;
70 break;
72 default:
73 name = (guchar *) NULL;
74 break;
75 }
77 if (name) {
78 if (a_this->prev) {
79 g_string_append_printf (*a_string, ", %s", name);
80 } else {
81 g_string_append (*a_string, name);
82 }
83 }
84 if (a_walk_list == TRUE && a_this->next) {
85 result = cr_font_family_to_string_real (a_this->next,
86 TRUE, a_string);
87 }
88 return result;
89 }
91 static const gchar *
92 cr_predefined_absolute_font_size_to_string (enum CRPredefinedAbsoluteFontSize
93 a_code)
94 {
95 gchar *str = NULL;
97 switch (a_code) {
98 case FONT_SIZE_XX_SMALL:
99 str = (gchar *) "xx-small";
100 break;
101 case FONT_SIZE_X_SMALL:
102 str = (gchar *) "x-small";
103 break;
104 case FONT_SIZE_SMALL:
105 str = (gchar *) "small";
106 break;
107 case FONT_SIZE_MEDIUM:
108 str = (gchar *) "medium";
109 break;
110 case FONT_SIZE_LARGE:
111 str = (gchar *) "large";
112 break;
113 case FONT_SIZE_X_LARGE:
114 str = (gchar *) "x-large";
115 break;
116 case FONT_SIZE_XX_LARGE:
117 str = (gchar *) "xx-large";
118 break;
119 default:
120 str = (gchar *) "unknown absolute font size value";
121 }
122 return str;
123 }
125 static const gchar *
126 cr_relative_font_size_to_string (enum CRRelativeFontSize a_code)
127 {
128 gchar *str = NULL;
130 switch (a_code) {
131 case FONT_SIZE_LARGER:
132 str = (gchar *) "larger";
133 break;
134 case FONT_SIZE_SMALLER:
135 str = (gchar *) "smaller";
136 break;
137 default:
138 str = (gchar *) "unknown relative font size value";
139 break;
140 }
141 return str;
142 }
144 CRFontFamily *
145 cr_font_family_new (enum CRFontFamilyType a_type, guchar * a_name)
146 {
147 CRFontFamily *result = NULL;
149 result = g_try_malloc (sizeof (CRFontFamily));
151 if (!result) {
152 cr_utils_trace_info ("Out of memory");
153 return NULL;
154 }
156 memset (result, 0, sizeof (CRFontFamily));
157 result->type = a_type;
159 cr_font_family_set_name (result, a_name);
161 return result;
162 }
164 guchar *
165 cr_font_family_to_string (CRFontFamily * a_this,
166 gboolean a_walk_font_family_list)
167 {
168 enum CRStatus status = CR_OK;
169 guchar *result = NULL;
170 GString *stringue = NULL;
172 if (!a_this) {
173 result = g_strdup ("NULL");
174 g_return_val_if_fail (result, NULL);
175 return result;
176 }
177 status = cr_font_family_to_string_real (a_this,
178 a_walk_font_family_list,
179 &stringue);
181 if (status == CR_OK && stringue) {
182 result = stringue->str;
183 g_string_free (stringue, FALSE);
184 stringue = NULL;
186 } else {
187 if (stringue) {
188 g_string_free (stringue, TRUE);
189 stringue = NULL;
190 }
191 }
193 return result;
194 }
195 enum CRStatus
196 cr_font_family_set_name (CRFontFamily * a_this, guchar * a_name)
197 {
198 g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
200 /*
201 *only non generic font families can have a name
202 */
204 if (a_this->type != FONT_FAMILY_NON_GENERIC) {
205 return CR_BAD_PARAM_ERROR;
206 }
208 if (a_this->name) {
209 g_free (a_this->name);
210 a_this->name = NULL;
211 }
213 a_this->name = a_name;
214 return CR_OK;
215 }
217 CRFontFamily *
218 cr_font_family_append (CRFontFamily * a_this,
219 CRFontFamily * a_family_to_append)
220 {
221 CRFontFamily *cur_ff = NULL;
223 g_return_val_if_fail (a_family_to_append, NULL);
225 if (!a_this)
226 return a_family_to_append;
228 for (cur_ff = a_this; cur_ff && cur_ff->next; cur_ff = cur_ff->next) ;
230 cur_ff->next = a_family_to_append;
231 a_family_to_append->prev = cur_ff;
233 return a_this;
235 }
237 CRFontFamily *
238 cr_font_family_prepend (CRFontFamily * a_this,
239 CRFontFamily * a_family_to_prepend)
240 {
241 g_return_val_if_fail (a_this && a_family_to_prepend, NULL);
243 if (!a_this)
244 return a_family_to_prepend;
246 a_family_to_prepend->next = a_this;
247 a_this->prev = a_family_to_prepend;
249 return CR_OK;
250 }
252 enum CRStatus
253 cr_font_family_destroy (CRFontFamily * a_this)
254 {
255 CRFontFamily *cur_ff = NULL;
257 g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
259 for (cur_ff = a_this; cur_ff && cur_ff->next; cur_ff = cur_ff->next) ;
261 for (; cur_ff; cur_ff = cur_ff->prev) {
262 if (a_this->name) {
263 g_free (a_this->name);
264 a_this->name = NULL;
265 }
267 if (cur_ff->next) {
268 g_free (cur_ff->next);
270 }
272 if (cur_ff->prev == NULL) {
273 g_free (a_this);
274 }
275 }
277 return CR_OK;
278 }
280 /***************************************************
281 *'font-size' manipulation functions definitions
282 ***************************************************/
284 CRFontSize *
285 cr_font_size_new (void)
286 {
287 CRFontSize *result = NULL;
289 result = g_try_malloc (sizeof (CRFontSize));
290 if (!result) {
291 cr_utils_trace_info ("Out of memory");
292 return NULL;
293 }
294 memset (result, 0, sizeof (CRFontSize));
296 return result;
297 }
299 enum CRStatus
300 cr_font_size_clear (CRFontSize * a_this)
301 {
302 g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
304 switch (a_this->type) {
305 case PREDEFINED_ABSOLUTE_FONT_SIZE:
306 case RELATIVE_FONT_SIZE:
307 case INHERITED_FONT_SIZE:
308 memset (a_this, 0, sizeof (CRFontSize));
309 break;
311 case ABSOLUTE_FONT_SIZE:
312 memset (a_this, 0, sizeof (CRFontSize));
313 break;
315 default:
316 return CR_UNKNOWN_TYPE_ERROR;
317 }
319 return CR_OK;
320 }
322 enum CRStatus
323 cr_font_size_copy (CRFontSize * a_dst, CRFontSize * a_src)
324 {
325 g_return_val_if_fail (a_dst && a_src, CR_BAD_PARAM_ERROR);
327 switch (a_src->type) {
328 case PREDEFINED_ABSOLUTE_FONT_SIZE:
329 case RELATIVE_FONT_SIZE:
330 case INHERITED_FONT_SIZE:
331 cr_font_size_clear (a_dst);
332 memcpy (a_dst, a_src, sizeof (CRFontSize));
333 break;
335 case ABSOLUTE_FONT_SIZE:
336 cr_font_size_clear (a_dst);
337 cr_num_copy (&a_dst->value.absolute,
338 &a_src->value.absolute);
339 a_dst->type = a_src->type;
340 break;
342 default:
343 return CR_UNKNOWN_TYPE_ERROR;
344 }
345 return CR_OK;
346 }
348 enum CRStatus
349 cr_font_size_set_predefined_absolute_font_size (CRFontSize *a_this,
350 enum CRPredefinedAbsoluteFontSize a_predefined)
351 {
352 g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR) ;
353 g_return_val_if_fail ((unsigned)a_predefined < NB_FONT_SIZE_TYPE,
354 CR_BAD_PARAM_ERROR) ;
356 a_this->type = PREDEFINED_ABSOLUTE_FONT_SIZE ;
357 a_this->value.predefined = a_predefined ;
359 return CR_OK ;
360 }
362 enum CRStatus
363 cr_font_size_set_relative_font_size (CRFontSize *a_this,
364 enum CRRelativeFontSize a_relative)
365 {
366 g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR) ;
367 g_return_val_if_fail ((unsigned)a_relative < NB_RELATIVE_FONT_SIZE,
368 CR_BAD_PARAM_ERROR) ;
370 a_this->type = RELATIVE_FONT_SIZE ;
371 a_this->value.relative = a_relative ;
372 return CR_OK ;
373 }
375 enum CRStatus
376 cr_font_size_set_absolute_font_size (CRFontSize *a_this,
377 enum CRNumType a_num_type,
378 gdouble a_value)
379 {
380 g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR) ;
381 g_return_val_if_fail ((unsigned)a_num_type < NB_NUM_TYPE,
382 CR_BAD_PARAM_ERROR) ;
384 a_this->type = ABSOLUTE_FONT_SIZE ;
385 cr_num_set (&a_this->value.absolute,
386 a_value, a_num_type) ;
387 return CR_OK ;
388 }
390 enum CRStatus
391 cr_font_size_set_to_inherit (CRFontSize *a_this)
392 {
393 g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR) ;
395 cr_font_size_clear (a_this) ;
396 a_this->type = INHERITED_FONT_SIZE ;
398 return CR_OK ;
399 }
401 gboolean
402 cr_font_size_is_set_to_inherit (CRFontSize *a_this)
403 {
404 g_return_val_if_fail (a_this, FALSE) ;
406 return a_this->type == INHERITED_FONT_SIZE ;
407 }
409 gchar *
410 cr_font_size_to_string (CRFontSize * a_this)
411 {
412 gchar *str = NULL;
414 if (!a_this) {
415 str = g_strdup ("NULL");
416 g_return_val_if_fail (str, NULL);
417 return str;
418 }
419 switch (a_this->type) {
420 case PREDEFINED_ABSOLUTE_FONT_SIZE:
421 str = g_strdup (cr_predefined_absolute_font_size_to_string
422 (a_this->value.predefined));
423 break;
424 case ABSOLUTE_FONT_SIZE:
425 str = cr_num_to_string (&a_this->value.absolute);
426 break;
427 case RELATIVE_FONT_SIZE:
428 str = g_strdup (cr_relative_font_size_to_string
429 (a_this->value.relative));
430 break;
431 case INHERITED_FONT_SIZE:
432 str = g_strdup ("inherit");
433 break;
434 default:
435 break;
436 }
437 return str;
438 }
440 void
441 cr_font_size_get_smaller_predefined_font_size (enum CRPredefinedAbsoluteFontSize a_font_size,
442 enum CRPredefinedAbsoluteFontSize *a_smaller_size)
443 {
444 enum CRPredefinedAbsoluteFontSize result = FONT_SIZE_MEDIUM ;
446 g_return_if_fail (a_smaller_size) ;
447 g_return_if_fail ((unsigned)a_font_size < NB_PREDEFINED_ABSOLUTE_FONT_SIZES) ;
449 switch (a_font_size) {
450 case FONT_SIZE_XX_SMALL:
451 result = FONT_SIZE_XX_SMALL ;
452 break ;
453 case FONT_SIZE_X_SMALL:
454 result = FONT_SIZE_XX_SMALL ;
455 break ;
456 case FONT_SIZE_SMALL:
457 result = FONT_SIZE_X_SMALL;
458 break ;
459 case FONT_SIZE_MEDIUM:
460 result = FONT_SIZE_SMALL;
461 break ;
462 case FONT_SIZE_LARGE:
463 result = FONT_SIZE_MEDIUM;
464 break ;
465 case FONT_SIZE_X_LARGE:
466 result = FONT_SIZE_LARGE;
467 break ;
468 case FONT_SIZE_XX_LARGE:
469 result = FONT_SIZE_XX_LARGE;
470 break ;
471 case FONT_SIZE_INHERIT:
472 cr_utils_trace_info ("can't return a smaller size for FONT_SIZE_INHERIT") ;
473 result = FONT_SIZE_MEDIUM ;
474 break ;
475 default:
476 cr_utils_trace_info ("Unknown FONT_SIZE") ;
477 result = FONT_SIZE_MEDIUM ;
478 break ;
479 }
480 *a_smaller_size = result ;
481 }
484 void
485 cr_font_size_get_larger_predefined_font_size (enum CRPredefinedAbsoluteFontSize a_font_size,
486 enum CRPredefinedAbsoluteFontSize *a_larger_size)
487 {
488 enum CRPredefinedAbsoluteFontSize result = FONT_SIZE_MEDIUM ;
490 g_return_if_fail (a_larger_size) ;
491 g_return_if_fail ((unsigned)a_font_size < NB_PREDEFINED_ABSOLUTE_FONT_SIZES) ;
493 switch (a_font_size) {
494 case FONT_SIZE_XX_SMALL:
495 result = FONT_SIZE_X_SMALL ;
496 break ;
497 case FONT_SIZE_X_SMALL:
498 result = FONT_SIZE_SMALL ;
499 break ;
500 case FONT_SIZE_SMALL:
501 result = FONT_SIZE_MEDIUM;
502 break ;
503 case FONT_SIZE_MEDIUM:
504 result = FONT_SIZE_LARGE;
505 break ;
506 case FONT_SIZE_LARGE:
507 result = FONT_SIZE_X_LARGE;
508 break ;
509 case FONT_SIZE_X_LARGE:
510 result = FONT_SIZE_XX_LARGE ;
511 break ;
512 case FONT_SIZE_XX_LARGE:
513 result = FONT_SIZE_XX_LARGE;
514 break ;
515 case FONT_SIZE_INHERIT:
516 cr_utils_trace_info ("can't return a bigger size for FONT_SIZE_INHERIT") ;
517 result = FONT_SIZE_MEDIUM ;
518 break ;
519 default:
520 cr_utils_trace_info ("Unknown FONT_SIZE") ;
521 result = FONT_SIZE_MEDIUM ;
522 break ;
523 }
524 *a_larger_size = result ;
525 }
527 gboolean
528 cr_font_size_is_predefined_absolute_font_size (enum CRPredefinedAbsoluteFontSize a_font_size)
529 {
530 if ((unsigned)a_font_size < NB_PREDEFINED_ABSOLUTE_FONT_SIZES) {
531 return TRUE ;
532 } else {
533 return FALSE ;
534 }
535 }
537 gchar *
538 cr_font_size_adjust_to_string (CRFontSizeAdjust * a_this)
539 {
540 gchar *str = NULL;
542 if (!a_this) {
543 str = g_strdup ("NULL");
544 g_return_val_if_fail (str, NULL);
545 return str;
546 }
548 switch (a_this->type) {
549 case FONT_SIZE_ADJUST_NONE:
550 str = g_strdup ("none");
551 break;
552 case FONT_SIZE_ADJUST_NUMBER:
553 if (a_this->num)
554 str = cr_num_to_string (a_this->num);
555 else
556 str = g_strdup ("unknow font-size-adjust property value"); // Should raise an error no?
557 break;
558 case FONT_SIZE_ADJUST_INHERIT:
559 str = g_strdup ("inherit");
560 }
561 return str;
562 }
564 const gchar *
565 cr_font_style_to_string (enum CRFontStyle a_code)
566 {
567 gchar *str = NULL;
569 switch (a_code) {
570 case FONT_STYLE_NORMAL:
571 str = (gchar *) "normal";
572 break;
573 case FONT_STYLE_ITALIC:
574 str = (gchar *) "italic";
575 break;
576 case FONT_STYLE_OBLIQUE:
577 str = (gchar *) "oblique";
578 break;
579 case FONT_STYLE_INHERIT:
580 str = (gchar *) "inherit";
581 break;
582 default:
583 str = (gchar *) "unknown font style value";
584 break;
585 }
586 return str;
587 }
589 const gchar *
590 cr_font_variant_to_string (enum CRFontVariant a_code)
591 {
592 gchar *str = NULL;
594 switch (a_code) {
595 case FONT_VARIANT_NORMAL:
596 str = (gchar *) "normal";
597 break;
598 case FONT_VARIANT_SMALL_CAPS:
599 str = (gchar *) "small-caps";
600 break;
601 case FONT_VARIANT_INHERIT:
602 str = (gchar *) "inherit";
603 break;
604 }
605 return str;
606 }
608 enum CRFontWeight
609 cr_font_weight_get_bolder (enum CRFontWeight a_weight)
610 {
611 if (a_weight >= NB_FONT_WEIGHTS) {
612 return FONT_WEIGHT_900 ;
613 } else if (a_weight < FONT_WEIGHT_NORMAL) {
614 return FONT_WEIGHT_NORMAL ;
615 } else if (a_weight == FONT_WEIGHT_BOLDER
616 || a_weight == FONT_WEIGHT_BOLDER) {
617 cr_utils_trace_info ("FONT_WEIGHT_BOLDER or FONT_WEIGHT_LIGHTER should not appear here") ;
618 return FONT_WEIGHT_NORMAL ;
619 } else {
620 return a_weight << 1 ;
621 }
622 }
624 const gchar *
625 cr_font_weight_to_string (enum CRFontWeight a_code)
626 {
627 gchar *str = NULL;
629 switch (a_code) {
630 case FONT_WEIGHT_NORMAL:
631 str = (gchar *) "normal";
632 break;
633 case FONT_WEIGHT_BOLD:
634 str = (gchar *) "bold";
635 break;
636 case FONT_WEIGHT_BOLDER:
637 str = (gchar *) "bolder";
638 break;
639 case FONT_WEIGHT_LIGHTER:
640 str = (gchar *) "lighter";
641 break;
642 case FONT_WEIGHT_100:
643 str = (gchar *) "100";
644 break;
645 case FONT_WEIGHT_200:
646 str = (gchar *) "200";
647 break;
648 case FONT_WEIGHT_300:
649 str = (gchar *) "300";
650 break;
651 case FONT_WEIGHT_400:
652 str = (gchar *) "400";
653 break;
654 case FONT_WEIGHT_500:
655 str = (gchar *) "500";
656 break;
657 case FONT_WEIGHT_600:
658 str = (gchar *) "600";
659 break;
660 case FONT_WEIGHT_700:
661 str = (gchar *) "700";
662 break;
663 case FONT_WEIGHT_800:
664 str = (gchar *) "800";
665 break;
666 case FONT_WEIGHT_900:
667 str = (gchar *) "900";
668 break;
669 case FONT_WEIGHT_INHERIT:
670 str = (gchar *) "inherit";
671 break;
672 default:
673 str = (gchar *) "unknown font-weight property value";
674 break;
675 }
676 return str;
677 }
679 const gchar *
680 cr_font_stretch_to_string (enum CRFontStretch a_code)
681 {
682 gchar *str = NULL;
684 switch (a_code) {
685 case FONT_STRETCH_NORMAL:
686 str = (gchar *) "normal";
687 break;
688 case FONT_STRETCH_WIDER:
689 str = (gchar *) "wider";
690 break;
691 case FONT_STRETCH_NARROWER:
692 str = (gchar *) "narrower";
693 break;
694 case FONT_STRETCH_ULTRA_CONDENSED:
695 str = (gchar *) "ultra-condensed";
696 break;
697 case FONT_STRETCH_EXTRA_CONDENSED:
698 str = (gchar *) "extra-condensed";
699 break;
700 case FONT_STRETCH_CONDENSED:
701 str = (gchar *) "condensed";
702 break;
703 case FONT_STRETCH_SEMI_CONDENSED:
704 str = (gchar *) "semi-condensed";
705 break;
706 case FONT_STRETCH_SEMI_EXPANDED:
707 str = (gchar *) "semi-expanded";
708 break;
709 case FONT_STRETCH_EXPANDED:
710 str = (gchar *) "expanded";
711 break;
712 case FONT_STRETCH_EXTRA_EXPANDED:
713 str = (gchar *) "extra-expaned";
714 break;
715 case FONT_STRETCH_ULTRA_EXPANDED:
716 str = (gchar *) "ultra-expanded";
717 break;
718 case FONT_STRETCH_INHERIT:
719 str = (gchar *) "inherit";
720 break;
721 }
722 return str;
723 }
725 void
726 cr_font_size_destroy (CRFontSize * a_font_size)
727 {
728 g_return_if_fail (a_font_size);
730 g_free (a_font_size) ;
731 }
733 /*******************************************************
734 *'font-size-adjust' manipulation function definition
735 *******************************************************/
737 CRFontSizeAdjust *
738 cr_font_size_adjust_new (void)
739 {
740 CRFontSizeAdjust *result = NULL;
742 result = g_try_malloc (sizeof (CRFontSizeAdjust));
743 if (!result) {
744 cr_utils_trace_info ("Out of memory");
745 return NULL;
746 }
747 memset (result, 0, sizeof (CRFontSizeAdjust));
749 return result;
750 }
752 void
753 cr_font_size_adjust_destroy (CRFontSizeAdjust * a_this)
754 {
755 g_return_if_fail (a_this);
757 if (a_this->type == FONT_SIZE_ADJUST_NUMBER && a_this->num) {
758 cr_num_destroy (a_this->num);
759 a_this->num = NULL;
760 }
761 }