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