summaryrefslogtreecommitdiffstats
path: root/src/extension/implementation/plugin.cpp
blob: aebc94b8d6176a1e9942d27867a05f12d9f431bf (plain)
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
/** \file
 * The implementation of pluggable objects into Inkscape.
 *
 * Author:  Ted Gould <ted@gould.cx>
 * Copyright (c) 2004-2005
 *
 * This code is licensed under the GNU GPL.  See COPYING for details.
 *
 * This file implements loadable modules for Inkscape.
 */
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdio.h>

#include <glibmm/module.h>
#include <glibmm/fileutils.h>
#include <path-prefix.h>
#include "extension/extension.h"
#include "xml/repr.h"
#include "plugin.h"
#include "plugin-link.h"

namespace Inkscape {
namespace Extension {
namespace Implementation {

/** \brief Create an object by nulling everything out. */
Plugin::Plugin(void)
{
    _module = NULL;
    _symTable = NULL;

    return;
}

/**
    \brief  Oh, so someone actually wants to use this plugin!  We better
            go and grab it then!
    \param  module  Unused except to pass to the plugin's load function.
    \return Whether the load was successful.  Hopefully always TRUE.

    Okay, first things first, are modules supported on this platform?  That
    is a good first check.  Also, is this plugin already loaded?  If so
    don't reload it.

    If all those are true we need to figure out the filename that needs
    to be loaded.  This involves going through the definition of the plugin
    for the \c name field.  It is then run though the \c build_path function
    to add the .so or .dll on the end.  The path that is used is the
    \c INKSCAPE_PLUGINDIR.

    The module is then loaded into RAM by Glib.  I'm sure there is lots
    of magic involved here -- but we don't have to worry about it, we
    just check to make sure it worked.

    After it is loaded into memory the function lookup table is grabbed
    and then the load function for the plugin is called.
*/
bool
Plugin::load(Inkscape::Extension::Extension *module)
{
    if (!Glib::Module::get_supported()) {
        return FALSE;
    }

    if (module->loaded()) {
        return TRUE;
    }

    Inkscape::XML::Node * child_repr = sp_repr_children(module->get_repr());
    const gchar * name = NULL;
    while (child_repr != NULL) {
        if (!strcmp(child_repr->name(), "plugin")) {
            child_repr = sp_repr_children(child_repr);
            while (child_repr != NULL) {
                if (!strcmp(child_repr->name(), "name")) {
                    name = sp_repr_children(child_repr)->content();
                }
                child_repr = sp_repr_next(child_repr);
            }
        }
        child_repr = sp_repr_next(child_repr);
    }

    if (name == NULL) {
        return FALSE;
    }

    std::string path = Glib::Module::build_path(INKSCAPE_PLUGINDIR, name);
    // std::cout << "Load path: " << path << std::endl;
    _module = new Glib::Module(path);

    if (!(bool)_module || _module == NULL) {
        printf("Loading failed\n");
        return FALSE;
    }

    /* Grab symbols */
    void * voidpntr;
    if (!_module->get_symbol(INKSCAPE_PLUGIN_NAME_STR, voidpntr)) {
        // printf("Error loading library\n");
        // std::cout << "Last error: " << _module->get_last_error() << std::endl;
        return FALSE;
    }
    _symTable = (inkscape_plugin_function_table *)voidpntr;

    if (_symTable->version != INKSCAPE_PLUGIN_VERSION) {
        /* Someday this could adapt older versions so that we could
           be compatible -- but not today */
        return FALSE;
    }

    if (_symTable->load != NULL) {
        return (bool)_symTable->load((inkscape_extension *)module);
    }

    return TRUE;
}

/**
    \brief  No one is interested in this plugin for now.  It is removed
            to save memory.
    \param  module  The module of this implementation, passed to unload.
    \return None.

    Call the unload function of the plugin, then delete the symbol table
    and the module itself.  Put everything back to NULL.
*/
void
Plugin::unload(Inkscape::Extension::Extension *module)
{
    _symTable->unload((inkscape_extension *)module);
    _symTable = NULL;
    delete _module;
    _module = NULL;
    return;
}

/**
    \brief  Just check to make sure everything exists.  This makes sure
            that the loadable file exits.
    \param  module  Unused.
    \return The status of the check.  TRUE means that it passed.

    This function builds the path name out of the XML definition of the
    plugin.  It does this by looking for the \c name parameter.  It then
    uses \c build_path to add the .so or .dll and adds in the \c INKSCAPE_PLUGINDIR
    to the front of it.  Then the \c file_test function is used to make
    sure it exists.
*/
bool
Plugin::check(Inkscape::Extension::Extension *module)
{
    Inkscape::XML::Node * child_repr = sp_repr_children(module->get_repr());
    const gchar * name = NULL;
    while (child_repr != NULL) {
        if (!strcmp(child_repr->name(), "plugin")) {
            child_repr = sp_repr_children(child_repr);
            while (child_repr != NULL) {
                if (!strcmp(child_repr->name(), "name")) {
                    name = sp_repr_children(child_repr)->content();
                }
                child_repr = sp_repr_next(child_repr);
            }
        }
        child_repr = sp_repr_next(child_repr);
    }

    if (name == NULL) {
        return FALSE;
    }

    std::string path = Glib::Module::build_path(INKSCAPE_PLUGINDIR, name);
    // std::cout << "Path: " << path << std::endl;
    if (!Glib::file_test(path, Glib::FILE_TEST_EXISTS | Glib::FILE_TEST_IS_EXECUTABLE)) {
        // std::cout << "Failed!" << std::endl;
        return FALSE;
    }

    // std::cout << "No Problem." << std::endl;
    return TRUE;
}

Gtk::Widget *
Plugin::prefs_input(Inkscape::Extension::Input *module, gchar const *filename)
{
    return Inkscape::Extension::Implementation::Implementation::prefs_input(module, filename);
}

/*
    \brief  Function to call the open in the plugin.
    \param  module    Passed on
    \param  filename  Passed on
    \return The document that is opened or NULL for error.

    This function looks in the symbol table to see if there is an open
    function.  If there is, it is called, otherwise the standard implementation
    function is used instead.
*/
SPDocument *
Plugin::open(Inkscape::Extension::Input *module, gchar const *filename)
{
    if (_symTable->open != NULL) {
        return _symTable->open((inkscape_extension *)module, filename);
    } else {
        return Inkscape::Extension::Implementation::Implementation::open(module, filename);
    }
}

Gtk::Widget *
Plugin::prefs_output(Inkscape::Extension::Output *module)
{
    return Inkscape::Extension::Implementation::Implementation::prefs_output(module);
}

void
Plugin::save(Inkscape::Extension::Output *module, SPDocument *doc, gchar const *filename)
{
    return Inkscape::Extension::Implementation::Implementation::save(module, doc, filename);
}

Gtk::Widget *
Plugin::prefs_effect(Inkscape::Extension::Effect *module, Inkscape::UI::View::View * view)
{
    if (_symTable->prefs_effect != NULL) {
        return _symTable->prefs_effect((inkscape_extension *)module, view);
    } else {
        return Inkscape::Extension::Implementation::Implementation::prefs_effect(module, view);
    }
}

void 
Plugin::effect(Inkscape::Extension::Effect *module, Inkscape::UI::View::View *document)
{
    if (_symTable->effect != NULL) {
        return _symTable->effect((inkscape_extension *)module, document);
    } else {
        return Inkscape::Extension::Implementation::Implementation::effect(module, document);
    }
}

unsigned
Plugin::setup(Inkscape::Extension::Print *module)
{
    return Inkscape::Extension::Implementation::Implementation::setup(module);
}

unsigned
Plugin::set_preview(Inkscape::Extension::Print *module)
{
    return Inkscape::Extension::Implementation::Implementation::set_preview(module);
}

unsigned
Plugin::begin(Inkscape::Extension::Print *module, SPDocument *doc)
{
    return Inkscape::Extension::Implementation::Implementation::begin(module, doc);
}

unsigned
Plugin::finish(Inkscape::Extension::Print *module)
{
    return Inkscape::Extension::Implementation::Implementation::finish(module);
}

bool
Plugin::textToPath(Inkscape::Extension::Print *ext)
{
    return Inkscape::Extension::Implementation::Implementation::finish(ext);
}

unsigned
Plugin::bind(Inkscape::Extension::Print *module, NRMatrix const *transform, float opacity)
{
    return Inkscape::Extension::Implementation::Implementation::bind(module, transform, opacity);
}

unsigned
Plugin::release(Inkscape::Extension::Print *module)
{
    return Inkscape::Extension::Implementation::Implementation::release(module);
}

unsigned
Plugin::comment(Inkscape::Extension::Print *module, const char * comment)
{
    return Inkscape::Extension::Implementation::Implementation::comment(module,comment);
}

unsigned
Plugin::fill(Inkscape::Extension::Print *module, NRBPath const *bpath, NRMatrix const *ctm, SPStyle const *style, NRRect const *pbox, NRRect const *dbox, NRRect const *bbox)
{
    return Inkscape::Extension::Implementation::Implementation::fill(module, bpath, ctm, style, pbox, dbox, bbox);
}

unsigned
Plugin::stroke(Inkscape::Extension::Print *module, NRBPath const *bpath, NRMatrix const *transform, SPStyle const *style, NRRect const *pbox, NRRect const *dbox, NRRect const *bbox)
{
    return Inkscape::Extension::Implementation::Implementation::stroke(module, bpath, transform, style, pbox, dbox, bbox);
}

unsigned
Plugin::image(Inkscape::Extension::Print *module, unsigned char *px, unsigned int w, unsigned int h, unsigned int rs, NRMatrix const *transform, SPStyle const *style)
{
    return Inkscape::Extension::Implementation::Implementation::image(module, px, w, h, rs, transform, style);
}

unsigned
Plugin::text(Inkscape::Extension::Print *module, char const *text, NR::Point p, SPStyle const *style)
{
    return Inkscape::Extension::Implementation::Implementation::text(module, text, p, style);
}

}  /* namespace Implementation */
}  /* namespace Extension */
}  /* namespace Inkscape */

/*
  Local Variables:
  mode:c++
  c-file-style:"stroustrup"
  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
  indent-tabs-mode:nil
  fill-column:99
  End:
*/
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :