1 #define __SP_OBJECT_REPR_C__
3 /*
4 * Object type dictionary and build frontend
5 *
6 * Authors:
7 * Lauris Kaplinski <lauris@kaplinski.com>
8 *
9 * Copyright (C) 1999-2003 Lauris Kaplinski
10 *
11 * Released under GNU GPL, read the file 'COPYING' for more information
12 */
14 #include "sp-defs.h"
15 #include "sp-symbol.h"
16 #include "sp-marker.h"
17 #include "sp-use.h"
18 #include "sp-root.h"
19 #include "sp-image.h"
20 #include "sp-linear-gradient-fns.h"
21 #include "sp-path.h"
22 #include "sp-radial-gradient-fns.h"
23 #include "sp-rect.h"
24 #include "sp-ellipse.h"
25 #include "sp-star.h"
26 #include "sp-stop-fns.h"
27 #include "sp-spiral.h"
28 #include "sp-offset.h"
29 #include "sp-line.h"
30 #include "sp-metadata.h"
31 #include "sp-polyline.h"
32 #include "sp-textpath.h"
33 #include "sp-tspan.h"
34 #include "sp-pattern.h"
35 #include "sp-clippath.h"
36 #include "sp-mask.h"
37 #include "sp-anchor.h"
38 //#include "sp-animation.h"
39 #include "sp-flowdiv.h"
40 #include "sp-flowregion.h"
41 #include "sp-flowtext.h"
42 #include "sp-style-elem.h"
43 #include "color-profile-fns.h"
44 #include "xml/repr.h"
46 enum NameType { REPR_NAME, SODIPODI_TYPE };
47 static unsigned const N_NAME_TYPES = SODIPODI_TYPE + 1;
49 static GType name_to_gtype(NameType name_type, gchar const *name);
51 /**
52 * Construct an SPRoot and all its descendents from the given repr.
53 */
54 SPObject *
55 sp_object_repr_build_tree(SPDocument *document, Inkscape::XML::Node *repr)
56 {
57 g_assert(document != NULL);
58 g_assert(repr != NULL);
60 gchar const * const name = repr->name();
61 g_assert(name != NULL);
62 GType const type = name_to_gtype(REPR_NAME, name);
63 g_assert(g_type_is_a(type, SP_TYPE_ROOT));
64 gpointer newobj = g_object_new(type, 0);
65 g_assert(newobj != NULL);
66 SPObject *const object = SP_OBJECT(newobj);
67 g_assert(object != NULL);
68 sp_object_invoke_build(object, document, repr, FALSE);
70 return object;
71 }
73 GType
74 sp_repr_type_lookup(Inkscape::XML::Node *repr)
75 {
76 if ( repr->type() == Inkscape::XML::TEXT_NODE ) {
77 return SP_TYPE_STRING;
78 } else if ( repr->type() == Inkscape::XML::ELEMENT_NODE ) {
79 gchar const * const type_name = repr->attribute("sodipodi:type");
80 return ( type_name
81 ? name_to_gtype(SODIPODI_TYPE, type_name)
82 : name_to_gtype(REPR_NAME, repr->name()) );
83 } else {
84 return 0;
85 }
86 }
88 static GHashTable *t2dtable[N_NAME_TYPES] = {NULL};
90 static void
91 populate_dtables()
92 {
93 struct NameTypeEntry { char const *const name; GType const type_id; };
94 NameTypeEntry const repr_name_entries[] = {
95 { "svg:a", SP_TYPE_ANCHOR },
96 //{ "svg:animate", SP_TYPE_ANIMATE },
97 { "svg:circle", SP_TYPE_CIRCLE },
98 { "svg:color-profile", COLORPROFILE_TYPE },
99 { "svg:clipPath", SP_TYPE_CLIPPATH },
100 { "svg:defs", SP_TYPE_DEFS },
101 { "svg:ellipse", SP_TYPE_ELLIPSE },
102 /* Note: flow* elements are proposed additions for SVG 1.2, they aren't in
103 SVG 1.1. */
104 { "svg:flowDiv", SP_TYPE_FLOWDIV },
105 { "svg:flowLine", SP_TYPE_FLOWLINE },
106 { "svg:flowPara", SP_TYPE_FLOWPARA },
107 { "svg:flowRegion", SP_TYPE_FLOWREGION },
108 { "svg:flowRegionBreak", SP_TYPE_FLOWREGIONBREAK },
109 { "svg:flowRegionExclude", SP_TYPE_FLOWREGIONEXCLUDE },
110 { "svg:flowRoot", SP_TYPE_FLOWTEXT },
111 { "svg:flowSpan", SP_TYPE_FLOWTSPAN },
112 { "svg:g", SP_TYPE_GROUP },
113 { "svg:image", SP_TYPE_IMAGE },
114 { "svg:line", SP_TYPE_LINE },
115 { "svg:linearGradient", SP_TYPE_LINEARGRADIENT },
116 { "svg:marker", SP_TYPE_MARKER },
117 { "svg:mask", SP_TYPE_MASK },
118 { "svg:metadata", SP_TYPE_METADATA },
119 { "svg:path", SP_TYPE_PATH },
120 { "svg:pattern", SP_TYPE_PATTERN },
121 { "svg:polygon", SP_TYPE_POLYGON },
122 { "svg:polyline", SP_TYPE_POLYLINE },
123 { "svg:radialGradient", SP_TYPE_RADIALGRADIENT },
124 { "svg:rect", SP_TYPE_RECT },
125 { "svg:stop", SP_TYPE_STOP },
126 { "svg:svg", SP_TYPE_ROOT },
127 { "svg:style", SP_TYPE_STYLE_ELEM },
128 { "svg:switch", SP_TYPE_GROUP },
129 { "svg:symbol", SP_TYPE_SYMBOL },
130 { "svg:text", SP_TYPE_TEXT },
131 { "svg:textPath", SP_TYPE_TEXTPATH },
132 { "svg:tspan", SP_TYPE_TSPAN },
133 { "svg:use", SP_TYPE_USE }
134 };
135 NameTypeEntry const sodipodi_name_entries[] = {
136 { "arc", SP_TYPE_ARC },
137 { "inkscape:offset", SP_TYPE_OFFSET },
138 { "spiral", SP_TYPE_SPIRAL },
139 { "star", SP_TYPE_STAR }
140 };
142 NameTypeEntry const *const t2entries[] = {
143 repr_name_entries,
144 sodipodi_name_entries
145 };
146 unsigned const t2n_entries[] = {
147 G_N_ELEMENTS(repr_name_entries),
148 G_N_ELEMENTS(sodipodi_name_entries)
149 };
151 for (unsigned nt = 0; nt < N_NAME_TYPES; ++nt) {
152 NameTypeEntry const *const entries = t2entries[nt];
153 unsigned const n_entries = t2n_entries[nt];
154 GHashTable *&dtable = t2dtable[nt];
156 dtable = g_hash_table_new(g_str_hash, g_str_equal);
157 for (unsigned i = 0; i < n_entries; ++i) {
158 g_hash_table_insert(dtable,
159 (void *)entries[i].name,
160 (gpointer) entries[i].type_id);
161 }
162 }
163 }
165 static inline void
166 ensure_dtables_populated()
167 {
168 if (!*t2dtable) {
169 populate_dtables();
170 }
171 }
173 static GType
174 name_to_gtype(NameType const name_type, gchar const *name)
175 {
176 ensure_dtables_populated();
178 gpointer const data = g_hash_table_lookup(t2dtable[name_type], name);
179 return ( ( data == NULL )
180 ? SP_TYPE_OBJECT
181 : (GType) data );
182 }
184 void
185 sp_object_type_register(gchar const *name, GType const gtype)
186 {
187 GType const current = name_to_gtype(REPR_NAME, name);
188 if (current == SP_TYPE_OBJECT) {
189 g_hash_table_insert(t2dtable[REPR_NAME],
190 const_cast<gchar *>(name),
191 (gpointer) gtype);
192 } else {
193 /* Already registered. */
194 if (current != gtype) {
195 g_warning("repr type `%s' already registered as type #%lu, ignoring attempt to re-register as #%lu.",
196 name, current, gtype);
197 }
198 }
199 }
201 /*
202 Local Variables:
203 mode:c++
204 c-file-style:"stroustrup"
205 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
206 indent-tabs-mode:nil
207 fill-column:99
208 End:
209 */
210 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :