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