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