1 // SPDX-License-Identifier: GPL-2.0-or-later
2 #ifdef HAVE_CONFIG_H
3 #endif
4 
5 /*
6  * SVG <glyph> element implementation
7  *
8  * Author:
9  *   Felipe C. da S. Sanches <juca@members.fsf.org>
10  *   Abhishek Sharma
11  *
12  * Copyright (C) 2008, Felipe C. da S. Sanches
13  *
14  * Released under GNU GPL v2+, read the file 'COPYING' for more information.
15  */
16 
17 #include "xml/repr.h"
18 #include "attributes.h"
19 #include "sp-glyph.h"
20 #include "document.h"
21 
SPGlyph()22 SPGlyph::SPGlyph()
23     : SPObject()
24 //TODO: correct these values:
25     , d(nullptr)
26     , orientation(GLYPH_ORIENTATION_BOTH)
27     , arabic_form(GLYPH_ARABIC_FORM_INITIAL)
28     , lang(nullptr)
29     , horiz_adv_x(0)
30     , vert_origin_x(0)
31     , vert_origin_y(0)
32     , vert_adv_y(0)
33 {
34 }
35 
build(SPDocument * document,Inkscape::XML::Node * repr)36 void SPGlyph::build(SPDocument *document, Inkscape::XML::Node *repr)
37 {
38     SPObject::build(document, repr);
39 
40     this->readAttr(SPAttr::UNICODE);
41     this->readAttr(SPAttr::GLYPH_NAME);
42     this->readAttr(SPAttr::D);
43     this->readAttr(SPAttr::ORIENTATION);
44     this->readAttr(SPAttr::ARABIC_FORM);
45     this->readAttr(SPAttr::LANG);
46     this->readAttr(SPAttr::HORIZ_ADV_X);
47     this->readAttr(SPAttr::VERT_ORIGIN_X);
48     this->readAttr(SPAttr::VERT_ORIGIN_Y);
49     this->readAttr(SPAttr::VERT_ADV_Y);
50 }
51 
release()52 void SPGlyph::release() {
53     SPObject::release();
54 }
55 
sp_glyph_read_arabic_form(gchar const * value)56 static glyphArabicForm sp_glyph_read_arabic_form(gchar const *value){
57     if (!value) {
58     	return GLYPH_ARABIC_FORM_INITIAL; //TODO: verify which is the default default (for me, the spec is not clear)
59     }
60 
61     switch(value[0]){
62         case 'i':
63             if (strncmp(value, "initial", 7) == 0) {
64             	return GLYPH_ARABIC_FORM_INITIAL;
65             }
66 
67             if (strncmp(value, "isolated", 8) == 0) {
68             	return GLYPH_ARABIC_FORM_ISOLATED;
69             }
70             break;
71         case 'm':
72             if (strncmp(value, "medial", 6) == 0) {
73             	return GLYPH_ARABIC_FORM_MEDIAL;
74             }
75             break;
76         case 't':
77             if (strncmp(value, "terminal", 8) == 0) {
78             	return GLYPH_ARABIC_FORM_TERMINAL;
79             }
80             break;
81     }
82 
83     return GLYPH_ARABIC_FORM_INITIAL; //TODO: VERIFY DEFAULT!
84 }
85 
sp_glyph_read_orientation(gchar const * value)86 static glyphOrientation sp_glyph_read_orientation(gchar const *value)
87 {
88     if (!value) {
89     	return GLYPH_ORIENTATION_BOTH;
90     }
91 
92     switch(value[0]){
93         case 'h':
94             return GLYPH_ORIENTATION_HORIZONTAL;
95             break;
96         case 'v':
97             return GLYPH_ORIENTATION_VERTICAL;
98             break;
99     }
100 
101 //ERROR? TODO: VERIFY PROPER ERROR HANDLING
102     return GLYPH_ORIENTATION_BOTH;
103 }
104 
set(SPAttr key,const gchar * value)105 void SPGlyph::set(SPAttr key, const gchar *value)
106 {
107     switch (key) {
108         case SPAttr::UNICODE:
109         {
110             this->unicode.clear();
111 
112             if (value) {
113             	this->unicode.append(value);
114             }
115 
116             this->requestModified(SP_OBJECT_MODIFIED_FLAG);
117             break;
118         }
119         case SPAttr::GLYPH_NAME:
120         {
121             this->glyph_name.clear();
122 
123             if (value) {
124             	this->glyph_name.append(value);
125             }
126 
127             this->requestModified(SP_OBJECT_MODIFIED_FLAG);
128             break;
129         }
130         case SPAttr::D:
131         {
132             if (this->d) {
133             	g_free(this->d);
134             }
135 
136             this->d = g_strdup(value);
137             this->requestModified(SP_OBJECT_MODIFIED_FLAG);
138             break;
139         }
140         case SPAttr::ORIENTATION:
141         {
142             glyphOrientation orient = sp_glyph_read_orientation(value);
143 
144             if (this->orientation != orient){
145                 this->orientation = orient;
146                 this->requestModified(SP_OBJECT_MODIFIED_FLAG);
147             }
148             break;
149         }
150         case SPAttr::ARABIC_FORM:
151         {
152             glyphArabicForm form = sp_glyph_read_arabic_form(value);
153 
154             if (this->arabic_form != form){
155                 this->arabic_form = form;
156                 this->requestModified(SP_OBJECT_MODIFIED_FLAG);
157             }
158             break;
159         }
160         case SPAttr::LANG:
161         {
162             if (this->lang) {
163             	g_free(this->lang);
164             }
165 
166             this->lang = g_strdup(value);
167             this->requestModified(SP_OBJECT_MODIFIED_FLAG);
168             break;
169         }
170         case SPAttr::HORIZ_ADV_X:
171         {
172             double number = value ? g_ascii_strtod(value, nullptr) : 0;
173 
174             if (number != this->horiz_adv_x){
175                 this->horiz_adv_x = number;
176                 this->requestModified(SP_OBJECT_MODIFIED_FLAG);
177             }
178             break;
179         }
180         case SPAttr::VERT_ORIGIN_X:
181         {
182             double number = value ? g_ascii_strtod(value, nullptr) : 0;
183 
184             if (number != this->vert_origin_x){
185                 this->vert_origin_x = number;
186                 this->requestModified(SP_OBJECT_MODIFIED_FLAG);
187             }
188             break;
189         }
190         case SPAttr::VERT_ORIGIN_Y:
191         {
192             double number = value ? g_ascii_strtod(value, nullptr) : 0;
193 
194             if (number != this->vert_origin_y){
195                 this->vert_origin_y = number;
196                 this->requestModified(SP_OBJECT_MODIFIED_FLAG);
197             }
198             break;
199         }
200         case SPAttr::VERT_ADV_Y:
201         {
202             double number = value ? g_ascii_strtod(value, nullptr) : 0;
203 
204             if (number != this->vert_adv_y){
205                 this->vert_adv_y = number;
206                 this->requestModified(SP_OBJECT_MODIFIED_FLAG);
207             }
208             break;
209         }
210         default:
211         {
212         	SPObject::set(key, value);
213             break;
214         }
215     }
216 }
217 
218 /**
219  * Receives update notifications.
220  */
update(SPCtx * ctx,guint flags)221 void SPGlyph::update(SPCtx *ctx, guint flags)
222 {
223     if (flags & SP_OBJECT_MODIFIED_FLAG) {
224         /* do something to trigger redisplay, updates? */
225         this->readAttr(SPAttr::UNICODE);
226         this->readAttr(SPAttr::GLYPH_NAME);
227         this->readAttr(SPAttr::D);
228         this->readAttr(SPAttr::ORIENTATION);
229         this->readAttr(SPAttr::ARABIC_FORM);
230         this->readAttr(SPAttr::LANG);
231         this->readAttr(SPAttr::HORIZ_ADV_X);
232         this->readAttr(SPAttr::VERT_ORIGIN_X);
233         this->readAttr(SPAttr::VERT_ORIGIN_Y);
234         this->readAttr(SPAttr::VERT_ADV_Y);
235     }
236 
237     SPObject::update(ctx, flags);
238 }
239 
240 #define COPY_ATTR(rd,rs,key) (rd)->setAttribute((key), rs->attribute(key));
241 
write(Inkscape::XML::Document * xml_doc,Inkscape::XML::Node * repr,guint flags)242 Inkscape::XML::Node* SPGlyph::write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags)
243 {
244     if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) {
245         repr = xml_doc->createElement("svg:glyph");
246     }
247 
248     /* I am commenting out this part because I am not certain how does it work. I will have to study it later. Juca
249     repr->setAttribute("unicode", glyph->unicode);
250     repr->setAttribute("glyph-name", glyph->glyph_name);
251     repr->setAttribute("d", glyph->d);
252     sp_repr_set_svg_double(repr, "orientation", (double) glyph->orientation);
253     sp_repr_set_svg_double(repr, "arabic-form", (double) glyph->arabic_form);
254     repr->setAttribute("lang", glyph->lang);
255     sp_repr_set_svg_double(repr, "horiz-adv-x", glyph->horiz_adv_x);
256     sp_repr_set_svg_double(repr, "vert-origin-x", glyph->vert_origin_x);
257     sp_repr_set_svg_double(repr, "vert-origin-y", glyph->vert_origin_y);
258     sp_repr_set_svg_double(repr, "vert-adv-y", glyph->vert_adv_y);
259     */
260 
261     if (repr != this->getRepr()) {
262         // All the COPY_ATTR functions below use
263         // XML Tree directly while they shouldn't.
264         COPY_ATTR(repr, this->getRepr(), "unicode");
265         COPY_ATTR(repr, this->getRepr(), "glyph-name");
266         COPY_ATTR(repr, this->getRepr(), "d");
267         COPY_ATTR(repr, this->getRepr(), "orientation");
268         COPY_ATTR(repr, this->getRepr(), "arabic-form");
269         COPY_ATTR(repr, this->getRepr(), "lang");
270         COPY_ATTR(repr, this->getRepr(), "horiz-adv-x");
271         COPY_ATTR(repr, this->getRepr(), "vert-origin-x");
272         COPY_ATTR(repr, this->getRepr(), "vert-origin-y");
273         COPY_ATTR(repr, this->getRepr(), "vert-adv-y");
274     }
275 
276     SPObject::write(xml_doc, repr, flags);
277 
278     return repr;
279 }
280 
281 /*
282   Local Variables:
283   mode:c++
284   c-file-style:"stroustrup"
285   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
286   indent-tabs-mode:nil
287   fill-column:99
288   End:
289 */
290 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
291