1 #define __SP_FONTFACE_C__
3 /*
4 * SVG <font-face> element implementation
5 *
6 * Section 20.8.3 of the W3C SVG 1.1 spec
7 * available at:
8 * http://www.w3.org/TR/SVG/fonts.html#FontFaceElement
9 *
10 * Author:
11 * Felipe C. da S. Sanches <felipe.sanches@gmail.com>
12 *
13 * Copyright (C) 2008, Felipe C. da S. Sanches
14 *
15 * Released under GNU GPL, read the file 'COPYING' for more information
16 */
18 #include "xml/repr.h"
19 #include "attributes.h"
20 #include "sp-font-face.h"
21 #include "document.h"
22 #include "helper-fns.h"
24 class ObjectContainer
25 {
27 public:
28 ObjectContainer(double def){
29 this->isset = false;
30 this->default_value = def;
31 }
33 double get(){
34 if (this->isset)
35 return this->obj;
36 else
37 return this->default_value;
38 }
40 void set(double val){
41 this->obj = val;
42 this->isset = true;
43 }
45 void unset(){
46 this->isset = false;
47 }
49 private:
50 double obj;
51 double default_value;
52 bool isset;
53 };
55 static void sp_fontface_class_init(SPFontFaceClass *fc);
56 static void sp_fontface_init(SPFontFace *font);
58 static void sp_fontface_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr);
59 static void sp_fontface_release(SPObject *object);
60 static void sp_fontface_set(SPObject *object, unsigned int key, const gchar *value);
61 static Inkscape::XML::Node *sp_fontface_write(SPObject *object, Inkscape::XML::Node *repr, guint flags);
63 static void sp_fontface_child_added(SPObject *object, Inkscape::XML::Node *child, Inkscape::XML::Node *ref);
64 static void sp_fontface_remove_child(SPObject *object, Inkscape::XML::Node *child);
65 static void sp_fontface_update(SPObject *object, SPCtx *ctx, guint flags);
67 static SPObjectClass *parent_class;
69 GType sp_fontface_get_type(void)
70 {
71 static GType type = 0;
73 if (!type) {
74 GTypeInfo info = {
75 sizeof(SPFontFaceClass),
76 NULL, /* base_init */
77 NULL, /* base_finalize */
78 (GClassInitFunc) sp_fontface_class_init,
79 NULL, /* class_finalize */
80 NULL, /* class_data */
81 sizeof(SPFontFace),
82 16, /* n_preallocs */
83 (GInstanceInitFunc) sp_fontface_init,
84 NULL, /* value_table */
85 };
86 type = g_type_register_static(SP_TYPE_OBJECT, "SPFontFace", &info, (GTypeFlags) 0);
87 }
89 return type;
90 }
92 static void sp_fontface_class_init(SPFontFaceClass *fc)
93 {
94 SPObjectClass *sp_object_class = (SPObjectClass *) fc;
96 parent_class = (SPObjectClass *) g_type_class_ref(SP_TYPE_OBJECT);
98 sp_object_class->build = sp_fontface_build;
99 sp_object_class->release = sp_fontface_release;
100 sp_object_class->set = sp_fontface_set;
101 sp_object_class->write = sp_fontface_write;
102 sp_object_class->child_added = sp_fontface_child_added;
103 sp_object_class->remove_child = sp_fontface_remove_child;
104 sp_object_class->update = sp_fontface_update;
105 }
107 static void sp_fontface_init(SPFontFace *face)
108 {
109 /*
110 //face->unicode_range = ;
111 face->units_per_em = 1000;
112 //face->panose_1 = ;
113 face->stem_v = ;
114 face->stem_h = ;
115 face->slope = 0;
116 face->cap_height = ;
117 face->x_height = ;
118 face->accent_height = ;
119 face->ascent = ;
120 face->descent = ;
121 face->widths = NULL;
122 face->bbox = NULL;
123 face->ideographic = ;
124 face->alphabetic = ;
125 face->mathematical = ;
126 face->hanging = ;
127 face->v_ideographic = ;
128 face->v_alphabetic = ;
129 face->v_mathematical = ;
130 face->v_hanging = ;
131 face->underline_position = ;
132 face->underline_thickness = ;
133 face->strikethrough_position = ;
134 face->strikethrough_thickness = ;
135 face->overline_position = ;
136 face->overline_thickness = ;
137 */
138 }
140 static void sp_fontface_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr)
141 {
142 if (((SPObjectClass *) (parent_class))->build) {
143 ((SPObjectClass *) (parent_class))->build(object, document, repr);
144 }
146 sp_object_read_attr(object, "unicode-range");
147 sp_object_read_attr(object, "units-per-em");
148 sp_object_read_attr(object, "panose-1");
149 sp_object_read_attr(object, "stem-v");
150 sp_object_read_attr(object, "stem-h");
151 sp_object_read_attr(object, "slope");
152 sp_object_read_attr(object, "cap-height");
153 sp_object_read_attr(object, "x-height");
154 sp_object_read_attr(object, "accent-height");
155 sp_object_read_attr(object, "ascent");
156 sp_object_read_attr(object, "descent");
157 sp_object_read_attr(object, "widths");
158 sp_object_read_attr(object, "bbox");
159 sp_object_read_attr(object, "ideographic");
160 sp_object_read_attr(object, "alphabetic");
161 sp_object_read_attr(object, "mathematical");
162 sp_object_read_attr(object, "ranging");
163 sp_object_read_attr(object, "v-ideogaphic");
164 sp_object_read_attr(object, "v-alphabetic");
165 sp_object_read_attr(object, "v-mathematical");
166 sp_object_read_attr(object, "v-hanging");
167 sp_object_read_attr(object, "underline-position");
168 sp_object_read_attr(object, "underline-thickness");
169 sp_object_read_attr(object, "strikethrough-position");
170 sp_object_read_attr(object, "strikethrough-thickness");
171 sp_object_read_attr(object, "overline-position");
172 sp_object_read_attr(object, "overline-thickness");
173 }
175 static void sp_fontface_children_modified(SPFontFace *sp_fontface)
176 {
177 }
179 /**
180 * Callback for child_added event.
181 */
182 static void
183 sp_fontface_child_added(SPObject *object, Inkscape::XML::Node *child, Inkscape::XML::Node *ref)
184 {
185 SPFontFace *f = SP_FONTFACE(object);
187 if (((SPObjectClass *) parent_class)->child_added)
188 (* ((SPObjectClass *) parent_class)->child_added)(object, child, ref);
190 sp_fontface_children_modified(f);
191 object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
192 }
195 /**
196 * Callback for remove_child event.
197 */
198 static void
199 sp_fontface_remove_child(SPObject *object, Inkscape::XML::Node *child)
200 {
201 SPFontFace *f = SP_FONTFACE(object);
203 if (((SPObjectClass *) parent_class)->remove_child)
204 (* ((SPObjectClass *) parent_class)->remove_child)(object, child);
206 sp_fontface_children_modified(f);
207 object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
208 }
210 static void sp_fontface_release(SPObject *object)
211 {
212 //SPFontFace *font = SP_FONTFACE(object);
214 if (((SPObjectClass *) parent_class)->release) {
215 ((SPObjectClass *) parent_class)->release(object);
216 }
217 }
219 static void sp_fontface_set(SPObject *object, unsigned int key, const gchar *value)
220 {
221 SPFontFace *face = SP_FONTFACE(object);
222 double number;
224 switch (key) {
225 case SP_ATTR_UNITS_PER_EM:
226 number = helperfns_read_number(value);
227 if (number != face->units_per_em){
228 face->units_per_em = number;
229 g_warning("<font-face>: SP_ATTR_UNITS_PER_EM: %f", number);
230 object->requestModified(SP_OBJECT_MODIFIED_FLAG);
231 }
232 break;
233 case SP_ATTR_STEMV:
234 number = helperfns_read_number(value);
235 if (number != face->stemv){
236 face->stemv = number;
237 g_warning("<font-face>: SP_ATTR_STEMV: %f", number);
238 object->requestModified(SP_OBJECT_MODIFIED_FLAG);
239 }
240 break;
241 case SP_ATTR_STEMH:
242 number = helperfns_read_number(value);
243 if (number != face->stemh){
244 face->stemh = number;
245 g_warning("<font-face>: SP_ATTR_STEMH: %f", number);
246 object->requestModified(SP_OBJECT_MODIFIED_FLAG);
247 }
248 break;
249 case SP_ATTR_SLOPE:
250 number = helperfns_read_number(value);
251 if (number != face->slope){
252 face->slope = number;
253 g_warning("<font-face>: SP_ATTR_SLOPE: %f", number);
254 object->requestModified(SP_OBJECT_MODIFIED_FLAG);
255 }
256 break;
257 case SP_ATTR_CAP_HEIGHT:
258 number = helperfns_read_number(value);
259 if (number != face->cap_height){
260 face->cap_height = number;
261 g_warning("<font-face>: SP_ATTR_CAP_HEIGHT: %f", number);
262 object->requestModified(SP_OBJECT_MODIFIED_FLAG);
263 }
264 break;
265 case SP_ATTR_X_HEIGHT:
266 number = helperfns_read_number(value);
267 if (number != face->x_height){
268 face->x_height = number;
269 g_warning("<font-face>: SP_ATTR_X_HEIGHT: %f", number);
270 object->requestModified(SP_OBJECT_MODIFIED_FLAG);
271 }
272 break;
273 case SP_ATTR_ACCENT_HEIGHT:
274 number = helperfns_read_number(value);
275 if (number != face->accent_height){
276 face->accent_height = number;
277 g_warning("<font-face>: SP_ATTR_ACCENT_HEIGHT: %f", number);
278 object->requestModified(SP_OBJECT_MODIFIED_FLAG);
279 }
280 break;
281 case SP_ATTR_ASCENT:
282 number = helperfns_read_number(value);
283 if (number != face->ascent){
284 face->ascent = number;
285 g_warning("<font-face>: SP_ATTR_ASCENT: %f", number);
286 object->requestModified(SP_OBJECT_MODIFIED_FLAG);
287 }
288 break;
289 case SP_ATTR_DESCENT:
290 number = helperfns_read_number(value);
291 if (number != face->descent){
292 face->descent = number;
293 g_warning("<font-face>: SP_ATTR_DESCENT: %f", number);
294 object->requestModified(SP_OBJECT_MODIFIED_FLAG);
295 }
296 break;
297 case SP_ATTR_IDEOGRAPHIC:
298 number = helperfns_read_number(value);
299 if (number != face->ideographic){
300 face->ideographic = number;
301 g_warning("<font-face>: SP_ATTR_IDEOGRAPHIC: %f", number);
302 object->requestModified(SP_OBJECT_MODIFIED_FLAG);
303 }
304 break;
305 case SP_ATTR_ALPHABETIC:
306 number = helperfns_read_number(value);
307 if (number != face->alphabetic){
308 face->alphabetic = number;
309 g_warning("<font-face>: SP_ATTR_ALPHABETIC: %f", number);
310 object->requestModified(SP_OBJECT_MODIFIED_FLAG);
311 }
312 break;
313 case SP_ATTR_MATHEMATICAL:
314 number = helperfns_read_number(value);
315 if (number != face->mathematical){
316 face->mathematical = number;
317 g_warning("<font-face>: SP_ATTR_MATHEMATICAL: %f", number);
318 object->requestModified(SP_OBJECT_MODIFIED_FLAG);
319 }
320 break;
321 case SP_ATTR_HANGING:
322 number = helperfns_read_number(value);
323 if (number != face->hanging){
324 face->hanging = number;
325 g_warning("<font-face>: SP_ATTR_HANGING: %f", number);
326 object->requestModified(SP_OBJECT_MODIFIED_FLAG);
327 }
328 break;
329 case SP_ATTR_V_IDEOGRAPHIC:
330 number = helperfns_read_number(value);
331 if (number != face->v_ideographic){
332 face->v_ideographic = number;
333 g_warning("<font-face>: SP_ATTR_V_IDEOGRAPHIC: %f", number);
334 object->requestModified(SP_OBJECT_MODIFIED_FLAG);
335 }
336 break;
337 case SP_ATTR_V_ALPHABETIC:
338 number = helperfns_read_number(value);
339 if (number != face->v_alphabetic){
340 face->v_alphabetic = number;
341 g_warning("<font-face>: SP_ATTR_V_ALPHABETIC: %f", number);
342 object->requestModified(SP_OBJECT_MODIFIED_FLAG);
343 }
344 break;
345 case SP_ATTR_V_MATHEMATICAL:
346 number = helperfns_read_number(value);
347 if (number != face->v_mathematical){
348 face->v_mathematical = number;
349 g_warning("<font-face>: SP_ATTR_V_MATHEMATICAL: %f", number);
350 object->requestModified(SP_OBJECT_MODIFIED_FLAG);
351 }
352 break;
353 case SP_ATTR_V_HANGING:
354 number = helperfns_read_number(value);
355 if (number != face->v_hanging){
356 face->v_hanging = number;
357 g_warning("<font-face>: SP_ATTR_V_HANGING: %f", number);
358 object->requestModified(SP_OBJECT_MODIFIED_FLAG);
359 }
360 break;
361 case SP_ATTR_UNDERLINE_POSITION:
362 number = helperfns_read_number(value);
363 if (number != face->underline_position){
364 face->underline_position = number;
365 g_warning("<font-face>: SP_ATTR_UNDERLINE_POSITION: %f", number);
366 object->requestModified(SP_OBJECT_MODIFIED_FLAG);
367 }
368 break;
369 case SP_ATTR_UNDERLINE_THICKNESS:
370 number = helperfns_read_number(value);
371 if (number != face->underline_thickness){
372 face->underline_thickness = number;
373 g_warning("<font-face>: SP_ATTR_UNDERLINE_THICKNESS: %f", number);
374 object->requestModified(SP_OBJECT_MODIFIED_FLAG);
375 }
376 break;
377 case SP_ATTR_STRIKETHROUGH_POSITION:
378 number = helperfns_read_number(value);
379 if (number != face->strikethrough_position){
380 face->strikethrough_position = number;
381 g_warning("<font-face>: SP_ATTR_STRIKETHROUGH_POSITION: %f", number);
382 object->requestModified(SP_OBJECT_MODIFIED_FLAG);
383 }
384 break;
385 case SP_ATTR_STRIKETHROUGH_THICKNESS:
386 number = helperfns_read_number(value);
387 if (number != face->strikethrough_thickness){
388 face->strikethrough_thickness = number;
389 g_warning("<font-face>: SP_ATTR_STRIKETHROUGH_THICKNESS: %f", number);
390 object->requestModified(SP_OBJECT_MODIFIED_FLAG);
391 }
392 break;
393 case SP_ATTR_OVERLINE_POSITION:
394 number = helperfns_read_number(value);
395 if (number != face->overline_position){
396 face->overline_position = number;
397 g_warning("<font-face>: SP_ATTR_OVERLINE_POSITION: %f", number);
398 object->requestModified(SP_OBJECT_MODIFIED_FLAG);
399 }
400 break;
401 case SP_ATTR_OVERLINE_THICKNESS:
402 number = helperfns_read_number(value);
403 if (number != face->overline_thickness){
404 face->overline_thickness = number;
405 g_warning("<font-face>: SP_ATTR_OVERLINE_THICKNESS: %f", number);
406 object->requestModified(SP_OBJECT_MODIFIED_FLAG);
407 }
408 break;
409 default:
410 if (((SPObjectClass *) (parent_class))->set) {
411 ((SPObjectClass *) (parent_class))->set(object, key, value);
412 }
413 break;
414 }
415 }
417 /**
418 * Receives update notifications.
419 */
420 static void
421 sp_fontface_update(SPObject *object, SPCtx *ctx, guint flags)
422 {
423 if (flags & (SP_OBJECT_MODIFIED_FLAG)) {
424 sp_object_read_attr(object, "unicode-range");
425 sp_object_read_attr(object, "units-per-em");
426 sp_object_read_attr(object, "panose-1");
427 sp_object_read_attr(object, "stemv");
428 sp_object_read_attr(object, "stemh");
429 sp_object_read_attr(object, "slope");
430 sp_object_read_attr(object, "cap-height");
431 sp_object_read_attr(object, "x-height");
432 sp_object_read_attr(object, "accent-height");
433 sp_object_read_attr(object, "ascent");
434 sp_object_read_attr(object, "descent");
435 sp_object_read_attr(object, "widths");
436 sp_object_read_attr(object, "bbox");
437 sp_object_read_attr(object, "ideographic");
438 sp_object_read_attr(object, "alphabetic");
439 sp_object_read_attr(object, "mathematical");
440 sp_object_read_attr(object, "hanging");
441 sp_object_read_attr(object, "v-ideographic");
442 sp_object_read_attr(object, "v-alphabetic");
443 sp_object_read_attr(object, "v-mathematical");
444 sp_object_read_attr(object, "v-hanging");
445 sp_object_read_attr(object, "underline-position");
446 sp_object_read_attr(object, "underline-thickness");
447 sp_object_read_attr(object, "strikethrough-position");
448 sp_object_read_attr(object, "strikethrough-thickness");
449 sp_object_read_attr(object, "overline-position");
450 sp_object_read_attr(object, "overline-thickness");
451 }
453 if (((SPObjectClass *) parent_class)->update) {
454 ((SPObjectClass *) parent_class)->update(object, ctx, flags);
455 }
456 }
458 #define COPY_ATTR(rd,rs,key) (rd)->setAttribute((key), rs->attribute(key));
460 static Inkscape::XML::Node *sp_fontface_write(SPObject *object, Inkscape::XML::Node *repr, guint flags)
461 {
462 SPFontFace *face = SP_FONTFACE(object);
464 if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) {
465 Inkscape::XML::Document *xml_doc = sp_document_repr_doc(SP_OBJECT_DOCUMENT(object));
466 repr = xml_doc->createElement("svg:font-face");
467 }
469 //TODO:
470 //sp_repr_set_svg_double(repr, "unicode-range", face->unicode_range);
471 sp_repr_set_svg_double(repr, "units-per-em", face->units_per_em);
472 //sp_repr_set_svg_double(repr, "panose-1", face->panose_1);
473 sp_repr_set_svg_double(repr, "stemv", face->stemv);
474 sp_repr_set_svg_double(repr, "stemh", face->stemh);
475 sp_repr_set_svg_double(repr, "slope", face->slope);
476 sp_repr_set_svg_double(repr, "cap-height", face->cap_height);
477 sp_repr_set_svg_double(repr, "x-height", face->x_height);
478 sp_repr_set_svg_double(repr, "accent-height", face->accent_height);
479 sp_repr_set_svg_double(repr, "ascent", face->ascent);
480 sp_repr_set_svg_double(repr, "descent", face->descent);
481 //sp_repr_set_svg_double(repr, "widths", face->widths);
482 //sp_repr_set_svg_double(repr, "bbox", face->bbox);
483 sp_repr_set_svg_double(repr, "ideographic", face->ideographic);
484 sp_repr_set_svg_double(repr, "alphabetic", face->alphabetic);
485 sp_repr_set_svg_double(repr, "mathematical", face->mathematical);
486 sp_repr_set_svg_double(repr, "hanging", face->hanging);
487 sp_repr_set_svg_double(repr, "v-ideographic", face->v_ideographic);
488 sp_repr_set_svg_double(repr, "v-alphabetic", face->v_alphabetic);
489 sp_repr_set_svg_double(repr, "v-mathematical", face->v_mathematical);
490 sp_repr_set_svg_double(repr, "v-hanging", face->v_hanging);
491 sp_repr_set_svg_double(repr, "underline-position", face->underline_position);
492 sp_repr_set_svg_double(repr, "underline-thickness", face->underline_thickness);
493 sp_repr_set_svg_double(repr, "strikethrough-position", face->strikethrough_position);
494 sp_repr_set_svg_double(repr, "strikethrough-thickness", face->strikethrough_thickness);
495 sp_repr_set_svg_double(repr, "overline-position", face->overline_position);
496 sp_repr_set_svg_double(repr, "overline-thickness", face->overline_thickness);
498 if (repr != SP_OBJECT_REPR(object)) {
499 COPY_ATTR(repr, object->repr, "unicode-range");
500 COPY_ATTR(repr, object->repr, "units-per-em");
501 COPY_ATTR(repr, object->repr, "panose-1");
502 COPY_ATTR(repr, object->repr, "stemv");
503 COPY_ATTR(repr, object->repr, "stemh");
504 COPY_ATTR(repr, object->repr, "slope");
505 COPY_ATTR(repr, object->repr, "cap-height");
506 COPY_ATTR(repr, object->repr, "x-height");
507 COPY_ATTR(repr, object->repr, "accent-height");
508 COPY_ATTR(repr, object->repr, "ascent");
509 COPY_ATTR(repr, object->repr, "descent");
510 COPY_ATTR(repr, object->repr, "widths");
511 COPY_ATTR(repr, object->repr, "bbox");
512 COPY_ATTR(repr, object->repr, "ideographic");
513 COPY_ATTR(repr, object->repr, "alphabetic");
514 COPY_ATTR(repr, object->repr, "mathematical");
515 COPY_ATTR(repr, object->repr, "hanging");
516 COPY_ATTR(repr, object->repr, "v-ideographic");
517 COPY_ATTR(repr, object->repr, "v-alphabetic");
518 COPY_ATTR(repr, object->repr, "v-mathematical");
519 COPY_ATTR(repr, object->repr, "v-hanging");
520 COPY_ATTR(repr, object->repr, "underline-position");
521 COPY_ATTR(repr, object->repr, "underline-thickness");
522 COPY_ATTR(repr, object->repr, "strikethrough-position");
523 COPY_ATTR(repr, object->repr, "strikethrough-thickness");
524 COPY_ATTR(repr, object->repr, "overline-position");
525 COPY_ATTR(repr, object->repr, "overline-thickness");
526 }
528 if (((SPObjectClass *) (parent_class))->write) {
529 ((SPObjectClass *) (parent_class))->write(object, repr, flags);
530 }
532 return repr;
533 }
535 /*
536 Local Variables:
537 mode:c++
538 c-file-style:"stroustrup"
539 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
540 indent-tabs-mode:nil
541 fill-column:99
542 End:
543 */
544 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :