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 gchar *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 = (gchar *) "sans-serif";
50 break;
52 case FONT_FAMILY_SERIF:
53 name = (gchar *) "sans-serif";
54 break;
56 case FONT_FAMILY_CURSIVE:
57 name = (gchar *) "cursive";
58 break;
60 case FONT_FAMILY_FANTASY:
61 name = (gchar *) "fantasy";
62 break;
64 case FONT_FAMILY_MONOSPACE:
65 name = (gchar *) "monospace";
66 break;
68 case FONT_FAMILY_NON_GENERIC:
69 name = (gchar *) a_this->name;
70 break;
72 default:
73 name = (gchar *) 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 = (CRFontFamily *)g_try_malloc (sizeof (CRFontFamily));
149 if (!result) {
150 cr_utils_trace_info ("Out of memory");
151 return NULL;
152 }
154 memset (result, 0, sizeof (CRFontFamily));
155 result->type = a_type;
157 cr_font_family_set_name (result, a_name);
159 return result;
160 }
162 guchar *
163 cr_font_family_to_string (CRFontFamily * a_this,
164 gboolean a_walk_font_family_list)
165 {
166 enum CRStatus status = CR_OK;
167 gchar *result = NULL;
168 GString *stringue = NULL;
170 if (!a_this) {
171 result = g_strdup ("NULL");
172 g_return_val_if_fail (result, NULL);
173 return (guchar *)result;
174 }
175 status = cr_font_family_to_string_real (a_this,
176 a_walk_font_family_list,
177 &stringue);
179 if (status == CR_OK && stringue) {
180 result = stringue->str;
181 g_string_free (stringue, FALSE);
182 stringue = NULL;
184 } else {
185 if (stringue) {
186 g_string_free (stringue, TRUE);
187 stringue = NULL;
188 }
189 }
191 return (guchar *)result;
192 }
193 enum CRStatus
194 cr_font_family_set_name (CRFontFamily * a_this, guchar * a_name)
195 {
196 g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
198 /*
199 *only non generic font families can have a name
200 */
202 if (a_this->type != FONT_FAMILY_NON_GENERIC) {
203 return CR_BAD_PARAM_ERROR;
204 }
206 if (a_this->name) {
207 g_free (a_this->name);
208 a_this->name = NULL;
209 }
211 a_this->name = a_name;
212 return CR_OK;
213 }
215 CRFontFamily *
216 cr_font_family_append (CRFontFamily * a_this,
217 CRFontFamily * a_family_to_append)
218 {
219 CRFontFamily *cur_ff = NULL;
221 g_return_val_if_fail (a_family_to_append, NULL);
223 if (!a_this)
224 return a_family_to_append;
226 for (cur_ff = a_this; cur_ff && cur_ff->next; cur_ff = cur_ff->next) ;
228 cur_ff->next = a_family_to_append;
229 a_family_to_append->prev = cur_ff;
231 return a_this;
233 }
235 CRFontFamily *
236 cr_font_family_prepend (CRFontFamily * a_this,
237 CRFontFamily * a_family_to_prepend)
238 {
239 g_return_val_if_fail (a_this && a_family_to_prepend, NULL);
241 if (!a_this)
242 return a_family_to_prepend;
244 a_family_to_prepend->next = a_this;
245 a_this->prev = a_family_to_prepend;
247 return a_family_to_prepend;
248 }
250 enum CRStatus
251 cr_font_family_destroy (CRFontFamily * a_this)
252 {
253 CRFontFamily *cur_ff = NULL;
255 g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
257 for (cur_ff = a_this; cur_ff && cur_ff->next; cur_ff = cur_ff->next) ;
259 for (; cur_ff; cur_ff = cur_ff->prev) {
260 if (a_this->name) {
261 g_free (a_this->name);
262 a_this->name = NULL;
263 }
265 if (cur_ff->next) {
266 g_free (cur_ff->next);
268 }
270 if (cur_ff->prev == NULL) {
271 g_free (a_this);
272 }
273 }
275 return CR_OK;
276 }
278 /***************************************************
279 *'font-size' manipulation functions definitions
280 ***************************************************/
282 CRFontSize *
283 cr_font_size_new (void)
284 {
285 CRFontSize *result = (CRFontSize *)g_try_malloc (sizeof (CRFontSize));
286 if (!result) {
287 cr_utils_trace_info ("Out of memory");
288 return NULL;
289 }
290 memset (result, 0, sizeof (CRFontSize));
292 return result;
293 }
295 enum CRStatus
296 cr_font_size_clear (CRFontSize * a_this)
297 {
298 g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
300 switch (a_this->type) {
301 case PREDEFINED_ABSOLUTE_FONT_SIZE:
302 case RELATIVE_FONT_SIZE:
303 case INHERITED_FONT_SIZE:
304 memset (a_this, 0, sizeof (CRFontSize));
305 break;
307 case ABSOLUTE_FONT_SIZE:
308 memset (a_this, 0, sizeof (CRFontSize));
309 break;
311 default:
312 return CR_UNKNOWN_TYPE_ERROR;
313 }
315 return CR_OK;
316 }
318 enum CRStatus
319 cr_font_size_copy (CRFontSize * a_dst, CRFontSize * a_src)
320 {
321 g_return_val_if_fail (a_dst && a_src, CR_BAD_PARAM_ERROR);
323 switch (a_src->type) {
324 case PREDEFINED_ABSOLUTE_FONT_SIZE:
325 case RELATIVE_FONT_SIZE:
326 case INHERITED_FONT_SIZE:
327 cr_font_size_clear (a_dst);
328 memcpy (a_dst, a_src, sizeof (CRFontSize));
329 break;
331 case ABSOLUTE_FONT_SIZE:
332 cr_font_size_clear (a_dst);
333 cr_num_copy (&a_dst->value.absolute,
334 &a_src->value.absolute);
335 a_dst->type = a_src->type;
336 break;
338 default:
339 return CR_UNKNOWN_TYPE_ERROR;
340 }
341 return CR_OK;
342 }
344 enum CRStatus
345 cr_font_size_set_predefined_absolute_font_size (CRFontSize *a_this,
346 enum CRPredefinedAbsoluteFontSize a_predefined)
347 {
348 g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR) ;
349 g_return_val_if_fail ((unsigned)a_predefined < NB_FONT_SIZE_TYPE,
350 CR_BAD_PARAM_ERROR) ;
352 a_this->type = PREDEFINED_ABSOLUTE_FONT_SIZE ;
353 a_this->value.predefined = a_predefined ;
355 return CR_OK ;
356 }
358 enum CRStatus
359 cr_font_size_set_relative_font_size (CRFontSize *a_this,
360 enum CRRelativeFontSize a_relative)
361 {
362 g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR) ;
363 g_return_val_if_fail ((unsigned)a_relative < NB_RELATIVE_FONT_SIZE,
364 CR_BAD_PARAM_ERROR) ;
366 a_this->type = RELATIVE_FONT_SIZE ;
367 a_this->value.relative = a_relative ;
368 return CR_OK ;
369 }
371 enum CRStatus
372 cr_font_size_set_absolute_font_size (CRFontSize *a_this,
373 enum CRNumType a_num_type,
374 gdouble a_value)
375 {
376 g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR) ;
377 g_return_val_if_fail ((unsigned)a_num_type < NB_NUM_TYPE,
378 CR_BAD_PARAM_ERROR) ;
380 a_this->type = ABSOLUTE_FONT_SIZE ;
381 cr_num_set (&a_this->value.absolute,
382 a_value, a_num_type) ;
383 return CR_OK ;
384 }
386 enum CRStatus
387 cr_font_size_set_to_inherit (CRFontSize *a_this)
388 {
389 g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR) ;
391 cr_font_size_clear (a_this) ;
392 a_this->type = INHERITED_FONT_SIZE ;
394 return CR_OK ;
395 }
397 gboolean
398 cr_font_size_is_set_to_inherit (CRFontSize *a_this)
399 {
400 g_return_val_if_fail (a_this, FALSE) ;
402 return a_this->type == INHERITED_FONT_SIZE ;
403 }
405 gchar *
406 cr_font_size_to_string (CRFontSize * a_this)
407 {
408 gchar *str = NULL;
410 if (!a_this) {
411 str = g_strdup ("NULL");
412 g_return_val_if_fail (str, NULL);
413 return str;
414 }
415 switch (a_this->type) {
416 case PREDEFINED_ABSOLUTE_FONT_SIZE:
417 str = g_strdup (cr_predefined_absolute_font_size_to_string
418 (a_this->value.predefined));
419 break;
420 case ABSOLUTE_FONT_SIZE:
421 str = (gchar *)cr_num_to_string (&a_this->value.absolute);
422 break;
423 case RELATIVE_FONT_SIZE:
424 str = g_strdup (cr_relative_font_size_to_string
425 (a_this->value.relative));
426 break;
427 case INHERITED_FONT_SIZE:
428 str = g_strdup ("inherit");
429 break;
430 default:
431 break;
432 }
433 return str;
434 }
436 void
437 cr_font_size_get_smaller_predefined_font_size (enum CRPredefinedAbsoluteFontSize a_font_size,
438 enum CRPredefinedAbsoluteFontSize *a_smaller_size)
439 {
440 enum CRPredefinedAbsoluteFontSize result = FONT_SIZE_MEDIUM ;
442 g_return_if_fail (a_smaller_size) ;
443 g_return_if_fail ((unsigned)a_font_size < NB_PREDEFINED_ABSOLUTE_FONT_SIZES) ;
445 switch (a_font_size) {
446 case FONT_SIZE_XX_SMALL:
447 result = FONT_SIZE_XX_SMALL ;
448 break ;
449 case FONT_SIZE_X_SMALL:
450 result = FONT_SIZE_XX_SMALL ;
451 break ;
452 case FONT_SIZE_SMALL:
453 result = FONT_SIZE_X_SMALL;
454 break ;
455 case FONT_SIZE_MEDIUM:
456 result = FONT_SIZE_SMALL;
457 break ;
458 case FONT_SIZE_LARGE:
459 result = FONT_SIZE_MEDIUM;
460 break ;
461 case FONT_SIZE_X_LARGE:
462 result = FONT_SIZE_LARGE;
463 break ;
464 case FONT_SIZE_XX_LARGE:
465 result = FONT_SIZE_XX_LARGE;
466 break ;
467 case FONT_SIZE_INHERIT:
468 cr_utils_trace_info ("can't return a smaller size for FONT_SIZE_INHERIT") ;
469 result = FONT_SIZE_MEDIUM ;
470 break ;
471 default:
472 cr_utils_trace_info ("Unknown FONT_SIZE") ;
473 result = FONT_SIZE_MEDIUM ;
474 break ;
475 }
476 *a_smaller_size = result ;
477 }
480 void
481 cr_font_size_get_larger_predefined_font_size (enum CRPredefinedAbsoluteFontSize a_font_size,
482 enum CRPredefinedAbsoluteFontSize *a_larger_size)
483 {
484 enum CRPredefinedAbsoluteFontSize result = FONT_SIZE_MEDIUM ;
486 g_return_if_fail (a_larger_size) ;
487 g_return_if_fail ((unsigned)a_font_size < NB_PREDEFINED_ABSOLUTE_FONT_SIZES) ;
489 switch (a_font_size) {
490 case FONT_SIZE_XX_SMALL:
491 result = FONT_SIZE_X_SMALL ;
492 break ;
493 case FONT_SIZE_X_SMALL:
494 result = FONT_SIZE_SMALL ;
495 break ;
496 case FONT_SIZE_SMALL:
497 result = FONT_SIZE_MEDIUM;
498 break ;
499 case FONT_SIZE_MEDIUM:
500 result = FONT_SIZE_LARGE;
501 break ;
502 case FONT_SIZE_LARGE:
503 result = FONT_SIZE_X_LARGE;
504 break ;
505 case FONT_SIZE_X_LARGE:
506 result = FONT_SIZE_XX_LARGE ;
507 break ;
508 case FONT_SIZE_XX_LARGE:
509 result = FONT_SIZE_XX_LARGE;
510 break ;
511 case FONT_SIZE_INHERIT:
512 cr_utils_trace_info ("can't return a bigger size for FONT_SIZE_INHERIT") ;
513 result = FONT_SIZE_MEDIUM ;
514 break ;
515 default:
516 cr_utils_trace_info ("Unknown FONT_SIZE") ;
517 result = FONT_SIZE_MEDIUM ;
518 break ;
519 }
520 *a_larger_size = result ;
521 }
523 gboolean
524 cr_font_size_is_predefined_absolute_font_size (enum CRPredefinedAbsoluteFontSize a_font_size)
525 {
526 if ((unsigned)a_font_size < NB_PREDEFINED_ABSOLUTE_FONT_SIZES) {
527 return TRUE ;
528 } else {
529 return FALSE ;
530 }
531 }
533 gchar *
534 cr_font_size_adjust_to_string (CRFontSizeAdjust * a_this)
535 {
536 gchar *str = NULL;
538 if (!a_this) {
539 str = g_strdup ("NULL");
540 g_return_val_if_fail (str, NULL);
541 return str;
542 }
544 switch (a_this->type) {
545 case FONT_SIZE_ADJUST_NONE:
546 str = g_strdup ("none");
547 break;
548 case FONT_SIZE_ADJUST_NUMBER:
549 if (a_this->num)
550 str = (gchar *)cr_num_to_string (a_this->num);
551 else
552 str = g_strdup ("unknow font-size-adjust property value"); // Should raise an error no?
553 break;
554 case FONT_SIZE_ADJUST_INHERIT:
555 str = g_strdup ("inherit");
556 }
557 return str;
558 }
560 const gchar *
561 cr_font_style_to_string (enum CRFontStyle a_code)
562 {
563 gchar *str = NULL;
565 switch (a_code) {
566 case FONT_STYLE_NORMAL:
567 str = (gchar *) "normal";
568 break;
569 case FONT_STYLE_ITALIC:
570 str = (gchar *) "italic";
571 break;
572 case FONT_STYLE_OBLIQUE:
573 str = (gchar *) "oblique";
574 break;
575 case FONT_STYLE_INHERIT:
576 str = (gchar *) "inherit";
577 break;
578 default:
579 str = (gchar *) "unknown font style value";
580 break;
581 }
582 return str;
583 }
585 const gchar *
586 cr_font_variant_to_string (enum CRFontVariant a_code)
587 {
588 gchar *str = NULL;
590 switch (a_code) {
591 case FONT_VARIANT_NORMAL:
592 str = (gchar *) "normal";
593 break;
594 case FONT_VARIANT_SMALL_CAPS:
595 str = (gchar *) "small-caps";
596 break;
597 case FONT_VARIANT_INHERIT:
598 str = (gchar *) "inherit";
599 break;
600 }
601 return str;
602 }
604 enum CRFontWeight
605 cr_font_weight_get_bolder (enum CRFontWeight a_weight)
606 {
607 if (a_weight >= NB_FONT_WEIGHTS) {
608 return FONT_WEIGHT_900 ;
609 } else if (a_weight < FONT_WEIGHT_NORMAL) {
610 return FONT_WEIGHT_NORMAL ;
611 } else if (a_weight == FONT_WEIGHT_BOLDER
612 || a_weight == FONT_WEIGHT_BOLDER) {
613 cr_utils_trace_info ("FONT_WEIGHT_BOLDER or FONT_WEIGHT_LIGHTER should not appear here") ;
614 return FONT_WEIGHT_NORMAL ;
615 } else {
616 return (enum CRFontWeight)(a_weight << 1) ;
617 }
618 }
620 const gchar *
621 cr_font_weight_to_string (enum CRFontWeight a_code)
622 {
623 gchar *str = NULL;
625 switch (a_code) {
626 case FONT_WEIGHT_NORMAL:
627 str = (gchar *) "normal";
628 break;
629 case FONT_WEIGHT_BOLD:
630 str = (gchar *) "bold";
631 break;
632 case FONT_WEIGHT_BOLDER:
633 str = (gchar *) "bolder";
634 break;
635 case FONT_WEIGHT_LIGHTER:
636 str = (gchar *) "lighter";
637 break;
638 case FONT_WEIGHT_100:
639 str = (gchar *) "100";
640 break;
641 case FONT_WEIGHT_200:
642 str = (gchar *) "200";
643 break;
644 case FONT_WEIGHT_300:
645 str = (gchar *) "300";
646 break;
647 case FONT_WEIGHT_400:
648 str = (gchar *) "400";
649 break;
650 case FONT_WEIGHT_500:
651 str = (gchar *) "500";
652 break;
653 case FONT_WEIGHT_600:
654 str = (gchar *) "600";
655 break;
656 case FONT_WEIGHT_700:
657 str = (gchar *) "700";
658 break;
659 case FONT_WEIGHT_800:
660 str = (gchar *) "800";
661 break;
662 case FONT_WEIGHT_900:
663 str = (gchar *) "900";
664 break;
665 case FONT_WEIGHT_INHERIT:
666 str = (gchar *) "inherit";
667 break;
668 default:
669 str = (gchar *) "unknown font-weight property value";
670 break;
671 }
672 return str;
673 }
675 const gchar *
676 cr_font_stretch_to_string (enum CRFontStretch a_code)
677 {
678 gchar *str = NULL;
680 switch (a_code) {
681 case FONT_STRETCH_NORMAL:
682 str = (gchar *) "normal";
683 break;
684 case FONT_STRETCH_WIDER:
685 str = (gchar *) "wider";
686 break;
687 case FONT_STRETCH_NARROWER:
688 str = (gchar *) "narrower";
689 break;
690 case FONT_STRETCH_ULTRA_CONDENSED:
691 str = (gchar *) "ultra-condensed";
692 break;
693 case FONT_STRETCH_EXTRA_CONDENSED:
694 str = (gchar *) "extra-condensed";
695 break;
696 case FONT_STRETCH_CONDENSED:
697 str = (gchar *) "condensed";
698 break;
699 case FONT_STRETCH_SEMI_CONDENSED:
700 str = (gchar *) "semi-condensed";
701 break;
702 case FONT_STRETCH_SEMI_EXPANDED:
703 str = (gchar *) "semi-expanded";
704 break;
705 case FONT_STRETCH_EXPANDED:
706 str = (gchar *) "expanded";
707 break;
708 case FONT_STRETCH_EXTRA_EXPANDED:
709 str = (gchar *) "extra-expaned";
710 break;
711 case FONT_STRETCH_ULTRA_EXPANDED:
712 str = (gchar *) "ultra-expanded";
713 break;
714 case FONT_STRETCH_INHERIT:
715 str = (gchar *) "inherit";
716 break;
717 }
718 return str;
719 }
721 void
722 cr_font_size_destroy (CRFontSize * a_font_size)
723 {
724 g_return_if_fail (a_font_size);
726 g_free (a_font_size) ;
727 }
729 /*******************************************************
730 *'font-size-adjust' manipulation function definition
731 *******************************************************/
733 CRFontSizeAdjust *
734 cr_font_size_adjust_new (void)
735 {
736 CRFontSizeAdjust *result =
737 (CRFontSizeAdjust *)g_try_malloc (sizeof (CRFontSizeAdjust));
738 if (!result) {
739 cr_utils_trace_info ("Out of memory");
740 return NULL;
741 }
742 memset (result, 0, sizeof (CRFontSizeAdjust));
744 return result;
745 }
747 void
748 cr_font_size_adjust_destroy (CRFontSizeAdjust * a_this)
749 {
750 g_return_if_fail (a_this);
752 if (a_this->type == FONT_SIZE_ADJUST_NUMBER && a_this->num) {
753 cr_num_destroy (a_this->num);
754 a_this->num = NULL;
755 }
756 }