1 /* Fo
2  * fo-property-baseline-shift.c: 'baseline-shift' 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 #include "property/fo-property-text-property.h"
16 #include "property/fo-property-font-size.h"
17 #include "property/fo-property-baseline-shift.h"
18 
19 /* baseline-shift */
20 /* Inherited: FALSE */
21 /* Shorthand: FALSE */
22 /* baseline | sub | super | <percentage> | <length> | inherit */
23 /* Initial value: baseline */
24 
25 struct _FoPropertyBaselineShift
26 {
27   FoProperty parent_instance;
28 };
29 
30 struct _FoPropertyBaselineShiftClass
31 {
32   FoPropertyClass parent_class;
33 };
34 
35 static void fo_property_baseline_shift_init         (FoPropertyBaselineShift      *property_baseline_shift);
36 static void fo_property_baseline_shift_class_init   (FoPropertyBaselineShiftClass *klass);
37 static void fo_property_baseline_shift_finalize     (GObject       *object);
38 static void fo_property_baseline_shift_text_property_init (FoPropertyTextPropertyIface *iface);
39 
40 static FoDatatype* fo_property_baseline_shift_resolve_enum (const gchar *token,
41                                                             FoContext   *context,
42                                                             GError     **error);
43 static FoDatatype* fo_property_baseline_shift_validate (FoDatatype *datatype,
44                                                         FoContext  *context,
45                                                         GError    **error);
46 static PangoAttribute * fo_property_baseline_shift_new_attr (FoProperty *property);
47 
48 static const gchar class_name[] = "baseline-shift";
49 static gpointer parent_class;
50 
51 /**
52  * fo_property_baseline_shift_get_type:
53  *
54  * Register the #FoPropertyBaselineShift type if not already registered and
55  * return its #GType value.
56  *
57  * Return value: #GType of #FoPropertyBaselineShift.
58  **/
59 GType
fo_property_baseline_shift_get_type(void)60 fo_property_baseline_shift_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 (FoPropertyBaselineShiftClass),
69         NULL,           /* base_init */
70         NULL,           /* base_finalize */
71         (GClassInitFunc) fo_property_baseline_shift_class_init,
72         NULL,           /* class_finalize */
73         NULL,           /* class_data */
74         sizeof (FoPropertyBaselineShift),
75         0,              /* n_preallocs */
76         (GInstanceInitFunc) fo_property_baseline_shift_init,
77 	NULL		/* value_table */
78       };
79 
80       static const GInterfaceInfo fo_property_text_property_info =
81       {
82 	(GInterfaceInitFunc) fo_property_baseline_shift_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_baseline_shift_init:
101  * @baseline_shift: #FoPropertyBaselineShift object to initialise.
102  *
103  * Implements #GInstanceInitFunc for #FoPropertyBaselineShift.
104  **/
105 void
fo_property_baseline_shift_init(FoPropertyBaselineShift * baseline_shift)106 fo_property_baseline_shift_init (FoPropertyBaselineShift *baseline_shift)
107 {
108   FO_PROPERTY (baseline_shift)->value =
109     g_object_ref (fo_length_get_length_zero ());
110 }
111 
112 /**
113  * fo_property_baseline_shift_class_init:
114  * @klass: #FoPropertyBaselineShiftClass object to initialise.
115  *
116  * Implements #GClassInitFunc for #FoPropertyBaselineShiftClass.
117  **/
118 void
fo_property_baseline_shift_class_init(FoPropertyBaselineShiftClass * klass)119 fo_property_baseline_shift_class_init (FoPropertyBaselineShiftClass *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_baseline_shift_finalize;
127 
128   property_class->is_inherited = FALSE;
129   property_class->is_shorthand = FALSE;
130   property_class->resolve_enum =
131     fo_property_baseline_shift_resolve_enum;
132   property_class->validate =
133     fo_property_baseline_shift_validate;
134   property_class->get_initial =
135     fo_property_baseline_shift_get_initial;
136 }
137 
138 /**
139  * fo_property_baseline_shift_finalize:
140  * @object: #FoPropertyBaselineShift object to finalize.
141  *
142  * Implements #GObjectFinalizeFunc for #FoPropertyBaselineShift.
143  **/
144 void
fo_property_baseline_shift_finalize(GObject * object)145 fo_property_baseline_shift_finalize (GObject *object)
146 {
147   FoPropertyBaselineShift *baseline_shift;
148 
149   baseline_shift = FO_PROPERTY_BASELINE_SHIFT (object);
150 
151   G_OBJECT_CLASS (parent_class)->finalize (object);
152 }
153 
154 /**
155  * fo_property_baseline_shift_text_property_init:
156  * @iface: #FoPropertyTextPropertyIFace structure for this class.
157  *
158  * Initialize #FoPropertyTextPropertyIface interface for this class.
159  **/
160 void
fo_property_baseline_shift_text_property_init(FoPropertyTextPropertyIface * iface)161 fo_property_baseline_shift_text_property_init (FoPropertyTextPropertyIface *iface)
162 {
163   iface->new_attr = fo_property_baseline_shift_new_attr;
164 }
165 
166 /**
167  * fo_property_baseline_shift_new:
168  *
169  * Creates a new #FoPropertyBaselineShift initialized to default value.
170  *
171  * Return value: the new #FoPropertyBaselineShift.
172  **/
173 FoProperty*
fo_property_baseline_shift_new(void)174 fo_property_baseline_shift_new (void)
175 {
176   FoProperty* baseline_shift;
177 
178   baseline_shift =
179     FO_PROPERTY (g_object_new (fo_property_baseline_shift_get_type (),
180                                NULL));
181 
182   return baseline_shift;
183 }
184 
185 /**
186  * fo_property_baseline_shift_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_baseline_shift_resolve_enum(const gchar * token,FoContext * context,GError ** error)201 fo_property_baseline_shift_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, "baseline") == 0)
210     {
211       return g_object_ref (fo_length_get_length_zero ());
212     }
213   else if (strcmp (token, "sub") == 0)
214     {
215       return g_object_ref (fo_length_get_length_minus_3pt ());
216     }
217   else if (strcmp (token, "super") == 0)
218     {
219       return g_object_ref (fo_length_get_length_3pt ());
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_baseline_shift_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_baseline_shift_validate(FoDatatype * datatype,FoContext * context,GError ** error)246 fo_property_baseline_shift_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_BASELINE) ||
265           (value == FO_ENUM_ENUM_SUB) ||
266           (value == FO_ENUM_ENUM_SUPER))
267 	{
268 	  return datatype;
269 	}
270       else
271 	{
272 	  gchar *datatype_sprintf = fo_object_sprintf (datatype);
273 
274 	  g_set_error (error,
275 		       FO_FO_ERROR,
276 		       FO_FO_ERROR_ENUMERATION_TOKEN,
277 		       _(fo_fo_error_messages[FO_FO_ERROR_ENUMERATION_TOKEN]),
278 		       class_name,
279 		       datatype_sprintf,
280 		       g_type_name (G_TYPE_FROM_INSTANCE (datatype)));
281 
282 	  g_object_unref (datatype);
283 
284 	  g_free (datatype_sprintf);
285 
286 	  return NULL;
287 	}
288     }
289   else if (FO_IS_STRING (datatype))
290     {
291       token = fo_string_get_value (datatype);
292 
293       new_datatype =
294         fo_property_baseline_shift_resolve_enum (token, context, &tmp_error);
295 
296       g_object_unref (datatype);
297 
298       fo_propagate_and_return_val_if_error (error, tmp_error, NULL);
299 
300       return new_datatype;
301     }
302   else if (FO_IS_NAME (datatype))
303     {
304       token = fo_name_get_value (datatype);
305 
306       new_datatype =
307         fo_property_baseline_shift_resolve_enum (token, context, &tmp_error);
308 
309       g_object_unref (datatype);
310 
311       fo_propagate_and_return_val_if_error (error, tmp_error, NULL);
312 
313       return new_datatype;
314     }
315   else if (FO_IS_PERCENTAGE (datatype))
316     {
317       return datatype;
318     }
319   else if (FO_IS_LENGTH (datatype))
320     {
321       return datatype;
322     }
323   else
324     {
325       gchar *datatype_sprintf = fo_object_sprintf (datatype);
326 
327       g_set_error (error,
328 		   FO_FO_ERROR,
329 		   FO_FO_ERROR_DATATYPE,
330 		   _(fo_fo_error_messages[FO_FO_ERROR_DATATYPE]),
331 		   class_name,
332 		   datatype_sprintf,
333 		   g_type_name (G_TYPE_FROM_INSTANCE (datatype)));
334 
335       g_object_unref (datatype);
336 
337       g_free (datatype_sprintf);
338 
339       return NULL;
340     }
341 }
342 
343 /**
344  * fo_property_baseline_shift_get_initial:
345  *
346  * Get an instance of the property with the correct initial value.
347  *
348  * Return value: An instance of the property.
349  **/
350 FoProperty*
fo_property_baseline_shift_get_initial(void)351 fo_property_baseline_shift_get_initial (void)
352 {
353   static FoProperty *baseline_shift = NULL;
354 
355   if (baseline_shift == NULL)
356     {
357       baseline_shift =
358 	fo_property_baseline_shift_new ();
359     }
360 
361   return baseline_shift;
362 }
363 
364 /**
365  * fo_property_baseline_shift_new_attr:
366  * @property: Property from which to create a PangoAttribute
367  *
368  * Makes a new PangoAttribute representing the current property
369  *
370  * Return value: New PangoAttribute
371  **/
372 PangoAttribute*
fo_property_baseline_shift_new_attr(FoProperty * property)373 fo_property_baseline_shift_new_attr (FoProperty *property)
374 {
375   gint pango_baseline_shift;
376 
377   g_return_val_if_fail (FO_IS_PROPERTY_BASELINE_SHIFT (property), NULL);
378 
379   pango_baseline_shift =
380     (int) (fo_length_get_value (property->value) *
381 	   PANGO_SCALE);
382 
383   return pango_attr_rise_new (pango_baseline_shift);
384 }
385