1 /* Fo
2  * fo-property-reference-orientation.c: 'reference-orientation' property
3  *
4  * Copyright (C) 2001-2006 Sun Microsystems
5  * Copyright (C) 2007-2010 Menteith Consulting Ltd
6  * Copyright (C) 2011 Mentea
7  *
8  * See COPYING for the status of this software.
9  */
10 
11 #include <string.h>
12 #include "fo-utils.h"
13 #include "fo-context.h"
14 #include "datatype/fo-datatype.h"
15 #include "property/fo-property-private.h"
16 #include "property/fo-property-font-size.h"
17 #include "property/fo-property-reference-orientation.h"
18 
19 /**
20  * SECTION:fo-property-reference-orientation
21  * @short_description: 'reference-orientation' property
22  *
23  * Inherited: TRUE
24  *
25  * Shorthand: FALSE
26  *
27  * Value: 0 | 90 | 180 | 270 | -90 | -180 | -270 | inherit
28  *
29  * Initial value: 0
30  *
31  * Definition: <ulink url="http://www.w3.org/TR/xsl11/&num;reference-orientation">http://www.w3.org/TR/xsl11/&num;reference-orientation</ulink>
32  */
33 
34 struct _FoPropertyReferenceOrientation
35 {
36   FoProperty parent_instance;
37 };
38 
39 struct _FoPropertyReferenceOrientationClass
40 {
41   FoPropertyClass parent_class;
42 };
43 
44 static void _init         (FoPropertyReferenceOrientation      *property_reference_orientation);
45 static void _class_init   (FoPropertyReferenceOrientationClass *klass);
46 
47 static FoDatatype * _resolve_enum (const gchar *token,
48                                    FoContext   *context,
49                                    GError     **error);
50 static FoDatatype * _validate     (FoDatatype  *datatype,
51                                    FoContext   *context,
52                                    GError     **error);
53 
54 static const gchar class_name[] = "reference-orientation";
55 static gpointer parent_class;
56 
57 /**
58  * fo_property_reference_orientation_get_type:
59  *
60  * Register the #FoPropertyReferenceOrientation type if not already registered and
61  * return its #GType value.
62  *
63  * Return value: #GType of #FoPropertyReferenceOrientation.
64  **/
65 GType
fo_property_reference_orientation_get_type(void)66 fo_property_reference_orientation_get_type (void)
67 {
68   static GType object_type = 0;
69 
70   if (!object_type)
71     {
72       static const GTypeInfo object_info =
73       {
74         sizeof (FoPropertyReferenceOrientationClass),
75         NULL,           /* base_init */
76         NULL,           /* base_finalize */
77         (GClassInitFunc) _class_init,
78         NULL,           /* class_finalize */
79         NULL,           /* class_data */
80         sizeof (FoPropertyReferenceOrientation),
81         0,              /* n_preallocs */
82         (GInstanceInitFunc) _init,
83 	NULL		/* value_table */
84       };
85 
86       object_type = g_type_register_static (FO_TYPE_PROPERTY,
87                                             class_name,
88                                             &object_info, 0);
89     }
90 
91   return object_type;
92 }
93 
94 /**
95  * _init:
96  * @reference_orientation: #FoPropertyReferenceOrientation object to initialise.
97  *
98  * Implements #GInstanceInitFunc for #FoPropertyReferenceOrientation.
99  **/
100 static void
_init(FoPropertyReferenceOrientation * reference_orientation)101 _init (FoPropertyReferenceOrientation *reference_orientation)
102 {
103   FO_PROPERTY (reference_orientation)->value =
104     g_object_ref (fo_enum_factory_get_enum_by_value (FO_ENUM_ENUM_0));
105 }
106 
107 /**
108  * _class_init:
109  * @klass: #FoPropertyReferenceOrientationClass object to initialise.
110  *
111  * Implements #GClassInitFunc for #FoPropertyReferenceOrientationClass.
112  **/
113 static void
_class_init(FoPropertyReferenceOrientationClass * klass)114 _class_init (FoPropertyReferenceOrientationClass *klass)
115 {
116   FoPropertyClass *property_class = FO_PROPERTY_CLASS (klass);
117 
118   parent_class = g_type_class_peek_parent (klass);
119 
120   property_class->is_inherited = TRUE;
121   property_class->is_shorthand = FALSE;
122   property_class->resolve_enum =
123     _resolve_enum;
124   property_class->validate =
125     _validate;
126   property_class->get_initial =
127     fo_property_reference_orientation_get_initial;
128 }
129 
130 /**
131  * fo_property_reference_orientation_new:
132  *
133  * Creates a new #FoPropertyReferenceOrientation initialized to default value.
134  *
135  * Return value: the new #FoPropertyReferenceOrientation.
136  **/
137 FoProperty*
fo_property_reference_orientation_new(void)138 fo_property_reference_orientation_new (void)
139 {
140   FoProperty* reference_orientation;
141 
142   reference_orientation =
143     FO_PROPERTY (g_object_new (fo_property_reference_orientation_get_type (),
144                                NULL));
145 
146   return reference_orientation;
147 }
148 
149 /**
150  * _resolve_enum:
151  * @token:   Token from the XML attribute value to be evaluated as an
152  *           enumeration token.
153  * @context: #FoContext object from which to possibly inherit values.
154  * @error:   Information about any error that has occurred.
155  *
156  * Compare @token against the enumeration tokens that are valid for the
157  * current FO property.  If @token is valid, returns either an #FoEnum datatype
158  * representing the enumeration token or a different datatype representing
159  * the enumeration token's resolved value.  If @token is not valid,
160  * sets @error and returns NULL.
161  *
162  * Return value: Resolved enumeration value or NULL.
163  **/
164 static FoDatatype *
_resolve_enum(const gchar * token,FoContext * context,GError ** error)165 _resolve_enum (const gchar *token,
166                FoContext   *context,
167                GError     **error)
168 {
169   g_return_val_if_fail (token != NULL, NULL);
170   g_return_val_if_fail (FO_IS_CONTEXT (context), NULL);
171   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
172 
173   if ((strcmp (token, "0") == 0) ||
174       (strcmp (token, "90") == 0) ||
175       (strcmp (token, "180") == 0) ||
176       (strcmp (token, "270") == 0) ||
177       (strcmp (token, "-90") == 0) ||
178       (strcmp (token, "-180") == 0) ||
179       (strcmp (token, "-270") == 0))
180     {
181       return g_object_ref (fo_enum_factory_get_enum_by_nick (token));
182     }
183   else
184     {
185       g_set_error (error,
186 		   FO_FO_ERROR,
187 		   FO_FO_ERROR_ENUMERATION_TOKEN,
188 		   _(fo_fo_error_messages[FO_FO_ERROR_ENUMERATION_TOKEN]),
189 		   class_name,
190 		   token);
191       return NULL;
192     }
193 }
194 
195 /**
196  * _validate:
197  * @datatype: #FoDatatype to be validated against allowed datatypes and
198  *            values for current property.
199  * @context:  #FoContext object from which to possibly inherit values.
200  * @error:    Information about any error that has occurred.
201  *
202  * Validates @datatype against allowed values.  Returns @datatype, a
203  * replacement datatype value, or NULL if validation failed.
204  *
205  * Return value: Valid datatype value or NULL.
206  **/
207 FoDatatype*
_validate(FoDatatype * datatype,FoContext * context,GError ** error)208 _validate (FoDatatype *datatype,
209            FoContext  *context,
210            GError    **error)
211 {
212   FoDatatype *new_datatype;
213   GError     *tmp_error = NULL;
214   gchar      *token;
215 
216   g_return_val_if_fail (datatype != NULL, NULL);
217   g_return_val_if_fail (FO_IS_DATATYPE (datatype), NULL);
218   g_return_val_if_fail (context != NULL, NULL);
219   g_return_val_if_fail (FO_IS_CONTEXT (context), NULL);
220   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
221 
222   if (FO_IS_ENUM (datatype))
223     {
224       FoEnumEnum value = fo_enum_get_value (datatype);
225 
226       if ((value == FO_ENUM_ENUM_0) ||
227           (value == FO_ENUM_ENUM_90) ||
228           (value == FO_ENUM_ENUM_180) ||
229           (value == FO_ENUM_ENUM_270) ||
230           (value == FO_ENUM_ENUM__90) ||
231           (value == FO_ENUM_ENUM__180) ||
232           (value == FO_ENUM_ENUM__270))
233 	{
234 	  return datatype;
235 	}
236       else
237 	{
238 	  gchar *datatype_sprintf = fo_object_sprintf (datatype);
239 
240 	  g_set_error (error,
241 		       FO_FO_ERROR,
242 		       FO_FO_ERROR_ENUMERATION_TOKEN,
243 		       _(fo_fo_error_messages[FO_FO_ERROR_ENUMERATION_TOKEN]),
244 		       class_name,
245 		       datatype_sprintf,
246 		       g_type_name (G_TYPE_FROM_INSTANCE (datatype)));
247 
248 	  g_object_unref (datatype);
249 
250 	  g_free (datatype_sprintf);
251 
252 	  return NULL;
253 	}
254     }
255   else if (FO_IS_STRING (datatype))
256     {
257       token = fo_string_get_value (datatype);
258 
259       new_datatype =
260         _resolve_enum (token, context, &tmp_error);
261 
262       g_object_unref (datatype);
263 
264       fo_propagate_and_return_val_if_error (error, tmp_error, NULL);
265 
266       return new_datatype;
267     }
268   else if (FO_IS_NAME (datatype))
269     {
270       token = fo_name_get_value (datatype);
271 
272       new_datatype =
273         _resolve_enum (token, context, &tmp_error);
274 
275       g_object_unref (datatype);
276 
277       fo_propagate_and_return_val_if_error (error, tmp_error, NULL);
278 
279       return new_datatype;
280     }
281   else if (FO_IS_NUMBER (datatype))
282     {
283       gfloat float_value = fo_number_get_value (datatype);
284 
285       if ((float_value == 0) || (float_value == 90) ||
286 	  (float_value == 180) || (float_value == 270) ||
287 	  (float_value == -90) || (float_value == -180) ||
288 	  (float_value == -270))
289 	{
290 	  new_datatype = fo_integer_new_with_value ((int) float_value);
291 	  g_object_unref (datatype);
292 
293 	  return new_datatype;
294 	}
295       else
296 	{
297 	  gchar *datatype_sprintf = fo_object_sprintf (datatype);
298 
299 	  g_set_error (error,
300 		       FO_FO_ERROR,
301 		       FO_FO_ERROR_DATATYPE,
302 		       _(fo_fo_error_messages[FO_FO_ERROR_DATATYPE]),
303 		       class_name,
304 		       datatype_sprintf,
305 		       g_type_name (G_TYPE_FROM_INSTANCE (datatype)));
306 
307 	  g_object_unref (datatype);
308 
309 	  g_free (datatype_sprintf);
310 
311 	  return NULL;
312 	}
313     }
314   else if (FO_IS_INTEGER (datatype))
315     {
316       gint int_value = fo_integer_get_value (datatype);
317 
318       if ((int_value == 0) || (int_value == 90) ||
319 	  (int_value == 180) || (int_value == 270) ||
320 	  (int_value == -90) || (int_value == -180) ||
321 	  (int_value == -270))
322 	{
323 	  return datatype;
324 	}
325       else
326 	{
327 	  gchar *datatype_sprintf = fo_object_sprintf (datatype);
328 
329 	  g_set_error (error,
330 		       FO_FO_ERROR,
331 		       FO_FO_ERROR_DATATYPE,
332 		       _(fo_fo_error_messages[FO_FO_ERROR_DATATYPE]),
333 		       class_name,
334 		       datatype_sprintf,
335 		       g_type_name (G_TYPE_FROM_INSTANCE (datatype)));
336 
337 	  g_object_unref (datatype);
338 
339 	  g_free (datatype_sprintf);
340 
341 	  return NULL;
342 	}
343     }
344   else
345     {
346       gchar *datatype_sprintf = fo_object_sprintf (datatype);
347 
348       g_set_error (error,
349 		   FO_FO_ERROR,
350 		   FO_FO_ERROR_DATATYPE,
351 		   _(fo_fo_error_messages[FO_FO_ERROR_DATATYPE]),
352 		   class_name,
353 		   datatype_sprintf,
354 		   g_type_name (G_TYPE_FROM_INSTANCE (datatype)));
355 
356       g_object_unref (datatype);
357 
358       g_free (datatype_sprintf);
359 
360       return NULL;
361     }
362 }
363 
364 /**
365  * fo_property_reference_orientation_get_initial:
366  *
367  * Get an instance of the property with the correct initial value.
368  *
369  * Return value: An instance of the property.
370  **/
371 FoProperty*
fo_property_reference_orientation_get_initial(void)372 fo_property_reference_orientation_get_initial (void)
373 {
374   static FoProperty *reference_orientation = NULL;
375 
376   if (reference_orientation == NULL)
377     {
378       reference_orientation =
379 	fo_property_reference_orientation_new ();
380     }
381 
382   return reference_orientation;
383 }
384