1 /* Fo
2 * fo-property-font-weight.c: 'font-weight' property
3 *
4 * Copyright (C) 2001-2005 Sun Microsystems
5 * Copyright (C) 2007 Menteith Consulting Ltd
6 *
7 * See COPYING for the status of this software.
8 */
9
10 #include <string.h>
11 #include "fo-utils.h"
12 #include "fo-context.h"
13 #include "datatype/fo-datatype.h"
14 #include "property/fo-property-private.h"
15 #include "property/fo-property-text-property.h"
16 #include "property/fo-property-font-size.h"
17 #include "property/fo-property-font-weight.h"
18
19 #ifndef FO_FONT_WEIGHT_NORMAL
20 #define FO_FONT_WEIGHT_NORMAL 400
21 #endif /* !FO_FONT_WEIGHT_NORMAL */
22
23 #ifndef FO_FONT_WEIGHT_BOLD
24 #define FO_FONT_WEIGHT_BOLD 700
25 #endif /* !FO_FONT_WEIGHT_BOLD */
26
27 #ifndef FO_FONT_WEIGHT_STEP
28 #define FO_FONT_WEIGHT_STEP 100
29 #endif /* !FO_FONT_WEIGHT_STEP */
30
31 #ifndef FO_FONT_WEIGHT_MAX
32 #define FO_FONT_WEIGHT_MAX 900
33 #endif /* !FO_FONT_WEIGHT_MAX */
34
35 #ifndef FO_FONT_WEIGHT_MIN
36 #define FO_FONT_WEIGHT_MIN 100
37 #endif /* !FO_FONT_WEIGHT_MIN */
38
39 /* font-weight */
40 /* Inherited: TRUE */
41 /* Shorthand: FALSE */
42 /* normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | inherit */
43 /* Initial value: normal */
44
45 struct _FoPropertyFontWeight
46 {
47 FoProperty parent_instance;
48 };
49
50 struct _FoPropertyFontWeightClass
51 {
52 FoPropertyClass parent_class;
53 };
54
55 static void fo_property_font_weight_init (FoPropertyFontWeight *property_font_weight);
56 static void fo_property_font_weight_class_init (FoPropertyFontWeightClass *klass);
57 static void fo_property_font_weight_finalize (GObject *object);
58 static void fo_property_font_weight_text_property_init (FoPropertyTextPropertyIface *iface);
59
60 static FoDatatype * fo_property_font_weight_resolve_enum (const gchar *token,
61 FoContext *context,
62 GError **error);
63 static FoDatatype * fo_property_font_weight_validate (FoDatatype *datatype,
64 FoContext *context,
65 GError **error);
66 static PangoAttribute * fo_property_font_weight_new_attr (FoProperty *property);
67
68 static const gchar class_name[] = "font-weight";
69 static gpointer parent_class;
70
71 /**
72 * fo_property_font_weight_get_type:
73 *
74 * Register the #FoPropertyFontWeight type if not already registered and
75 * return its #GType value.
76 *
77 * Return value: #GType of #FoPropertyFontWeight.
78 **/
79 GType
fo_property_font_weight_get_type(void)80 fo_property_font_weight_get_type (void)
81 {
82 static GType object_type = 0;
83
84 if (!object_type)
85 {
86 static const GTypeInfo object_info =
87 {
88 sizeof (FoPropertyFontWeightClass),
89 NULL, /* base_init */
90 NULL, /* base_finalize */
91 (GClassInitFunc) fo_property_font_weight_class_init,
92 NULL, /* class_finalize */
93 NULL, /* class_data */
94 sizeof (FoPropertyFontWeight),
95 0, /* n_preallocs */
96 (GInstanceInitFunc) fo_property_font_weight_init,
97 NULL /* value_table */
98 };
99
100 static const GInterfaceInfo fo_property_text_property_info =
101 {
102 (GInterfaceInitFunc) fo_property_font_weight_text_property_init, /* interface_init */
103 NULL,
104 NULL
105 };
106
107 object_type = g_type_register_static (FO_TYPE_PROPERTY,
108 class_name,
109 &object_info, 0);
110
111 g_type_add_interface_static (object_type,
112 FO_TYPE_PROPERTY_TEXT_PROPERTY,
113 &fo_property_text_property_info);
114 }
115
116 return object_type;
117 }
118
119 /**
120 * fo_property_font_weight_init:
121 * @font_weight: #FoPropertyFontWeight object to initialise.
122 *
123 * Implements #GInstanceInitFunc for #FoPropertyFontWeight.
124 **/
125 void
fo_property_font_weight_init(FoPropertyFontWeight * font_weight)126 fo_property_font_weight_init (FoPropertyFontWeight *font_weight)
127 {
128 FO_PROPERTY (font_weight)->value =
129 g_object_ref (fo_integer_new_with_value (FO_FONT_WEIGHT_NORMAL));
130 }
131
132 /**
133 * fo_property_font_weight_class_init:
134 * @klass: #FoPropertyFontWeightClass object to initialise.
135 *
136 * Implements #GClassInitFunc for #FoPropertyFontWeightClass.
137 **/
138 void
fo_property_font_weight_class_init(FoPropertyFontWeightClass * klass)139 fo_property_font_weight_class_init (FoPropertyFontWeightClass *klass)
140 {
141 GObjectClass *object_class = G_OBJECT_CLASS (klass);
142 FoPropertyClass *property_class = FO_PROPERTY_CLASS (klass);
143
144 parent_class = g_type_class_peek_parent (klass);
145
146 object_class->finalize = fo_property_font_weight_finalize;
147
148 property_class->is_inherited = TRUE;
149 property_class->is_shorthand = FALSE;
150 property_class->resolve_enum =
151 fo_property_font_weight_resolve_enum;
152 property_class->validate =
153 fo_property_font_weight_validate;
154 property_class->get_initial =
155 fo_property_font_weight_get_initial;
156 }
157
158 /**
159 * fo_property_font_weight_finalize:
160 * @object: #FoPropertyFontWeight object to finalize.
161 *
162 * Implements #GObjectFinalizeFunc for #FoPropertyFontWeight.
163 **/
164 void
fo_property_font_weight_finalize(GObject * object)165 fo_property_font_weight_finalize (GObject *object)
166 {
167 FoPropertyFontWeight *font_weight;
168
169 font_weight = FO_PROPERTY_FONT_WEIGHT (object);
170
171 G_OBJECT_CLASS (parent_class)->finalize (object);
172 }
173
174 /**
175 * fo_property_font_weight_text_property_init:
176 * @iface: #FoPropertyTextPropertyIFace structure for this class.
177 *
178 * Initialize #FoPropertyTextPropertyIface interface for this class.
179 **/
180 void
fo_property_font_weight_text_property_init(FoPropertyTextPropertyIface * iface)181 fo_property_font_weight_text_property_init (FoPropertyTextPropertyIface *iface)
182 {
183 iface->new_attr = fo_property_font_weight_new_attr;
184 }
185
186 /**
187 * fo_property_font_weight_new:
188 *
189 * Creates a new #FoPropertyFontWeight initialized to default value.
190 *
191 * Return value: the new #FoPropertyFontWeight.
192 **/
193 FoProperty*
fo_property_font_weight_new(void)194 fo_property_font_weight_new (void)
195 {
196 FoProperty* font_weight;
197
198 font_weight =
199 FO_PROPERTY (g_object_new (fo_property_font_weight_get_type (),
200 NULL));
201
202 return font_weight;
203 }
204
205 /**
206 * fo_property_font_weight_resolve_enum:
207 * @token: Token from the XML attribute value to be evaluated as an
208 * enumeration token.
209 * @context: #FoContext object from which to possibly inherit values.
210 * @error: Information about any error that has occurred.
211 *
212 * Compare @token against the enumeration tokens that are valid for the
213 * current FO property. If @token is valid, returns either an #FoEnum datatype
214 * representing the enumeration token or a different datatype representing
215 * the enumeration token's resolved value. If @token is not valid,
216 * sets @error and returns NULL.
217 *
218 * Return value: Resolved enumeration value or NULL.
219 **/
220 FoDatatype*
fo_property_font_weight_resolve_enum(const gchar * token,FoContext * context,GError ** error)221 fo_property_font_weight_resolve_enum (const gchar *token,
222 FoContext *context,
223 GError **error)
224 {
225 gint old_font_weight_value;
226
227 g_return_val_if_fail (token != NULL, NULL);
228 g_return_val_if_fail (FO_IS_CONTEXT (context), NULL);
229 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
230
231 if (strcmp (token, "normal") == 0)
232 {
233 return fo_integer_new_with_value (FO_FONT_WEIGHT_NORMAL);
234 }
235 else if (strcmp (token, "bold") == 0)
236 {
237 return fo_integer_new_with_value (FO_FONT_WEIGHT_BOLD);
238 }
239 else if (strcmp (token, "bolder") == 0)
240 {
241 /* FIXME: Redo with fo_datatype_max(), etc. */
242 old_font_weight_value =
243 fo_integer_get_value (fo_property_get_value (fo_context_get_font_weight (context)));
244
245 return fo_integer_new_with_value (MIN (old_font_weight_value + FO_FONT_WEIGHT_STEP,
246 FO_FONT_WEIGHT_MAX));
247 }
248 else if (strcmp (token, "lighter") == 0)
249 {
250 old_font_weight_value =
251 fo_integer_get_value (fo_property_get_value (fo_context_get_font_weight (context)));
252
253 return fo_integer_new_with_value (MAX (old_font_weight_value - FO_FONT_WEIGHT_STEP,
254 FO_FONT_WEIGHT_MIN));
255 }
256 else
257 {
258 g_set_error (error,
259 FO_FO_ERROR,
260 FO_FO_ERROR_ENUMERATION_TOKEN,
261 _(fo_fo_error_messages[FO_FO_ERROR_ENUMERATION_TOKEN]),
262 class_name,
263 token);
264 return NULL;
265 }
266 }
267
268 /**
269 * fo_property_font_weight_validate:
270 * @datatype: #FoDatatype to be validated against allowed datatypes and
271 * values for current property.
272 * @context: #FoContext object from which to possibly inherit values.
273 * @error: Information about any error that has occurred.
274 *
275 * Validates @datatype against allowed values. Returns @datatype, a
276 * replacement datatype value, or NULL if validation failed.
277 *
278 * Return value: Valid datatype value or NULL.
279 **/
280 FoDatatype*
fo_property_font_weight_validate(FoDatatype * datatype,FoContext * context,GError ** error)281 fo_property_font_weight_validate (FoDatatype *datatype,
282 FoContext *context,
283 GError **error)
284 {
285 FoDatatype *new_datatype;
286 GError *tmp_error = NULL;
287 gchar *token;
288 gint int_value;
289 gfloat float_value;
290
291 g_return_val_if_fail (datatype != NULL, NULL);
292 g_return_val_if_fail (FO_IS_DATATYPE (datatype), NULL);
293 g_return_val_if_fail (context != NULL, NULL);
294 g_return_val_if_fail (FO_IS_CONTEXT (context), NULL);
295 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
296
297 if (FO_IS_ENUM (datatype))
298 {
299 FoEnumEnum value = fo_enum_get_value (datatype);
300
301 if (value == FO_ENUM_ENUM_NORMAL)
302 {
303 return fo_integer_new_with_value (FO_FONT_WEIGHT_NORMAL);
304 }
305 else if (value == FO_ENUM_ENUM_BOLD)
306 {
307 return fo_integer_new_with_value (FO_FONT_WEIGHT_BOLD);
308 }
309 else if ((value == FO_ENUM_ENUM_BOLDER) ||
310 (value == FO_ENUM_ENUM_LIGHTER))
311 {
312 return datatype;
313 }
314 else if (value == FO_ENUM_ENUM_100)
315 {
316 return fo_integer_new_with_value (100);
317 }
318 else if (value == FO_ENUM_ENUM_200)
319 {
320 return fo_integer_new_with_value (200);
321 }
322 else if (value == FO_ENUM_ENUM_300)
323 {
324 return fo_integer_new_with_value (300);
325 }
326 else if (value == FO_ENUM_ENUM_400)
327 {
328 return fo_integer_new_with_value (400);
329 }
330 else if (value == FO_ENUM_ENUM_500)
331 {
332 return fo_integer_new_with_value (500);
333 }
334 else if (value == FO_ENUM_ENUM_600)
335 {
336 return fo_integer_new_with_value (600);
337 }
338 else if (value == FO_ENUM_ENUM_700)
339 {
340 return fo_integer_new_with_value (700);
341 }
342 else if (value == FO_ENUM_ENUM_800)
343 {
344 return fo_integer_new_with_value (800);
345 }
346 else if (value == FO_ENUM_ENUM_900)
347 {
348 return fo_integer_new_with_value (900);
349 }
350 else
351 {
352 gchar *datatype_sprintf = fo_object_sprintf (datatype);
353
354 g_set_error (error,
355 FO_FO_ERROR,
356 FO_FO_ERROR_ENUMERATION_TOKEN,
357 _(fo_fo_error_messages[FO_FO_ERROR_ENUMERATION_TOKEN]),
358 class_name,
359 datatype_sprintf,
360 g_type_name (G_TYPE_FROM_INSTANCE (datatype)));
361
362 g_object_unref (datatype);
363
364 g_free (datatype_sprintf);
365
366 return NULL;
367 }
368 }
369 else if (FO_IS_STRING (datatype))
370 {
371 token = fo_string_get_value (datatype);
372
373 new_datatype =
374 fo_property_font_weight_resolve_enum (token, context, &tmp_error);
375
376 g_object_unref (datatype);
377
378 fo_propagate_and_return_val_if_error (error, tmp_error, NULL);
379
380 return new_datatype;
381 }
382 else if (FO_IS_NAME (datatype))
383 {
384 token = fo_name_get_value (datatype);
385
386 new_datatype =
387 fo_property_font_weight_resolve_enum (token, context, &tmp_error);
388
389 g_object_unref (datatype);
390
391 fo_propagate_and_return_val_if_error (error, tmp_error, NULL);
392
393 return new_datatype;
394 }
395 else if (FO_IS_NUMBER (datatype))
396 {
397 float_value = fo_number_get_value (datatype);
398
399 if ((float_value == 100) || (float_value == 200) ||
400 (float_value == 300) || (float_value == 400) ||
401 (float_value == 500) || (float_value == 600) ||
402 (float_value == 700) || (float_value == 800) ||
403 (float_value == 900))
404 {
405 new_datatype = fo_integer_new_with_value ((int) float_value);
406 g_object_unref (datatype);
407
408 return new_datatype;
409 }
410 else
411 {
412 g_warning ("Incorrect font-weight: %g", float_value);
413
414 int_value = (int) float_value / 100;
415
416 int_value = CLAMP (int_value, 1, 9) * 100;
417
418 new_datatype = fo_integer_new_with_value (int_value);
419
420 g_object_unref (datatype);
421
422 return new_datatype;
423 }
424 }
425 else if (FO_IS_INTEGER (datatype))
426 {
427 int_value = fo_integer_get_value (datatype);
428
429 if ((int_value == 100) || (int_value == 200) ||
430 (int_value == 300) || (int_value == 400) ||
431 (int_value == 500) || (int_value == 600) ||
432 (int_value == 700) || (int_value == 800) ||
433 (int_value == 900))
434 {
435 return datatype;
436 }
437 else
438 {
439 g_warning ("Incorrect font-weight: %d", int_value);
440
441 int_value = CLAMP (int_value / 100, 1, 9) * 100;
442
443 new_datatype = fo_integer_new_with_value (int_value);
444
445 g_object_unref (datatype);
446
447 return new_datatype;
448 }
449 }
450 else
451 {
452 gchar *datatype_sprintf = fo_object_sprintf (datatype);
453
454 g_set_error (error,
455 FO_FO_ERROR,
456 FO_FO_ERROR_DATATYPE,
457 _(fo_fo_error_messages[FO_FO_ERROR_DATATYPE]),
458 class_name,
459 datatype_sprintf,
460 g_type_name (G_TYPE_FROM_INSTANCE (datatype)));
461
462 g_object_unref (datatype);
463
464 g_free (datatype_sprintf);
465
466 return NULL;
467 }
468 }
469
470 /**
471 * fo_property_font_weight_get_initial:
472 *
473 * Get an instance of the property with the correct initial value.
474 *
475 * Return value: An instance of the property.
476 **/
477 FoProperty*
fo_property_font_weight_get_initial(void)478 fo_property_font_weight_get_initial (void)
479 {
480 static FoProperty *font_weight = NULL;
481
482 if (font_weight == NULL)
483 {
484 font_weight =
485 fo_property_font_weight_new ();
486 }
487
488 return font_weight;
489 }
490
491 /**
492 * fo_property_font_weight_new_attr:
493 * @property: #FoProperty from which to create a #PangoAttribute.
494 *
495 * Makes a new #PangoAttribute representing the current property.
496 *
497 * Return value: New #PangoAttribute.
498 **/
499 PangoAttribute*
fo_property_font_weight_new_attr(FoProperty * property)500 fo_property_font_weight_new_attr (FoProperty *property)
501 {
502 gint pango_font_weight;
503
504 g_return_val_if_fail (FO_IS_PROPERTY_FONT_WEIGHT (property), NULL);
505
506 pango_font_weight =
507 fo_integer_get_value (property->value);
508
509 return pango_attr_weight_new (pango_font_weight);
510 }
511