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