~inkscape.dev/inkscape/trunk

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
#ifndef SEEN_SP_DOCUMENT_H
#define SEEN_SP_DOCUMENT_H

/** \file
 * SPDocument: Typed SVG document implementation
 */
/* Authors:
 *   Lauris Kaplinski <lauris@kaplinski.com>
 *   MenTaLguY <mental@rydia.net>
 *   Jon A. Cruz <jon@joncruz.org>
 *   Abhishek Sharma
 *
 * Copyright (C) 2004-2005 MenTaLguY
 * Copyright (C) 1999-2002 Lauris Kaplinski
 * Copyright (C) 2000-2001 Ximian, Inc.
 *
 * Released under GNU GPL, read the file 'COPYING' for more information
 */

#include <stddef.h>
#include <sigc++/sigc++.h>
#include "libcroco/cr-cascade.h"
#include <2geom/forward.h>
#include "inkgc/gc-managed.h"
#include "gc-finalized.h"
#include "gc-anchored.h"
#include <glibmm/ustring.h>
#include <boost/ptr_container/ptr_list.hpp>
#include <vector>
#include <set>
#include <deque>

// This variable is introduced with 0.92.1
// with the introduction of automatic fix 
// for files detected to have been created 
// with previous versions to have a similar
// look in 0.92+.
extern bool sp_no_convert_text_baseline_spacing;



// This variable is introduced with 0.92.1
// with the introduction of automatic fix 
// for files detected to have been created 
// with previous versions to have a similar
// look in 0.92+.
extern bool sp_do_not_fix_pre_92;



namespace Avoid {
class Router;
}

class  SPItem;
class  SPObject;
class SPGroup;
class SPRoot;

namespace Inkscape {
    class Selection; 
    class UndoStackObserver;
    class EventLog;
    class ProfileManager;
    namespace XML {
        struct Document;
        class Node;
    }
    namespace Util {
        class Unit;
        class Quantity;
    }
}

class SPDefs;
class SP3DBox;
class Persp3D;
class Persp3DImpl;
class SPItemCtx;

namespace Proj {
    class TransfMat3x4;
}

struct SPDocumentPrivate;

/// Typed SVG document implementation.
class SPDocument : public Inkscape::GC::Managed<>,
                    public Inkscape::GC::Finalized,
                    public Inkscape::GC::Anchored
{
// Note: multiple public and private sections is not a good practice, but happens
// in this class as transitional to fixing encapsulation:
public:
    typedef sigc::signal<void, SPObject *> IDChangedSignal;
    typedef sigc::signal<void> ResourcesChangedSignal;
    typedef sigc::signal<void, unsigned> ModifiedSignal;
    typedef sigc::signal<void, char const *> URISetSignal;
    typedef sigc::signal<void, double, double> ResizedSignal;
    typedef sigc::signal<void> ReconstructionStart;
    typedef sigc::signal<void> ReconstructionFinish;
    typedef sigc::signal<void> CommitSignal;

    SPDocument();
    virtual ~SPDocument();

    sigc::connection connectDestroy(sigc::signal<void>::slot_type slot);


    unsigned int keepalive : 1;
    unsigned int virgin    : 1; ///< Has the document never been touched?
    unsigned int modified_since_save : 1;

    Inkscape::XML::Document *rdoc; ///< Our Inkscape::XML::Document
    Inkscape::XML::Node *rroot; ///< Root element of Inkscape::XML::Document
private:
    SPRoot *root;             ///< Our SPRoot
public:
    CRCascade *style_cascade;

protected:
    char *uri;   ///< A filename (not a URI yet), or NULL
    char *base;  ///< To be used for resolving relative hrefs.
    char *name;  ///< basename(uri) or other human-readable label for the document.

public:

    SPDocumentPrivate *priv;

    /// Last action key
    Glib::ustring actionkey;

    /// Handler ID
    unsigned modified_id;
    
    /// Connector rerouting handler ID
    unsigned rerouting_handler_id;

    Inkscape::ProfileManager* profileManager;

    // Instance of the connector router
    Avoid::Router *router;

    std::vector<SPObject *> _collection_queue;

    bool oldSignalsConnected;

    /** Returns our SPRoot */
    SPRoot *getRoot() { return root; }
    SPRoot const *getRoot() const { return root; }

    Inkscape::XML::Node *getReprRoot() { return rroot; }

    /** Our Inkscape::XML::Document. */
    Inkscape::XML::Document *getReprDoc() { return rdoc; }
    Inkscape::XML::Document const *getReprDoc() const { return rdoc; }

    /** A filename (not a URI yet), or NULL */
    char const *getURI() const { return uri; }
    void setUri(char const *uri);

    /** To be used for resolving relative hrefs. */
    char const *getBase() const { return base; };
    void setBase( char const* base );

    /** basename(uri) or other human-readable label for the document. */
    char const* getName() const { return name; }

    /** Return the main defs object for the document. */
    SPDefs *getDefs();


    void setCurrentPersp3D(Persp3D * const persp);
    inline void setCurrentPersp3DImpl(Persp3DImpl * const persp_impl) { current_persp3d_impl = persp_impl; }
    /*
     * getCurrentPersp3D returns current_persp3d (if non-NULL) or the first
     * perspective in the defs. If no perspective exists, returns NULL.
     */
    Persp3D * getCurrentPersp3D();
    Persp3DImpl * getCurrentPersp3DImpl();

    void getPerspectivesInDefs(std::vector<Persp3D*> &list) const;

    unsigned int numPerspectivesInDefs() const {
        std::vector<Persp3D*> list;
        getPerspectivesInDefs(list);
        return list.size();
    }

    sigc::connection connectModified(ModifiedSignal::slot_type slot);
    sigc::connection connectURISet(URISetSignal::slot_type slot);
    sigc::connection connectResized(ResizedSignal::slot_type slot);
    sigc::connection connectCommit(CommitSignal::slot_type slot);

    void bindObjectToId(char const *id, SPObject *object);
    SPObject *getObjectById(Glib::ustring const &id) const;
    SPObject *getObjectById(char const *id) const;
    sigc::connection connectIdChanged(const char *id, IDChangedSignal::slot_type slot);

    std::vector<SPObject *> getObjectsByClass(Glib::ustring const &klass) const;
    std::vector<SPObject *> getObjectsByElement(Glib::ustring const &element) const;
    std::vector<SPObject *> getObjectsBySelector(Glib::ustring const &selector) const;
    
    void bindObjectToRepr(Inkscape::XML::Node *repr, SPObject *object);
    SPObject *getObjectByRepr(Inkscape::XML::Node *repr) const;

    Glib::ustring getLanguage() const;

    void queueForOrphanCollection(SPObject *object);
    void collectOrphans();

    void _emitModified();

    void addUndoObserver(Inkscape::UndoStackObserver& observer);
    void removeUndoObserver(Inkscape::UndoStackObserver& observer);

    bool _updateDocument();

    /// Are we currently in a transition between two "known good" states of the document?
    bool isSeeking() const;

    bool isModifiedSinceSave() const { return modified_since_save; }
    void setModifiedSinceSave(bool const modified = true);

private:
    SPDocument(SPDocument const &); // no copy
    void operator=(SPDocument const &); // no assign

    Persp3D *current_persp3d; /**< Currently 'active' perspective (to which, e.g., newly created boxes are attached) */
    Persp3DImpl *current_persp3d_impl;

    // A list of svg documents being used or shown within this document
    boost::ptr_list<SPDocument> _child_documents;
    // Conversely this is a parent document because this is a child.
    SPDocument *_parent_document;

public:
    sigc::connection connectReconstructionStart(ReconstructionStart::slot_type slot);
    sigc::connection connectReconstructionFinish(ReconstructionFinish::slot_type slot);
    void emitReconstructionStart(void);
    void emitReconstructionFinish(void);

    unsigned long serial() const;
    void reset_key(void *dummy);
    sigc::connection _selection_changed_connection;
    sigc::connection _desktop_activated_connection;

    sigc::connection connectResourcesChanged(char const *key, SPDocument::ResourcesChangedSignal::slot_type slot);

    void fitToRect(Geom::Rect const &rect, bool with_margins = false);
    static SPDocument *createNewDoc(char const*uri, unsigned int keepalive,
            bool make_new = false, SPDocument *parent=NULL );
    static SPDocument *createNewDocFromMem(char const*buffer, int length, unsigned int keepalive);
           SPDocument *createChildDoc(std::string const &uri);

    /**
     * Returns the bottommost item from the list which is at the point, or NULL if none.
     */
    static SPItem *getItemFromListAtPointBottom(unsigned int dkey, SPGroup *group, const std::vector<SPItem*> &list, Geom::Point const &p, bool take_insensitive = false);

    static SPDocument *createDoc(Inkscape::XML::Document *rdoc, char const *uri,
            char const *base, char const *name, unsigned int keepalive,
            SPDocument *parent);

    SPDocument *doRef();
    SPDocument *doUnref();
    Inkscape::Util::Unit const* getDisplayUnit() const;
    void setDocumentScale( const double scaleX, const double scaleY );
    void setDocumentScale( const double scale );
    Geom::Scale getDocumentScale() const;
    Inkscape::Util::Quantity getWidth() const;
    Inkscape::Util::Quantity getHeight() const;
    Geom::Rect getViewBox() const;
    Geom::Point getDimensions() const;
    Geom::OptRect preferredBounds() const;
    void setWidthAndHeight(const Inkscape::Util::Quantity &width, const Inkscape::Util::Quantity &height, bool changeSize=true);
    void setWidth(const Inkscape::Util::Quantity &width, bool changeSize=true);
    void setHeight(const Inkscape::Util::Quantity &height, bool changeSize=true);
    void setViewBox(const Geom::Rect &viewBox);
    void requestModified();
    int ensureUpToDate();
    bool addResource(char const *key, SPObject *object);
    bool removeResource(char const *key, SPObject *object);
    const std::vector<SPObject *> getResourceList(char const *key) const;
    std::vector<SPItem*> getItemsInBox(unsigned int dkey, Geom::Rect const &box, bool into_groups = false) const;
    std::vector<SPItem*> getItemsPartiallyInBox(unsigned int dkey, Geom::Rect const &box, bool into_groups = false) const;
    SPItem *getItemAtPoint(unsigned int key, Geom::Point const &p, bool into_groups, SPItem *upto = NULL) const;
    std::vector<SPItem*> getItemsAtPoints(unsigned const key, std::vector<Geom::Point> points, bool all_layers = true, size_t limit = 0) const ;
    SPItem *getGroupAtPoint(unsigned int key,  Geom::Point const &p) const;

    void changeUriAndHrefs(char const *uri);
    void emitResizedSignal(double width, double height);
	
    unsigned int vacuumDocument();

    void importDefs(SPDocument *source);

private:
    void do_change_uri(char const *const filename, bool const rebase);
    void setupViewport(SPItemCtx *ctx);
    void importDefsNode(SPDocument *source, Inkscape::XML::Node *defs, Inkscape::XML::Node *target_defs);
    void build_flat_item_list(unsigned int dkey, SPGroup *group, gboolean into_groups) const;
    mutable std::deque<SPItem*> _node_cache;
    mutable bool _node_cache_valid;
};

/*
 * Ideas: How to overcome style invalidation nightmare
 *
 * 1. There is reference request dictionary, that contains
 * objects (styles) needing certain id. Object::build checks
 * final id against it, and invokes necesary methods
 *
 * 2. Removing referenced object is simply prohibited -
 * needs analyse, how we can deal with situations, where
 * we simply want to ungroup etc. - probably we need
 * Repr::reparent method :( [Or was it ;)]
 *
 */

#endif // SEEN_SP_DOCUMENT_H

/*
  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:fileencoding=utf-8:textwidth=99 :