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