1 /* Fo
2 * fo-property-line-height.c: 'line-height' property
3 *
4 * Copyright (C) 2001 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 /*
16 #include "property/fo-property-text-property.h"
17 */
18 #include "property/fo-property-font-size.h"
19 #include "property/fo-property-line-height.h"
20
21
22 #define FO_PROPERTY_LINE_HEIGHT_NORMAL_MULTIPLIER 1.2
23 /* line-height */
24 /* Inherited: TRUE */
25 /* Shorthand: FALSE */
26 /* normal | <length> | <number> | <percentage> | <space> | inherit */
27 /* Initial value: normal */
28
29 struct _FoPropertyLineHeight
30 {
31 FoProperty parent_instance;
32 };
33
34 struct _FoPropertyLineHeightClass
35 {
36 FoPropertyClass parent_class;
37 };
38
39 static void fo_property_line_height_init (FoPropertyLineHeight *property_line_height);
40 static void fo_property_line_height_class_init (FoPropertyLineHeightClass *klass);
41 static void fo_property_line_height_finalize (GObject *object);
42
43 static FoDatatype* fo_property_line_height_resolve_enum (const gchar *token,
44 FoContext *context,
45 GError **error);
46 static FoDatatype* fo_property_line_height_validate (FoDatatype *datatype,
47 FoContext *context,
48 GError **error);
49 /*
50 static void fo_property_line_height_text_property_init (FoPropertyTextPropertyIface *iface);
51 static PangoAttribute * fo_property_line_height_new_attr (FoProperty *property);
52 */
53 static const gchar class_name[] = "line-height";
54 static gpointer parent_class;
55
56 /**
57 * fo_property_line_height_get_type:
58 *
59 * Register the #FoPropertyLineHeight type if not already registered and
60 * return its #GType value.
61 *
62 * Return value: #GType of #FoPropertyLineHeight.
63 **/
64 GType
fo_property_line_height_get_type(void)65 fo_property_line_height_get_type (void)
66 {
67 static GType object_type = 0;
68
69 if (!object_type)
70 {
71 static const GTypeInfo object_info =
72 {
73 sizeof (FoPropertyLineHeightClass),
74 NULL, /* base_init */
75 NULL, /* base_finalize */
76 (GClassInitFunc) fo_property_line_height_class_init,
77 NULL, /* class_finalize */
78 NULL, /* class_data */
79 sizeof (FoPropertyLineHeight),
80 0, /* n_preallocs */
81 (GInstanceInitFunc) fo_property_line_height_init,
82 NULL /* value_table */
83 };
84 /*
85 static const GInterfaceInfo fo_property_text_property_info =
86 {
87 (GInterfaceInitFunc) fo_property_line_height_text_property_init, / * interface_init * /
88 NULL,
89 NULL
90 };
91 */
92 object_type = g_type_register_static (FO_TYPE_PROPERTY,
93 class_name,
94 &object_info, 0);
95 /*
96 g_type_add_interface_static (object_type,
97 FO_TYPE_PROPERTY_TEXT_PROPERTY,
98 &fo_property_text_property_info);
99 */
100 }
101
102 return object_type;
103 }
104
105 /**
106 * fo_property_line_height_init:
107 * @line_height: #FoPropertyLineHeight object to initialise.
108 *
109 * Implements #GInstanceInitFunc for #FoPropertyLineHeight.
110 **/
111 void
fo_property_line_height_init(FoPropertyLineHeight * line_height)112 fo_property_line_height_init (FoPropertyLineHeight *line_height)
113 {
114 FO_PROPERTY (line_height)->value =
115 g_object_ref (fo_enum_factory_get_enum_by_nick ("normal"));
116 }
117
118 /**
119 * fo_property_line_height_class_init:
120 * @klass: #FoPropertyLineHeightClass object to initialise.
121 *
122 * Implements #GClassInitFunc for #FoPropertyLineHeightClass.
123 **/
124 void
fo_property_line_height_class_init(FoPropertyLineHeightClass * klass)125 fo_property_line_height_class_init (FoPropertyLineHeightClass *klass)
126 {
127 GObjectClass *object_class = G_OBJECT_CLASS (klass);
128 FoPropertyClass *property_class = FO_PROPERTY_CLASS (klass);
129
130 parent_class = g_type_class_peek_parent (klass);
131
132 object_class->finalize = fo_property_line_height_finalize;
133
134 property_class->is_inherited = TRUE;
135 property_class->is_shorthand = FALSE;
136 property_class->resolve_enum =
137 fo_property_line_height_resolve_enum;
138 property_class->validate =
139 fo_property_line_height_validate;
140 property_class->get_initial =
141 fo_property_line_height_get_initial;
142 }
143
144 /**
145 * fo_property_line_height_finalize:
146 * @object: #FoPropertyLineHeight object to finalize.
147 *
148 * Implements #GObjectFinalizeFunc for #FoPropertyLineHeight.
149 **/
150 void
fo_property_line_height_finalize(GObject * object)151 fo_property_line_height_finalize (GObject *object)
152 {
153 FoPropertyLineHeight *line_height;
154
155 line_height = FO_PROPERTY_LINE_HEIGHT (object);
156
157 G_OBJECT_CLASS (parent_class)->finalize (object);
158 }
159
160 /**
161 * fo_property_line_height_text_property_init:
162 * @iface: #FoPropertyTextPropertyIFace structure for this class.
163 *
164 * Initialize #FoPropertyTextPropertyIface interface for this class.
165 **/
166 /*
167 void
168 fo_property_line_height_text_property_init (FoPropertyTextPropertyIface *iface)
169 {
170 iface->new_attr = fo_property_line_height_new_attr;
171 }
172 */
173
174 /**
175 * fo_property_line_height_new:
176 *
177 * Creates a new #FoPropertyLineHeight initialized to default value.
178 *
179 * Return value: the new #FoPropertyLineHeight.
180 **/
181 FoProperty*
fo_property_line_height_new(void)182 fo_property_line_height_new (void)
183 {
184 FoProperty* line_height;
185
186 line_height =
187 FO_PROPERTY (g_object_new (fo_property_line_height_get_type (),
188 NULL));
189
190 return line_height;
191 }
192
193 /**
194 * fo_property_line_height_resolve_enum:
195 * @token: Token from the XML attribute value to be evaluated as an
196 * enumeration token.
197 * @context: #FoContext object from which to possibly inherit values.
198 * @error: Information about any error that has occurred.
199 *
200 * Compare @token against the enumeration tokens that are valid for the
201 * current FO property. If @token is valid, returns either an #FoEnum datatype
202 * representing the enumeration token or a different datatype representing
203 * the enumeration token's resolved value. If @token is not valid,
204 * sets @error and returns NULL.
205 *
206 * Return value: Resolved enumeration value or NULL.
207 **/
208 FoDatatype*
fo_property_line_height_resolve_enum(const gchar * token,FoContext * context,GError ** error)209 fo_property_line_height_resolve_enum (const gchar *token,
210 FoContext *context,
211 GError **error)
212 {
213 g_return_val_if_fail (token != NULL, NULL);
214 g_return_val_if_fail (FO_IS_CONTEXT (context), NULL);
215 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
216
217 if (strcmp (token, "normal") == 0)
218 {
219 return g_object_ref (fo_enum_factory_get_enum_by_nick (token));
220 }
221 else
222 {
223 g_set_error (error,
224 FO_FO_ERROR,
225 FO_FO_ERROR_ENUMERATION_TOKEN,
226 _(fo_fo_error_messages[FO_FO_ERROR_ENUMERATION_TOKEN]),
227 class_name,
228 token);
229 return NULL;
230 }
231 }
232
233 /**
234 * fo_property_line_height_validate:
235 * @datatype: #FoDatatype to be validated against allowed datatypes and
236 * values for current property.
237 * @context: #FoContext object from which to possibly inherit values.
238 * @error: Information about any error that has occurred.
239 *
240 * Validates @datatype against allowed values. Returns @datatype, a
241 * replacement datatype value, or NULL if validation failed.
242 *
243 * Return value: Valid datatype value or NULL.
244 **/
245 FoDatatype*
fo_property_line_height_validate(FoDatatype * datatype,FoContext * context,GError ** error)246 fo_property_line_height_validate (FoDatatype *datatype,
247 FoContext *context,
248 GError **error)
249 {
250 FoDatatype *new_datatype;
251 GError *tmp_error = NULL;
252 gchar *token;
253
254 g_return_val_if_fail (datatype != NULL, NULL);
255 g_return_val_if_fail (FO_IS_DATATYPE (datatype), NULL);
256 g_return_val_if_fail (context != NULL, NULL);
257 g_return_val_if_fail (FO_IS_CONTEXT (context), NULL);
258 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
259
260 if (FO_IS_ENUM (datatype))
261 {
262 FoEnumEnum value = fo_enum_get_value (datatype);
263
264 if (value == FO_ENUM_ENUM_NORMAL)
265 {
266 return datatype;
267 }
268 else
269 {
270 gchar *datatype_sprintf = fo_object_sprintf (datatype);
271
272 g_set_error (error,
273 FO_FO_ERROR,
274 FO_FO_ERROR_ENUMERATION_TOKEN,
275 _(fo_fo_error_messages[FO_FO_ERROR_ENUMERATION_TOKEN]),
276 class_name,
277 datatype_sprintf,
278 g_type_name (G_TYPE_FROM_INSTANCE (datatype)));
279
280 g_object_unref (datatype);
281
282 g_free (datatype_sprintf);
283
284 return NULL;
285 }
286 }
287 else if (FO_IS_STRING (datatype))
288 {
289 token = fo_string_get_value (datatype);
290
291 new_datatype =
292 fo_property_line_height_resolve_enum (token, context, &tmp_error);
293
294 g_object_unref (datatype);
295
296 fo_propagate_and_return_val_if_error (error, tmp_error, NULL);
297
298 return new_datatype;
299 }
300 else if (FO_IS_NAME (datatype))
301 {
302 token = fo_name_get_value (datatype);
303
304 new_datatype =
305 fo_property_line_height_resolve_enum (token, context, &tmp_error);
306
307 g_object_unref (datatype);
308
309 fo_propagate_and_return_val_if_error (error, tmp_error, NULL);
310
311 return new_datatype;
312 }
313 else if (FO_IS_LENGTH (datatype))
314 {
315 return datatype;
316 }
317 else if (FO_IS_NUMBER (datatype))
318 {
319 return datatype;
320 }
321 else if (FO_IS_PERCENTAGE (datatype))
322 {
323 return datatype;
324 }
325 else if (FO_IS_SPACE (datatype))
326 {
327 return datatype;
328 }
329 else
330 {
331 gchar *datatype_sprintf = fo_object_sprintf (datatype);
332
333 g_set_error (error,
334 FO_FO_ERROR,
335 FO_FO_ERROR_DATATYPE,
336 _(fo_fo_error_messages[FO_FO_ERROR_DATATYPE]),
337 class_name,
338 datatype_sprintf,
339 g_type_name (G_TYPE_FROM_INSTANCE (datatype)));
340
341 g_object_unref (datatype);
342
343 g_free (datatype_sprintf);
344
345 return NULL;
346 }
347 }
348
349 /**
350 * fo_property_line_height_get_initial:
351 *
352 * Get an instance of the property with the correct initial value.
353 *
354 * Return value: An instance of the property.
355 **/
356 FoProperty*
fo_property_line_height_get_initial(void)357 fo_property_line_height_get_initial (void)
358 {
359 static FoProperty *line_height = NULL;
360
361 if (line_height == NULL)
362 {
363 line_height =
364 fo_property_line_height_new ();
365 }
366
367 return line_height;
368 }
369
370 /**
371 * fo_property_line_height_resolve:
372 * @line_height: 'line-height' property.
373 * @font_size: 'font-size' property.
374 *
375 * Determine the computed value of the 'line-height' based on
376 * @line_height and @font_size.
377 *
378 * Return value: #FoProperty with the computed value of @line_height.
379 **/
380 FoProperty*
fo_property_line_height_resolve(FoProperty * line_height,FoProperty * font_size)381 fo_property_line_height_resolve (FoProperty *line_height,
382 FoProperty *font_size)
383 {
384 FoDatatype *line_height_value;
385
386 g_return_val_if_fail (FO_IS_PROPERTY_LINE_HEIGHT (line_height), NULL);
387 g_return_val_if_fail (FO_IS_PROPERTY_FONT_SIZE (font_size), NULL);
388
389 line_height_value = fo_property_get_value (line_height);
390
391 if (FO_IS_LENGTH (line_height_value))
392 {
393 return line_height;
394 }
395 else
396 {
397 FoDatatype *new_value = NULL;
398 FoProperty *new_line_height = fo_property_line_height_new ();
399
400 gfloat font_size_value =
401 fo_length_get_value (fo_property_get_value (font_size));
402
403 /* FIXME Doesn't handle space case */
404 if (FO_IS_ENUM (line_height_value))
405 {
406 FoEnumEnum enum_value = fo_enum_get_value (line_height_value);
407
408 if (enum_value == FO_ENUM_ENUM_NORMAL)
409 {
410 new_value =
411 fo_length_new_with_value (font_size_value *
412 FO_PROPERTY_LINE_HEIGHT_NORMAL_MULTIPLIER);
413 }
414 }
415 else if (FO_IS_NUMBER (line_height_value))
416 {
417 new_value =
418 fo_length_new_with_value (fo_number_get_value (line_height_value) *
419 font_size_value);
420 }
421 else if (FO_IS_PERCENTAGE (line_height_value))
422 {
423 new_value =
424 fo_length_new_with_value (fo_percentage_get_value (line_height_value) *
425 font_size_value / 100);
426 }
427
428 fo_property_set_value (new_line_height, new_value);
429 return new_line_height;
430 }
431 }
432
433 /**
434 * fo_property_line_height_new_attr:
435 * @property: #FoProperty from which to create a #PangoAttribute.
436 *
437 * Makes a new #PangoAttribute representing the current property.
438 *
439 * Return value: New #PangoAttribute.
440 **/
441 /*
442 PangoAttribute*
443 fo_property_line_height_new_attr (FoProperty *property)
444 {
445 gint pango_line_height;
446
447 g_return_val_if_fail (FO_IS_PROPERTY_LINE_HEIGHT (property), NULL);
448
449 pango_line_height =
450 (int) (fo_length_get_value (property->value) *
451 PANGO_SCALE);
452
453 return pango_attr_line_height_new (pango_line_height);
454 }
455 */
456