1 /*
2 * This file is part of LibCSS
3 * Licensed under the MIT License,
4 * http://www.opensource.org/licenses/mit-license.php
5 * Copyright 2009 John-Mark Bell <jmb@netsurf-browser.org>
6 */
7
8 #include "bytecode/bytecode.h"
9 #include "bytecode/opcodes.h"
10 #include "select/propset.h"
11 #include "select/propget.h"
12 #include "utils/utils.h"
13
14 #include "select/properties/properties.h"
15 #include "select/properties/helpers.h"
16
css__cascade_font_family(uint32_t opv,css_style * style,css_select_state * state)17 css_error css__cascade_font_family(uint32_t opv, css_style *style,
18 css_select_state *state)
19 {
20 uint16_t value = CSS_FONT_FAMILY_INHERIT;
21 lwc_string **fonts = NULL;
22 uint32_t n_fonts = 0;
23
24 if (isInherit(opv) == false) {
25 uint32_t v = getValue(opv);
26
27 while (v != FONT_FAMILY_END) {
28 lwc_string *font = NULL;
29 lwc_string **temp;
30
31 switch (v) {
32 case FONT_FAMILY_STRING:
33 case FONT_FAMILY_IDENT_LIST:
34 css__stylesheet_string_get(style->sheet,
35 *((css_code_t *) style->bytecode),
36 &font);
37 advance_bytecode(style, sizeof(css_code_t));
38 break;
39 case FONT_FAMILY_SERIF:
40 if (value == CSS_FONT_FAMILY_INHERIT)
41 value = CSS_FONT_FAMILY_SERIF;
42 break;
43 case FONT_FAMILY_SANS_SERIF:
44 if (value == CSS_FONT_FAMILY_INHERIT)
45 value = CSS_FONT_FAMILY_SANS_SERIF;
46 break;
47 case FONT_FAMILY_CURSIVE:
48 if (value == CSS_FONT_FAMILY_INHERIT)
49 value = CSS_FONT_FAMILY_CURSIVE;
50 break;
51 case FONT_FAMILY_FANTASY:
52 if (value == CSS_FONT_FAMILY_INHERIT)
53 value = CSS_FONT_FAMILY_FANTASY;
54 break;
55 case FONT_FAMILY_MONOSPACE:
56 if (value == CSS_FONT_FAMILY_INHERIT)
57 value = CSS_FONT_FAMILY_MONOSPACE;
58 break;
59 }
60
61 /* Only use family-names which occur before the first
62 * generic-family. Any values which occur after the
63 * first generic-family are ignored. */
64 /** \todo Do this at bytecode generation time? */
65 if (value == CSS_FONT_FAMILY_INHERIT && font != NULL) {
66 temp = realloc(fonts,
67 (n_fonts + 1) * sizeof(lwc_string *));
68 if (temp == NULL) {
69 if (fonts != NULL) {
70 free(fonts);
71 }
72 return CSS_NOMEM;
73 }
74
75 fonts = temp;
76
77 fonts[n_fonts] = font;
78
79 n_fonts++;
80 }
81
82 v = *((uint32_t *) style->bytecode);
83 advance_bytecode(style, sizeof(v));
84 }
85 }
86
87 /* Terminate array with blank entry, if needed */
88 if (n_fonts > 0) {
89 lwc_string **temp;
90
91 temp = realloc(fonts, (n_fonts + 1) * sizeof(lwc_string *));
92 if (temp == NULL) {
93 free(fonts);
94 return CSS_NOMEM;
95 }
96
97 fonts = temp;
98
99 fonts[n_fonts] = NULL;
100
101 if (value == CSS_FONT_FAMILY_INHERIT) {
102 /* The stylesheet doesn't specify a generic family,
103 * but it has specified named fonts.
104 * Fall back to the user agent's default family.
105 * We don't want to inherit, because that will
106 * incorrectly overwrite the named fonts list too.
107 */
108 css_hint hint;
109 css_error error;
110
111 error = state->handler->ua_default_for_property(
112 state->pw, CSS_PROP_FONT_FAMILY, &hint);
113 if (error == CSS_OK) {
114 lwc_string **item;
115
116 value = hint.status;
117
118 for (item = hint.data.strings;
119 item != NULL && (*item) != NULL;
120 item++) {
121 lwc_string_unref(*item);
122 }
123
124 if (hint.data.strings != NULL) {
125 free(hint.data.strings);
126 }
127 }
128
129 if (value == CSS_FONT_FAMILY_INHERIT) {
130 /* No sane UA default: assume sans-serif */
131 value = CSS_FONT_FAMILY_SANS_SERIF;
132 }
133 }
134 }
135
136 if (css__outranks_existing(getOpcode(opv), isImportant(opv), state,
137 isInherit(opv))) {
138 css_error error;
139
140 error = set_font_family(state->computed, value, fonts);
141 if (error != CSS_OK && n_fonts > 0)
142 free(fonts);
143
144 return error;
145 } else {
146 if (n_fonts > 0)
147 free(fonts);
148 }
149
150 return CSS_OK;
151 }
152
css__set_font_family_from_hint(const css_hint * hint,css_computed_style * style)153 css_error css__set_font_family_from_hint(const css_hint *hint,
154 css_computed_style *style)
155 {
156 lwc_string **item;
157 css_error error;
158
159 error = set_font_family(style, hint->status, hint->data.strings);
160
161 for (item = hint->data.strings;
162 item != NULL && (*item) != NULL; item++) {
163 lwc_string_unref(*item);
164 }
165
166 if (error != CSS_OK && hint->data.strings != NULL)
167 free(hint->data.strings);
168
169 return error;
170 }
171
css__initial_font_family(css_select_state * state)172 css_error css__initial_font_family(css_select_state *state)
173 {
174 css_hint hint;
175 css_error error;
176
177 error = state->handler->ua_default_for_property(state->pw,
178 CSS_PROP_FONT_FAMILY, &hint);
179 if (error != CSS_OK)
180 return error;
181
182 return css__set_font_family_from_hint(&hint, state->computed);
183 }
184
css__compose_font_family(const css_computed_style * parent,const css_computed_style * child,css_computed_style * result)185 css_error css__compose_font_family(const css_computed_style *parent,
186 const css_computed_style *child,
187 css_computed_style *result)
188 {
189 css_error error;
190 lwc_string **names = NULL;
191 uint8_t type = get_font_family(child, &names);
192
193 if (type == CSS_FONT_FAMILY_INHERIT || result != child) {
194 size_t n_names = 0;
195 lwc_string **copy = NULL;
196
197 if (type == CSS_FONT_FAMILY_INHERIT)
198 type = get_font_family(parent, &names);
199
200 if (names != NULL) {
201 lwc_string **i;
202
203 for (i = names; (*i) != NULL; i++)
204 n_names++;
205
206 copy = malloc((n_names + 1) * sizeof(lwc_string *));
207 if (copy == NULL)
208 return CSS_NOMEM;
209
210 memcpy(copy, names, (n_names + 1) *
211 sizeof(lwc_string *));
212 }
213
214 error = set_font_family(result, type, copy);
215 if (error != CSS_OK && copy != NULL)
216 free(copy);
217
218 return error;
219 }
220
221 return CSS_OK;
222 }
223
224