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
|
<?xml version="1.0"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd">
<book lang="en_us">
<title>Inkscape Extensions</title>
<chapter>
<title>Introduction</title>
<para>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.</para>
<para>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.</para>
<para>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.</para>
</chapter>
<chapter>
<title>Terminology</title>
<para><emphasis>Extension</emphasis> - 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.</para>
<para><emphasis>Extension Type</emphasis> - Establishes the functional interface that the Extension provides, including the types of messages it handles and what is contained in its data structures.</para>
<para><emphasis>Extension Implementation</emphasis> - Defines how the extension is accessed; i.e. through message passing, pipe/exec calls with commandline arguments, direct function calls, etc.</para>
<para><emphasis>Plug-in</emphasis> - 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.</para>
<para><emphasis>Script</emphasis> - 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.</para>
<para><emphasis>Language Binding</emphasis> - 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.</para>
<para><emphasis>INX</emphasis> - <emphasis>'INkscape eXtension'</emphasis> - The filename extension used for XML metadata files that describe each Inkscape Extension.</para>
<para><emphasis>Internal Extension</emphasis> - 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.</para>
</chapter>
<chapter>
<title>Requirements</title>
<itemizedlist>
<listitem><para>Uses a general language binding system so it's easy to add new language binding support.</para></listitem>
<listitem><para>Allows direct interaction with the document object model including changing.</para></listitem>
<listitem><para>Allows some limited interaction with the Inkscape UI such as manipulating grids, overlays, etc.</para></listitem>
<listitem><para>Allows direct interaction with file load/save/export/print subsystem.</para></listitem>
<listitem><para>Guaranteed to work properly with the undo system, even if the extension is not written carefully.</para></listitem>
<listitem><para>Well documented so is easy for people to learn how to make new extensions.</para></listitem>
<listitem><para>Each extension can be implemented, distributed, and managed independently of the core project.</para></listitem>
<listitem><para>Icons, buttons, and other UI elements for extensions fit seamlessly into main application GUI.</para></listitem>
<listitem><para>User can easily select which extensions to automatically load into application at startup.</para></listitem>
<listitem><para>Loading of extensions shall not seriously slow startup time or make a major impact on memory footprint.</para></listitem>
<listitem><para>Failure of a extension shall not leave the drawing in an inconsistent state.</para></listitem>
<listitem><para>Main application must gracefully recover from extension crashes or other serious problems with extension execution.</para></listitem>
<listitem><para>Dependencies for particular extensions must be clearly identified for user if missing.</para></listitem>
</itemizedlist>
</chapter>
<chapter>
<title>Overview</title>
<para>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.</para>
<para>The first kind of categorization is called the <emphasis>Extension Type</emphasis>. 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.</para>
<para>The second is the <emphasis>Extension Implementation</emphasis>. 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.</para>
<para>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.</para>
<para>For the purposes of this document, however, we focus on just the following Types and Implementations:</para>
<variablelist>
<varlistentry>
<term>Extension Types</term>
<listitem>
<variablelist>
<varlistentry>
<term>Input</term>
<listitem>
<para>loading various file formats</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Output</term>
<listitem>
<para>saving as various file formats</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Effect</term>
<listitem>
<para>apply some sort of change to SVG elements in the doc</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Print</term>
<listitem>
<para>prints using different drivers or modes</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Collection</term>
<listitem>
<para>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</para>
</listitem>
</varlistentry>
</variablelist>
</listitem>
</varlistentry>
<varlistentry>
<term>Extension Implementations</term>
<listitem>
<variablelist>
<varlistentry>
<term>Internal</term>
<listitem>
<para>code that is internal to Inkscape which uses the extension system for some functionality</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Script</term>
<listitem>
<para>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.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Plug-in</term>
<listitem>
<para>a loadable module with a message handler routine that receives messages and that operates on the Inkscape API functions directly.</para>
</listitem>
</varlistentry>
</variablelist>
</listitem>
</varlistentry>
</variablelist>
</chapter>
<chapter>
<title>Extension System Basics</title>
<para>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.</para>
<section>
<title>Extension Base Class</title>
<para>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:</para>
<variablelist>
<varlistentry>
<term>ID</term>
<para>A unique identifier for this extension that is used for referring to the extension and naming its parameters in the configuration files.</para>
</varlistentry>
<varlistentry>
<term>Name</term>
<para>The textual name of the extension, it is used for user interaction with the extension. It is used for users to identify the extension.</para>
</varlistentry>
<varlistentry>
<term>Parameters</term>
<para>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.</para>
</varlistentry>
</variablelist>
</section>
<section>
<title>Extension Registry</title>
<para>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).</para>
<para>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.</para>
<para>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.</para>
</section>
<section>
<title>Handling Preferences</title>
<para>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.</para>
<para>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.</para>
<para>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.</para>
</section>
<section>
<title>INX Files</title>
<para>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).</para>
<para>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.</para>
</section>
</chapter>
<chapter>
<title>Extension Types</title>
<para>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.</para>
<section>
<title>Input</title>
<para>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.</para>
<para>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.</para>
</section>
<section>
<title>Output</title>
<para>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.</para>
<para>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.</para>
</section>
<section>
<title>Effect</title>
<para>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.</para>
</section>
<section>
<title>Print</title>
<para>The Print Extension Type is for extensions that interface with printing subsystems. Examples would be Win32, postscript, and GNOME Print.</para>
</section>
<section>
<title>Collection</title>
</section>
</chapter>
<chapter>
<title>Creating Extensions</title>
<para>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.</para>
<section>
<title>Selecting an Extension Strategy</title>
<para>First of all, you will need to select the method you'll use for creating your extension.</para>
<para>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.</para>
<para>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.</para>
<para>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++.</para>
<para>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.</para>
<para>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.</para>
</section>
<section>
<title>Writing Your Extension</title>
<para>This section provides some guidance and examples for implementing different kinds of Extensions.</para>
<section>
<title>Writing Script Extensions</title>
</section>
<section>
<title>Writing Plug-in Extensions</title>
</section>
<section>
<title>Writing Language Binding Plug-in Extensions</title>
</section>
</section>
<section>
<title>Creating an INX File</title>
<para>Every extension must have a corrosponding *.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.</para>
</section>
<section>
<title>Packaging Your Extension</title>
</section>
<section>
<title>Contributing Your Extensino to the Inkscape Community</title>
<para>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.</para>
<section>
<title>Listing Your Extension</title>
<para>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.</para>
<para>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.</para>
</section>
<section>
<title>Announcing Your Extension</title>
<para>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.</para>
</section>
<section>
<title>Incorporating Your Extension in to Inkscape</title>
<para>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.</para>
<para>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.</para>
</section>
</section>
</chapter>
<chapter>
<title>Conclusion</title>
<para>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.</para>
<para>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.</para>
</chapter>
<chapter>
<title>History and references</title>
<para>Base design taken from Ted Gould's Extension System work.</para>
<para>This document originally authored by Bryce Harrington, July 2004</para>
</chapter>
</book>
|