Code

A simple layout document as to what, why and how is cppification.
[inkscape.git] / src / conditions.cpp
1 #define __SP_CONDITIONS_CPP__
3 /*
4  * SVG conditional attribute evaluation
5  *
6  * Authors:
7  *   Andrius R. <knutux@gmail.com>
8  *
9  * Copyright (C) 2006 authors
10  *
11  * Released under GNU GPL, read the file 'COPYING' for more information
12  */
14 #ifdef HAVE_CONFIG_H
15 # include "config.h"
16 #endif
18 #include <set>
19 #include <glibmm/ustring.h>
20 #include "conditions.h"
21 #include "xml/repr.h"
22 #include "rdf.h"
24 typedef bool (* condition_evaluator)(SPItem const *item, gchar const *value);
26 struct Condition {
27     gchar const *attribute;
28     condition_evaluator evaluator;
29 };
31 static bool evaluateSystemLanguage(SPItem const *item, gchar const *value);
32 static bool evaluateRequiredFeatures(SPItem const *item, gchar const *value);
33 static bool evaluateRequiredExtensions(SPItem const *item, gchar const *value);
35 /* define any conditional attributes and their handler functions in this array */
36 static Condition _condition_handlers[] = {
37     { "systemLanguage", evaluateSystemLanguage },
38     { "requiredFeatures", evaluateRequiredFeatures },
39     { "requiredExtensions", evaluateRequiredExtensions },
40 };
42 /* function which evaluates if item should be displayed */
43 bool sp_item_evaluate(SPItem const *item) {
44     //Inkscape::XML::Node *grepr = SP_OBJECT_REPR (item);
45     
46     for ( unsigned int i = 0 ; i < sizeof(_condition_handlers)/sizeof(_condition_handlers[0]) ; i++ ) {
47         //gchar const *value = grepr->attribute(_condition_handlers[i].attribute);
48         gchar const *value = item->getAttribute(_condition_handlers[i].attribute);
49         if ( NULL == value )
50             continue;
52         if (!_condition_handlers[i].evaluator(item, value))
53             return false;
54     }
56     return true;
57 }
59 #define ISALNUM(c)    (((c) >= 'a' && (c) <= 'z') || ((c) >= 'A' && (c) <= 'Z') || ((c) >= '0' && (c) <= '9'))
61 static gchar *preprocessLanguageCode(gchar *lngcode) {
62     if ( NULL == lngcode )
63         return NULL;
65     lngcode = g_strstrip(lngcode);
66     if ( 0 == *lngcode )
67         return lngcode;
68     for ( unsigned int i = 0 ; i < strlen(lngcode) ; i++ ) {
69         if ( lngcode[i] >= 'A' && lngcode[i] <= 'Z' ) {
70             lngcode[i] = g_ascii_tolower(lngcode[i]);
71         } else if ( '_' == lngcode[i] ) {
72             lngcode[i] = '-';
73         } else if ( !ISALNUM(lngcode[i]) && '-' != lngcode[i] ) {
74             // only alpha numeric characters and '-' may be contained in language code
75             lngcode[0] = 0;
76             break;
77         }
78     }
79     
80     return lngcode;
81 }
83 static bool evaluateSystemLanguage(SPItem const *item, gchar const *value) {
84     if ( NULL == value )
85         return true;
87     std::set<Glib::ustring> language_codes;
88     gchar *str = NULL;
89     gchar **strlist = g_strsplit( value, ",", 0);
91     for ( int i = 0 ; (str = strlist[i]) ; i++ ) {
92         gchar *lngcode = preprocessLanguageCode(str);
93         if ( 0 == *lngcode )
94             continue;
95         language_codes.insert(lngcode);
97         gchar *pos = strchr (lngcode, '-');
98         if (pos)
99         {
100             // if subtag is used, primary tag is still a perfect match
101             *pos = 0;
102             if ( language_codes.find(lngcode) == language_codes.end() ) {
103                 language_codes.insert(lngcode);
104             }
105         }
106     }
107     g_strfreev(strlist);
109     if (language_codes.empty())
110         return false;
112     SPDocument *document = SP_OBJECT_DOCUMENT(item);
113     Glib::ustring document_language = document->getLanguage();
115     if (document_language.size() == 0)
116         return false;
118     bool match = true;
119     strlist = g_strsplit( document_language.c_str(), ",", 0);
120     for ( int i = 0 ; (str = strlist[i]) ; i++ ) {
121         gchar *lngcode = preprocessLanguageCode(str);
122         if ( 0 == *lngcode )
123             continue;
124         if ( language_codes.find(lngcode) != language_codes.end() ) {
125             match = true;
126             break;
127         }
128         match = false;
129     }
130     g_strfreev(strlist);
131     return match;
134 static std::vector<Glib::ustring> splitByWhitespace(gchar const *value) {
135     std::vector<Glib::ustring> parts;
136     gchar *str = NULL;
137     gchar **strlist = g_strsplit( value, ",", 0);
139     for ( int i = 0 ; (str = strlist[i]) ; i++ ) {
140         gchar *part = g_strstrip(str);
141         if ( 0 == *part )
142             continue;
143         parts.push_back(part);
144     }
145     g_strfreev(strlist);
146     return parts;
149 #define SVG11FEATURE    "http://www.w3.org/TR/SVG11/feature#"
150 #define SVG10FEATURE    "org.w3c."
152 static bool evaluateSVG11Feature(gchar const *feature) {
153     static gchar const *_supported_features[] = {
154         "SVG", // incomplete "SVG-static" - missing support for "Filter"
155            /* SVG - user agent supports at least one of the following:
156                 "SVG-static", "SVG-animation", "SVG-dynamic" or "SVGDOM" */
157         // "SVGDOM", // not sure
158            /* SVGDOM - user agent supports at least one of the following:
159                  "SVGDOM-static", "SVGDOM-animation" or "SVGDOM-dynamic" */
160         "SVG-static", // incomplete - missing support for "Filter"
161            /* SVG-static - user agent supports the following features:
162                 "CoreAttribute", "Structure", "ContainerAttribute",
163                 "ConditionalProcessing", "Image", "Style", "ViewportAttribute",
164                 "Shape", "Text", "PaintAttribute", "OpacityAttribute",
165                 "GraphicsAttribute", "Marker", "ColorProfile",
166                 "Gradient", "Pattern", "Clip", "Mask", "Filter",
167                 "XlinkAttribute", "Font", "Extensibility" */
168         // "SVGDOM-static", // not sure
169            /* SVGDOM-static - All of the DOM interfaces and methods
170                 that correspond to SVG-static */
171         // "SVG-animation", // no support
172            /* SVG-animation - All of the language features from "SVG-static"
173                 plus the feature "feature#Animation" */
174         // "SVGDOM-animation", // no support
175            /* SVGDOM-animation - All of the DOM interfaces and methods
176                 that correspond to SVG-animation */
177         // "SVG-dynamic", // no support
178            /* SVG-dynamic - user agent supports all "SVG-animation" and the following features:
179                 "Hyperlinking", "Scripting", "View", "Cursor",
180                 "GraphicalEventsAttribute", "DocumentEventsAttribute", "AnimationEventsAttribute" */
181         // "SVGDOM-dynamic", // no support
182            /* SVGDOM-dynamic - All of the DOM interfaces and methods
183                 that correspond to SVG-dynamic */
184         "CoreAttribute",
185         "Structure",
186         "BasicStructure",
187         "ContainerAttribute",
188         "ConditionalProcessing",
189         "Image",
190         "Style",
191         "ViewportAttribute", // not sure
192         "Shape",
193         "Text",
194         "BasicText",
195         "PaintAttribute",
196         "BasicPaintAttribute",
197         "OpacityAttribute",
198         "GraphicsAttribute",
199         "BasicGraphicsAttribute",
200         "Marker",
201         "ColorProfile",
202         "Gradient",
203         "Pattern",
204         "Clip",
205         "BasicClip",
206         "Mask",
207         // "Filter",
208         // "BasicFilter",
209         // "DocumentEventsAttribute",
210         // "GraphicalEventsAttribute",
211         // "AnimationEventsAttribute",
212         // "Cursor", // not sure
213         "Hyperlinking", // not sure
214         "XlinkAttribute", // not sure
215         "ExternalResourcesRequired", // not sure
216         "View",
217         // "Script",
218         // "Animation",
219         "Font",
220         "BasicFont",
221         "Extensibility", // not sure
222     };
223     
224     for ( unsigned int i = 0 ; i < sizeof(_supported_features)/sizeof(_supported_features[0]); i++ ) {
225         if ( 0 == strcasecmp(feature, _supported_features[0]) )
226             return true;
227     }
228     return false;
231 static bool evaluateSVG10Feature(gchar const *feature) {
232     static gchar const *_supported_features[] = {
233         "svg.static", // incomplete - no filter effects
234         "dom.svg.static", // not sure
235         // "svg.animation",
236         // "dom.svg.animation",
237         // "svg.dynamic",
238         // "dom.svg.dynamic"
239         // "svg.all",
240         // "dom.svg.all"
241     };
242     for ( unsigned int i = 0 ; i < sizeof(_supported_features)/sizeof(_supported_features[0]); i++ ) {
243         if ( 0 == strcasecmp(feature, _supported_features[0]) )
244             return true;
245     }
246     return false;
249 static bool evaluateSingleFeature(gchar const *value) {
250     if ( NULL == value )
251         return false;
252     gchar const *found;
253     found = strstr(value, SVG11FEATURE);
254     if ( value == found )
255         return evaluateSVG11Feature(found + strlen(SVG11FEATURE));
256     found = strstr(value, SVG10FEATURE);
257     if ( value == found )
258         return evaluateSVG10Feature(found + strlen(SVG10FEATURE));
259     return false;
262 static bool evaluateRequiredFeatures(SPItem const */*item*/, gchar const *value) {
263     if ( NULL == value )
264         return true;
266     std::vector<Glib::ustring> parts = splitByWhitespace(value);
267     if ( 0 == parts.size() )
268         return false;
270     for ( unsigned int i = 0 ; i < parts.size() ; i++ ) {
271         if (!evaluateSingleFeature(parts[i].c_str())) {
272             return false;
273         }
274     }
275     
276     return true;
279 static bool evaluateRequiredExtensions(SPItem const */*item*/, gchar const *value) {
280     if ( NULL == value )
281         return true;
282     return false;
285 /*
286  * Language codes and names:
287 aa Afar
288 ab Abkhazian
289 af Afrikaans
290 am Amharic
291 ar Arabic
292 as Assamese
293 ay Aymara
294 az Azerbaijani
296 ba Bashkir
297 be Byelorussian
298 bg Bulgarian
299 bh Bihari
300 bi Bislama
301 bn Bengali; Bangla
302 bo Tibetan
303 br Breton
305 ca Catalan
306 co Corsican
307 cs Czech
308 cy Welsh
310 da Danish
311 de German
312 dz Bhutani
314 el Greek
315 en English
316 eo Esperanto
317 es Spanish
318 et Estonian
319 eu Basque
321 fa Persian
322 fi Finnish
323 fj Fiji
324 fo Faroese
325 fr French
326 fy Frisian
328 ga Irish
329 gd Scots Gaelic
330 gl Galician
331 gn Guarani
332 gu Gujarati
334 ha Hausa
335 he Hebrew (formerly iw)
336 hi Hindi
337 hr Croatian
338 hu Hungarian
339 hy Armenian
341 ia Interlingua
342 id Indonesian (formerly in)
343 ie Interlingue
344 ik Inupiak
345 is Icelandic
346 it Italian
347 iu Inuktitut
349 ja Japanese
350 jw Javanese
352 ka Georgian
353 kk Kazakh
354 kl Greenlandic
355 km Cambodian
356 kn Kannada
357 ko Korean
358 ks Kashmiri
359 ku Kurdish
360 ky Kirghiz
362 la Latin
363 ln Lingala
364 lo Laothian
365 lt Lithuanian
366 lv Latvian, Lettish
368 mg Malagasy
369 mi Maori
370 mk Macedonian
371 ml Malayalam
372 mn Mongolian
373 mo Moldavian
374 mr Marathi
375 ms Malay
376 mt Maltese
377 my Burmese
379 na Nauru
380 ne Nepali
381 nl Dutch
382 no Norwegian
384 oc Occitan
385 om (Afan) Oromo
386 or Oriya
388 pa Punjabi
389 pl Polish
390 ps Pashto, Pushto
391 pt Portuguese
393 qu Quechua
395 rm Rhaeto-Romance
396 rn Kirundi
397 ro Romanian
398 ru Russian
399 rw Kinyarwanda
401 sa Sanskrit
402 sd Sindhi
403 sg Sangho
404 sh Serbo-Croatian
405 si Sinhalese
406 sk Slovak
407 sl Slovenian
408 sm Samoan
409 sn Shona
410 so Somali
411 sq Albanian
412 sr Serbian
413 ss Siswati
414 st Sesotho
415 su Sundanese
416 sv Swedish
417 sw Swahili
419 ta Tamil
420 te Telugu
421 tg Tajik
422 th Thai
423 ti Tigrinya
424 tk Turkmen
425 tl Tagalog
426 tn Setswana
427 to Tonga
428 tr Turkish
429 ts Tsonga
430 tt Tatar
431 tw Twi
433 ug Uighur
434 uk Ukrainian
435 ur Urdu
436 uz Uzbek
438 vi Vietnamese
439 vo Volapuk
441 wo Wolof
443 xh Xhosa
445 yi Yiddish (formerly ji)
446 yo Yoruba
448 za Zhuang
449 zh Chinese
450 zu Zulu
451  */
454 /*
455   Local Variables:
456   mode:c++
457   c-file-style:"stroustrup"
458   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
459   indent-tabs-mode:nil
460   fill-column:99
461   End:
462 */
463 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :