1 #ifdef HAVE_CONFIG_H
2 # include <config.h>
3 #endif
5 #ifdef ENABLE_SVG_FONTS
6 #define __SP_GLYPH_C__
8 /*
9 * SVG <glyph> element implementation
10 *
11 * Author:
12 * Felipe C. da S. Sanches <juca@members.fsf.org>
13 * Abhishek Sharma
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-glyph.h"
23 #include "document.h"
25 static void sp_glyph_class_init(SPGlyphClass *gc);
26 static void sp_glyph_init(SPGlyph *glyph);
28 static void sp_glyph_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr);
29 static void sp_glyph_release(SPObject *object);
30 static void sp_glyph_set(SPObject *object, unsigned int key, const gchar *value);
31 static Inkscape::XML::Node *sp_glyph_write(SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags);
32 static void sp_glyph_update(SPObject *object, SPCtx *ctx, guint flags);
34 static SPObjectClass *parent_class;
36 GType sp_glyph_get_type(void)
37 {
38 static GType type = 0;
40 if (!type) {
41 GTypeInfo info = {
42 sizeof(SPGlyphClass),
43 NULL, /* base_init */
44 NULL, /* base_finalize */
45 (GClassInitFunc) sp_glyph_class_init,
46 NULL, /* class_finalize */
47 NULL, /* class_data */
48 sizeof(SPGlyph),
49 16, /* n_preallocs */
50 (GInstanceInitFunc) sp_glyph_init,
51 NULL, /* value_table */
52 };
53 type = g_type_register_static(SP_TYPE_OBJECT, "SPGlyph", &info, (GTypeFlags) 0);
54 }
56 return type;
57 }
59 static void sp_glyph_class_init(SPGlyphClass *gc)
60 {
61 SPObjectClass *sp_object_class = (SPObjectClass *) gc;
63 parent_class = (SPObjectClass*)g_type_class_peek_parent(gc);
65 sp_object_class->build = sp_glyph_build;
66 sp_object_class->release = sp_glyph_release;
67 sp_object_class->set = sp_glyph_set;
68 sp_object_class->write = sp_glyph_write;
69 sp_object_class->update = sp_glyph_update;
70 }
72 static void sp_glyph_init(SPGlyph *glyph)
73 {
74 //TODO: correct these values:
76 new (&glyph->unicode) Glib::ustring();
77 new (&glyph->glyph_name) Glib::ustring();
78 glyph->d = NULL;
79 glyph->orientation = GLYPH_ORIENTATION_BOTH;
80 glyph->arabic_form = GLYPH_ARABIC_FORM_INITIAL;
81 glyph->lang = NULL;
82 glyph->horiz_adv_x = 0;
83 glyph->vert_origin_x = 0;
84 glyph->vert_origin_y = 0;
85 glyph->vert_adv_y = 0;
86 }
88 static void sp_glyph_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr)
89 {
90 if (((SPObjectClass *) (parent_class))->build) {
91 ((SPObjectClass *) (parent_class))->build(object, document, repr);
92 }
94 object->readAttr( "unicode" );
95 object->readAttr( "glyph-name" );
96 object->readAttr( "d" );
97 object->readAttr( "orientation" );
98 object->readAttr( "arabic-form" );
99 object->readAttr( "lang" );
100 object->readAttr( "horiz-adv-x" );
101 object->readAttr( "vert-origin-x" );
102 object->readAttr( "vert-origin-y" );
103 object->readAttr( "vert-adv-y" );
104 }
106 static void sp_glyph_release(SPObject *object)
107 {
108 //SPGlyph *glyph = SP_GLYPH(object);
110 if (((SPObjectClass *) parent_class)->release) {
111 ((SPObjectClass *) parent_class)->release(object);
112 }
113 }
115 static glyphArabicForm sp_glyph_read_arabic_form(gchar const *value){
116 if (!value) return GLYPH_ARABIC_FORM_INITIAL; //TODO: verify which is the default default (for me, the spec is not clear)
117 switch(value[0]){
118 case 'i':
119 if (strncmp(value, "initial", 7) == 0) return GLYPH_ARABIC_FORM_INITIAL;
120 if (strncmp(value, "isolated", 8) == 0) return GLYPH_ARABIC_FORM_ISOLATED;
121 break;
122 case 'm':
123 if (strncmp(value, "medial", 6) == 0) return GLYPH_ARABIC_FORM_MEDIAL;
124 break;
125 case 't':
126 if (strncmp(value, "terminal", 8) == 0) return GLYPH_ARABIC_FORM_TERMINAL;
127 break;
128 }
129 return GLYPH_ARABIC_FORM_INITIAL; //TODO: VERIFY DEFAULT!
130 }
132 static glyphOrientation sp_glyph_read_orientation(gchar const *value){
133 if (!value) return GLYPH_ORIENTATION_BOTH;
134 switch(value[0]){
135 case 'h':
136 return GLYPH_ORIENTATION_HORIZONTAL;
137 break;
138 case 'v':
139 return GLYPH_ORIENTATION_VERTICAL;
140 break;
141 }
142 //ERROR? TODO: VERIFY PROPER ERROR HANDLING
143 return GLYPH_ORIENTATION_BOTH;
144 }
146 static void sp_glyph_set(SPObject *object, unsigned int key, const gchar *value)
147 {
148 SPGlyph *glyph = SP_GLYPH(object);
150 switch (key) {
151 case SP_ATTR_UNICODE:
152 {
153 glyph->unicode.clear();
154 if (value) glyph->unicode.append(value);
155 object->requestModified(SP_OBJECT_MODIFIED_FLAG);
156 break;
157 }
158 case SP_ATTR_GLYPH_NAME:
159 {
160 glyph->glyph_name.clear();
161 if (value) glyph->glyph_name.append(value);
162 object->requestModified(SP_OBJECT_MODIFIED_FLAG);
163 break;
164 }
165 case SP_ATTR_D:
166 {
167 if (glyph->d) g_free(glyph->d);
168 glyph->d = g_strdup(value);
169 object->requestModified(SP_OBJECT_MODIFIED_FLAG);
170 break;
171 }
172 case SP_ATTR_ORIENTATION:
173 {
174 glyphOrientation orient = sp_glyph_read_orientation(value);
175 if (glyph->orientation != orient){
176 glyph->orientation = orient;
177 object->requestModified(SP_OBJECT_MODIFIED_FLAG);
178 }
179 break;
180 }
181 case SP_ATTR_ARABIC_FORM:
182 {
183 glyphArabicForm form = sp_glyph_read_arabic_form(value);
184 if (glyph->arabic_form != form){
185 glyph->arabic_form = form;
186 object->requestModified(SP_OBJECT_MODIFIED_FLAG);
187 }
188 break;
189 }
190 case SP_ATTR_LANG:
191 {
192 if (glyph->lang) g_free(glyph->lang);
193 glyph->lang = g_strdup(value);
194 object->requestModified(SP_OBJECT_MODIFIED_FLAG);
195 break;
196 }
197 case SP_ATTR_HORIZ_ADV_X:
198 {
199 double number = value ? g_ascii_strtod(value, 0) : 0;
200 if (number != glyph->horiz_adv_x){
201 glyph->horiz_adv_x = number;
202 object->requestModified(SP_OBJECT_MODIFIED_FLAG);
203 }
204 break;
205 }
206 case SP_ATTR_VERT_ORIGIN_X:
207 {
208 double number = value ? g_ascii_strtod(value, 0) : 0;
209 if (number != glyph->vert_origin_x){
210 glyph->vert_origin_x = number;
211 object->requestModified(SP_OBJECT_MODIFIED_FLAG);
212 }
213 break;
214 }
215 case SP_ATTR_VERT_ORIGIN_Y:
216 {
217 double number = value ? g_ascii_strtod(value, 0) : 0;
218 if (number != glyph->vert_origin_y){
219 glyph->vert_origin_y = number;
220 object->requestModified(SP_OBJECT_MODIFIED_FLAG);
221 }
222 break;
223 }
224 case SP_ATTR_VERT_ADV_Y:
225 {
226 double number = value ? g_ascii_strtod(value, 0) : 0;
227 if (number != glyph->vert_adv_y){
228 glyph->vert_adv_y = number;
229 object->requestModified(SP_OBJECT_MODIFIED_FLAG);
230 }
231 break;
232 }
233 default:
234 {
235 if (((SPObjectClass *) (parent_class))->set) {
236 ((SPObjectClass *) (parent_class))->set(object, key, value);
237 }
238 break;
239 }
240 }
241 }
243 /**
244 * * Receives update notifications.
245 * */
246 static void
247 sp_glyph_update(SPObject *object, SPCtx *ctx, guint flags)
248 {
249 SPGlyph *glyph = SP_GLYPH(object);
250 (void)glyph;
252 if (flags & SP_OBJECT_MODIFIED_FLAG) {
253 /* do something to trigger redisplay, updates? */
254 object->readAttr( "unicode" );
255 object->readAttr( "glyph-name" );
256 object->readAttr( "d" );
257 object->readAttr( "orientation" );
258 object->readAttr( "arabic-form" );
259 object->readAttr( "lang" );
260 object->readAttr( "horiz-adv-x" );
261 object->readAttr( "vert-origin-x" );
262 object->readAttr( "vert-origin-y" );
263 object->readAttr( "vert-adv-y" );
264 }
266 if (((SPObjectClass *) parent_class)->update) {
267 ((SPObjectClass *) parent_class)->update(object, ctx, flags);
268 }
269 }
271 #define COPY_ATTR(rd,rs,key) (rd)->setAttribute((key), rs->attribute(key));
273 static Inkscape::XML::Node *sp_glyph_write(SPObject *object, Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags)
274 {
275 // SPGlyph *glyph = SP_GLYPH(object);
277 if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) {
278 repr = xml_doc->createElement("svg:glyph");
279 }
281 /* I am commenting out this part because I am not certain how does it work. I will have to study it later. Juca
282 repr->setAttribute("unicode", glyph->unicode);
283 repr->setAttribute("glyph-name", glyph->glyph_name);
284 repr->setAttribute("d", glyph->d);
285 sp_repr_set_svg_double(repr, "orientation", (double) glyph->orientation);
286 sp_repr_set_svg_double(repr, "arabic-form", (double) glyph->arabic_form);
287 repr->setAttribute("lang", glyph->lang);
288 sp_repr_set_svg_double(repr, "horiz-adv-x", glyph->horiz_adv_x);
289 sp_repr_set_svg_double(repr, "vert-origin-x", glyph->vert_origin_x);
290 sp_repr_set_svg_double(repr, "vert-origin-y", glyph->vert_origin_y);
291 sp_repr_set_svg_double(repr, "vert-adv-y", glyph->vert_adv_y);
292 */
293 if (repr != SP_OBJECT_REPR(object)) {
294 // All the COPY_ATTR functions below use
295 // XML Tree directly while they shouldn't.
296 COPY_ATTR(repr, object->getRepr(), "unicode");
297 COPY_ATTR(repr, object->getRepr(), "glyph-name");
298 COPY_ATTR(repr, object->getRepr(), "d");
299 COPY_ATTR(repr, object->getRepr(), "orientation");
300 COPY_ATTR(repr, object->getRepr(), "arabic-form");
301 COPY_ATTR(repr, object->getRepr(), "lang");
302 COPY_ATTR(repr, object->getRepr(), "horiz-adv-x");
303 COPY_ATTR(repr, object->getRepr(), "vert-origin-x");
304 COPY_ATTR(repr, object->getRepr(), "vert-origin-y");
305 COPY_ATTR(repr, object->getRepr(), "vert-adv-y");
306 }
308 if (((SPObjectClass *) (parent_class))->write) {
309 ((SPObjectClass *) (parent_class))->write(object, xml_doc, repr, flags);
310 }
312 return repr;
313 }
314 #endif //#ifdef ENABLE_SVG_FONTS
315 /*
316 Local Variables:
317 mode:c++
318 c-file-style:"stroustrup"
319 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
320 indent-tabs-mode:nil
321 fill-column:99
322 End:
323 */
324 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :