1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
|
== Inkscape Extensions ==
=== Introduction ===
The extensions system in Inkscape is a way for adding functionality to
Inkscape, without affecting the core of the program itself. We want
Inkscape to follow a core-plus-modules approach similar to that adopted
by many successful open source projects such as the Linux kernel, Perl,
Apache, Gimp, and so on. There are many different types of extension
mechanisms, including file format conversion tools, filter scripts that
process SVG, user interface elements that can be added at runtime, and
so forth.
This proposal defines a design for handling this wide variety of
extensions in a flexible manner. This document provides a way to
understand the extensions system, and how extensions fit into this
overall system.
Much of the documentation that will be useful for users of the extension
system is not included in this document, it is autogenerated from the
source code and placed on the Inkscape webpage. While this is less
convenient, it is more correct, and maintained as the source code is
modified. Please look aton the Inkscape webpage also.
=== Terminology ===
*Extension* - An extension is something that extends the functionality
of Inkscape without being directly part of the core. This implies
that it should be easy to remove or add, and nothing in the core should
depend on it directly.
*Extension Type* - Establishes the functional interface that the
Extension provides, including the types of messages it handles and what
is contained in its data structures.
*Extension Implementation* - Defines how the extension is accessed;
i.e. through message passing, pipe/exec calls with commandline
arguments, direct function calls, etc.
*Plug-in* - An extension that is implemented through a loadable library.
This is a .so file on Unix-like systems or a .dll on Win32. The
libraries should not be loaded until they are used.
*Script* - A script is a type of extension that is implemented through
an external program that receives and sets SVG data through files and
pipes. This allows Inkscape to use programs that handle SVG but are
targeted differently, seamlessly inside of Inkscape.
*Language Binding* - A special type of plug-in that wraps a scripting
language interpreter such as Perl, Python, Lisp, etc. A user
interested in programmatic access to Inkscape's internals via one of
these languages can install (or create) the relevant Language Binding
Plug-in to achieve this.
*INX* - *'INkscape eXtension'* - The filename extension used for XML
metadata files that describe each Inkscape Extension.
*Internal Extension* - A part of the Inkscape codebase which uses the
extension system in order to make it more modular. This code is
compiled into Inkscape, but appears as an extension to all other code
in the codebase.
=== Requirements ===
* Uses a general language binding system so it's easy to add new
language binding support.
* Allows direct interaction with the document object model including
changing.
* Allows some limited interaction with the Inkscape UI such as
manipulating grids, overlays, etc.
* Allows direct interaction with file load/save/export/print
subsystem.
* Guaranteed to work properly with the undo system, even if the
extension is not written carefully.
* Well documented so is easy for people to learn how to make new
extensions.
* Each extension can be implemented, distributed, and managed
independently of the core project.
* Icons, buttons, and other UI elements for extensions fit seamlessly
into main application GUI.
* User can easily select which extensions to automatically load into
application at startup.
* Loading of extensions shall not seriously slow startup time or make
a major impact on memory footprint.
* Failure of a extension shall not leave the drawing in an
inconsistent state.
* Main application must gracefully recover from extension crashes or
other serious problems with extension execution.
* Dependencies for particular extensions must be clearly identified for user if missing.
=== Overview ===
Different kinds of extensions can be categorized in two ways. First,
but what the extension does: File format converters, printing, SVG
manipulation, symbol libraries, etc. Second, by how the extension is
implemented: command-line scripts, dynamically loaded libraries,
internal compiled-in code, etc.
The first kind of categorization is called the *Extension Type*. This
essentially establishes a calling interface and the set of messages the
extension must be able to receive and handle. For example, extensions
of type Print must have a way to handle 'print' message.
The second is the *Extension Implementation*. This defines the
mechanism Inkscape must use for passing messages to the extension. For
example, commandline scripts would have messages passed as commandline
arguments, whereas loadable plug-ins would have the messages passed to
the plug-in's message handler routine.
The categories of both Extension Types and Extension Implementations are
left open ended. This way, if someone comes up with new ideas for ways
to extend Inkscape that doesn't fit within the existing models, they can
add these mechanisms in a straightforward fashion.
For the purposes of this document, however, we focus on just the
following Types and Implementations:
Extension
"Input" - loading various file formats
"Output" - saving as various file formats
"Effect" - apply some sort of change to SVG elements in the doc
"Print" - prints using different drivers or modes
"Collection" - a group of objects that have thumbnails and images that
can be used inside a document. Libraries can be
searchable and may be presented in a hierarchical
structure
"Extension Implementations"
"Internal" - code that is internal to Inkscape which uses the
extension system for some functionality
"Script" - a cmdline program that takes an SVG document to its
STDIN and emits a modified SVG document to its STDOUT,
with control messages given as commandline parameters.
"Plug-in" - a loadable module with a message handler routine that
receives messages and that operates on the Inkscape API
functions directly.
=== Extension System Basics ===
Leaving the topic of Types and Implementations aside, we can make some
generalizations about how all Extensions work, and behaviors or
attributes that all Extensions share. This includes how they are
registered, how they handle preferences, how dependency resolution is
achieved, and versioning. These common behaviors are all established
via a base class that all Extension Types derive from.
=== Extension Base Class ===
The Extension base class holds the attribute data that all extensions
must have and establishes the base functionality that all extensions
share. All extensions have the following properties:
"ID" - A unique identifier for this extension that is used for referring
to the extension and naming its parameters in the configuration files.
"Name" - The textual name of the extension, it is used for user
interaction with the extension. It is used for users to identify the
extension.
"Parameters" - Each extension keeps a record of all of the parameters
that it has. The can be changed internally, through a GUI, or by other
extensions. Parameters can be found and adjusted using functions that
are within the base class.
=== Extension Registry ===
Inkscape maintains a data structure of all the registered extensions.
This registry can be queried against to retrieve lists of extensions
meeting various conditions (such as all Input extensions).
The Extension Registry contains all extensions whether or not they
failed their dependency checking on startup. This allows for additional
information to be displayed on the reasoning behind marking the
extension as disabled.
The registry can be reloaded from the Inkscape GUI while Inkscape is
running. This can be used to add new extensions into the system, or
help debug new extensions. When the registry is reloaded all extensions
are first unloaded, then they're specification files are re-read.
=== Handling Preferences ===
Individual extensions can have their own preferences which are used by
the extension. These are typically attributes of the operation that can
be modified by the user through a dialog. It is also possible to have
other extensions modify these values when they are using an extension.
For most extensions, these will be edited by a dialog that relates to
the preferences of the user.
The preferences themselves are defined in the inx file that describes
the extension. In this definition there is the name, the type, and the
default value. The types are: boolean, integer, float and string.
Other types can be developed using these as a basis. If there is no
custom value set the default value is used.
When a value is written to a preference for an extension, that value is
saved in the global preferences for Inkscape using the ID of the module
as the basis for the naming. At next use (including after restarting
the application) this value is used instead of the default. This allows
user preferences on a extension to remain persistent throughout uses of
Inkscape.
=== INX Files ===
The INX file is the description of the Inkscape Extension. It provides
all of the information that is used to identify the extension, and
determine what type of extension it is. This file is loaded on startup
of Inkscape, and the objects relating to the extension are created. All
extensions have an inx file, but many internal extensions compile this
file into the codebase (to reduce dependencies).
The INX file also contains information on the dependencies that are
required for the extension to operate. These dependencies can be
everything from required files, required libraries or other extensions
that help this one. The dependencies are checked as the file is loaded,
and an extension is marked as dead if they are not met. Also
dependencies can check different versions of particular objects to see
if they are met.
=== Extension Types ===
Each Extension is identified by it's 'Type'. This determines the type
of programmatic interface that it adheres to, enabling Inkscape to know
what functionality it can expect from the extension.
=== Input ===
An input extension provides a way to get data into Inkscape. This type
of extension creates a document given a filename. This is done by using
the 'open' method within the class. Also, there is a 'prefs' function
which will generate a GtkDialog. This dialog is then used to get any
settings that the incoming file and extension may use. This function is
executed, and the dialog returns, before the open method is called.
There are also several other settings stored in an Input extension.
This includes information on the type of file the input module can take
in including its filename extension and mime type. Also, there is a
space to store a tooltip for additional information on the file type in
the file dialog. Lastly, there is the key of which Output extension is
recommended for saving this filetype. This is useful, as there is no
other direct links between the Input and Output functions, and a user
expects to be able to open and save without using the 'Save As...'
dialog.
=== Output ===
An output extension controls how SVG documents are exported from
Inkscape. This type of extension creates a file given a document
object. This is done using the 'save' method within the class.
The method for how files are exported depends on what type of
Implementation is used. For Scripts, the file is first saved as a
temporary SVG file, and then processed by calling the commandline
programs to convert it. For Plug-ins, the document object is passed to
the extension with a 'save' message and a filename, and the extension
program performs the file save operation itself.
=== Effect ===
Effect extensions cause a modification of a loaded document. For
example, it might add a new shape to the drawing, or change all selected
objects to be purple with green dotted borders.
=== Print ===
The Print Extension Type is for extensions that interface with printing
subsystems. Examples would be Win32, postscript, and GNOME Print.
=== Collection ===
=== Creating Extensions ===
In this chapter, we discuss how to create an extension from scratch,
incorporate into Inkscape, and release it for the general Inkscape
community to use. This chapter can be read independently of the rest of
the document, using the rest as reference material.
=== Selecting an Extension Strategy ===
First of all, you will need to select the method you'll use for creating your extension.
Scripts are the simplest extensions to create, because they work through
STDIN/STDOUT, so you need to know very little about Inkscape internals
to make them work. However, their ability to interact with the Inkscape
internals is limited compared with other approaches. For file format
converters, this is usually fine. You can also create filters programs
that take the entire document to its STDIN, process it, and return a
modified copy to STDOUT. Some control of the extension is possible via
its commandline arguments.
One of the nice things about Scripts is that they can be written in any
language. It need not even be a scripting language - as long as it
handles STDIN and STDOUT and uses commandline arguments, you can write
it however you wish.
Plug-ins are more powerful than Scripts, but require more knowledge of
Inkscape internals, and must be written according to specific criteria.
Generally, since these are loaded as dynamic objects, they'll need to be
written in a language that can generate them, such as C or C++.
The best of both worlds can be available through Language Bindings,
which are Plug-ins that wrapper a script interpreter. This enables you
to call various Inkscape internal routines through your scripting
language's functions. If someone has created a Language Binding for
your language of choice, you're all set, otherwise you'll have to create
a Plug-in for it. Language Binding Plug-ins have a few more
requirements than ordinary Plug-ins, and require a greater amount of
knowledge of the Inkscape internals, so it can take quite some time to
do properly.
Internal Extensions are in a way the reverse of a normal Extension, in
that instead of providing a way to hook into Inkscape from the outside,
they provide hooks from inside Inkscape. These are used directly by
Inkscape, such as in the case of compiled-in printing modules. Most
users will never need to write this type of extension, they are pretty
much for Inkscape core developers only.
=== Writing Your Extension ===
This section provides some guidance and examples for implementing
different kinds of Extensions.
=== Writing Script Extensions ===
=== Writing Plug-in Extensions ===
=== Writing Language Binding Plug-in Extensions ===
=== Creating an INX File ===
Every extension must have a corresponding *.inx file. This is an XML
file that provides Inkscape with information about the module and allows
it to load the info without needing to access the module itself. The
*.inx file contains enough info for Inkscape to set up menu items and
know what kinds of functionality to expect from the extension.
=== Packaging Your Extension ===
=== Contributing Your Extension to the Inkscape Community ===
Once your extension is complete, you may wish to share it with the
community. There are of course no hard and fast rules for how to share
your work, but this section illustrates some approaches.
=== Listing Your Extension ===
First, you will need to put your extension someplace that others can
find and download it. If you have adequate webspace, you could simply
upload it to your web server. More typically, you will want to upload
it to a mirroring system like SourceForge (http://www.sourceforge.net),
CPAN (http://www.cpan.org), and the like. The Inkscape project may also
be willing to host your extension; contact the admins for more info.
It can also be helpful to list your extension with one of the various
software registries, such as Freshmeat (http://www.freshmeat.net). You
should also list it on the Inkscape Wiki site.
=== Announcing Your Extension ===
After posting your extension someplace from which it can be downloaded,
you should also announce its availability, by sending an email to
inkscape-announce@lists.sourceforge.net. You may also want to announce
it on other related sites; for instance, if you've written a plug-in to
allow operation of Imagemagick from within Inkscape, it could be a good
idea to announce it to the Imagemagick list.
=== Incorporating Your Extension in to Inkscape ===
Because the intent with the extension system is to break things *out*
from the core, most extensions should be packaged and distributed
independently of the main Inkscape distribution. However, for ease of
user installation, an extension-pack can be shipped along with the core
Inkscape package. Also, certain extensions may be so critical to
Inkscape operation (such as for printing) that they should be included
in the core.
If your extension seems like it should be incorporated into the Inkscape
core, contact the Inkscape developers about this, and discuss how best
to include it in the distribution with them.
=== Conclusion ===
It is anticipated that the incorporation of this extensions capability
will bring Inkscape added power and flexibility while avoiding bloating
the core with cool-but-rarely-used functionality. Further, it empowers
users and non-core Inkscape developers to extend the application with
their own new capabilities, without needing to gain special access and
acceptance by the project. Dynamic loading of functionality will also
allow Inkscape to remain 'lean and mean', loading up functionality on an
as-needed basis, and conserving memory by unloading functionality when
it is not needed.
The key point of this design specification is the architectural concept
of separately identifying an extension's interface type, or 'Extension
Type', from its implementation method, or 'Extension Implementation'.
This feature enables Inkscape to be extended in a variety of mechanisms,
including ways not yet foreseen.
=== History and references ===
Base design taken from Ted Gould's Extension System work.
This document originally authored by Bryce Harrington, July 2004
|