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