Code

switch to sigc++ signal for "release"
[inkscape.git] / src / svg-profile.h
1 #ifndef __INK_SVG_PROFILE_H__
2 #define __INK_SVG_PROFILE_H__
3 /*
4  * A class for managing which SVG Profiles are used.
5  *
6  * Authors:
7  *   Ted Gould <ted@gould.cx>
8  *
9  * Copyright (C) 2004 Authors
10  *
11  * Released under GNU GPL, read the file 'COPYING' for more information
12  */
14 namespace Inkscape {
16 /**
17     \brief  A class that contains information on which SVG profiles are
18             marked for the object.
20     The basic functionality here is to allow marking of which profiles
21     are supported or required by some other object.  The basic
22     implementation of that is a bitfield, a data type that has bits
23     to be able to be set depending on whether or not that particular
24     feature is available.  This implementation is a little more complex
25     for a coulple of reasons.
27     The first reason for making it be more complex is to make it into
28     a nice C++ friendly class, where the actual bits aren't required
29     by the calling application.  This is accomplished by use of the
30     \c SvgProfileType enum, and having the various fields in there.
32     The second reason that this is more complex is that it is reasonable
33     that the enum will grow to be greater than the native integer of
34     a given system.  As more profiles and distinctions are made, there
35     will have to be more entries in the enum.  In order to combat this,
36     the \c BitField class was created.  This creates consistent operations
37     independent of how many integers are used to represent the particular
38     bitfield.
39  
40     The entire class has been optimized for inlining and compiler reduction
41     of code.  All entires should allow being put in a structure or other
42     static allocation.  For most operations, simple and/or instructions
43     in the processor is required after optimization.
45     Adding additional profiles to the class is as easy as adding entires
46     into the enum.  Adding additional aggregates requires adding to the
47     enum, and adding the aggregate into the constructor for the class.
48 */
49 class SvgProfile {
50 public:
51     /** \brief  The enum listing all the different profiles supported, and
52                 some aggregate ones supported.
54         \note  This \c enum should not be used for anything other than passing
55                data into the constructor of \c SvgProfile.  The optimization
56                of the constructor is best when it is passed a static value.
57                So, passing this enum through a function, and then constructing
58                the \c SvgProfile would be less than ideal.  Plus, as far as
59                memory goes, today, they take up the same amount of memory.
60     */
61     enum SvgProfileType {
62         BASIC_OPERATION = 0,  /**< This describes a feature that is part
63                                    of the basic functionality of Inkscape
64                                    itself.  This would be like save or open. */
65         SVG_BASE_1_0,         /**< The base SVG spec version 1.0 */
66         SVG_BASE_1_1,         /**< The base SVG spec version 1.1 */
67         SVG_BASE_1_2,         /**< The base SVG spec version 1.2 */
68         SVG_BASE_2_0,         /**< The base SVG spec version 2.0 */
70         SVG_MOBILE_TINY_1_1,  /**< The mobile SVG spec Tiny profile version 1.1 */
71         SVG_MOBILE_BASIC_1_1, /**< The mobile SVG spec Basic profile version 1.1 */
72         SVG_MOBILE_TINY_1_2,  /**< The mobile SVG spec Tiny profile version 1.2 */
73         SVG_MOBILE_BASIC_1_2, /**< The mobile SVG spec Basic profile version 1.2 */
75         SVG_PRINT_1_1,        /**< */
77         PROFILE_UNIQUE_CNT,   /**< A marker to seperate between the entires
78                                    that are unique, and those which are
79                                    aggregates of them. */
81         SVG_BASE_ALL,         /**< Every version of the SVG Base spec */
82         SVG_MOBILE_ALL,       /**< Every version and profile in SVG Mobile */
83         SVG_TINY_ALL,         /**< Every version of the tiny profile in SVG Mobile */
84         SVG_BASIC_ALL,        /**< Every version of the basic profile in SVG Mobile */
85         ALL                   /**< All, everything, basically doesn't tell you anything at all */
86     };
88 private:
89     /** \brief  The core of the \c SvgProfile class, this implements a
90                 bitfield which can be several integers large with standard
91                 operations independent of size. */
92     class BitField {
93         /** \brief A quick way identify the number of bits in an integer. */
94         #define  BITS_IN_INT (sizeof(int) * 8)
95         /** \brief The size of the array which is being used. */
96         #define  ARRAY_SIZE  (((PROFILE_UNIQUE_CNT - 1) / BITS_IN_INT) + 1)
98             /** \brief The actuall array holding the bitfield. */
99             unsigned int bits[ARRAY_SIZE];
101         public:
102             /** \brief Constructor for the bitfield, it clears the \c bits
103                        array by setting things to zero. */
104             inline BitField(void) {
105                 for (int i = 0; i < ARRAY_SIZE; i++) {
106                     bits[i] = 0;
107                 }
108             }
110             /** \brief Constructs a bitfield by passing in another array
111                        describing how the bits should look.  The function
112                        just copies the array into \c bits. */
113             inline BitField(unsigned int in_bits[ARRAY_SIZE]) {
114                 for (int i = 0; i < ARRAY_SIZE; i++) {
115                     bits[i] = in_bits[i];
116                 }
117             }
119             /** \brief The equals operator, but it doesn't do quite that.
120                        This function checks to see if there are bits that
121                        are similarly high in both bitfields. */
122             inline bool operator == (const BitField &in_field) const {
123                 for (int i = 0; i < ARRAY_SIZE; i++) {
124                     if (bits[i] & in_field.bits[i] != 0)
125                         return true;
126                 }
127                 return false;
128             }
130             /** \brief A convience function to set a particular bit in the
131                        bitfield
133                 This function first find which integer the bit is in by
134                 dividing by \c BITS_IN_INT and then which bit in the
135                 integer by getting the modulus.  The selected integer is
136                 the \c |= with a \c 1 shifted left by the possition.
137             */
138             inline void set (const unsigned int pos) {
139                 unsigned int array_pos = pos / BITS_IN_INT;
140                 unsigned int bit_pos   = pos % BITS_IN_INT;
141                 bits[array_pos] |= 1 << bit_pos;
142             }
144             /** \brief Does a bitwise \c OR on two bitfields.  It does
145                        this for the entire \c bits array. */
146             inline BitField operator | (const BitField &other) const {
147                 unsigned int local_bits[ARRAY_SIZE];
149                 for (int i = 0; i < ARRAY_SIZE; i++) {
150                     local_bits[i] = bits[i] | other.bits[i];
151                 }
153                 return BitField(local_bits);
154             }
156             /** \brief  Causes one \c BitField to take on the values
157                         stored in a different bitfield. */
158             inline BitField & operator = (const BitField &other) {
159                 for (int i = 0; i < ARRAY_SIZE; i++) {
160                     bits[i] = other.bits[i];
161                 }
163                 return *this;
164             }
166             /** \brief  Does a logical \c OR of the bitfield with another
167                         bitfield.  It does this by using \c |=. */
168             inline BitField & operator |= (const BitField &other) {
169                 for (int i = 0; i < ARRAY_SIZE; i++) {
170                     bits[i] |= other.bits[i];
171                 }
172                 return *this;    
173             }
175         #undef BITS_IN_INT
176         #undef ARRAY_SIZE
177     };
178     
179     /** \brief The actual data stored on the profile. */
180     BitField _profile;
182     /**
183         \brief  Create an SvgProfile with an already created bitfield
184         \param  in_field  The bitfield that should be used in the profile
186         This function just copies the incoming bitfield into the one
187         which is allocated for this.
188     */
189     inline SvgProfile (const BitField &in_field) {
190         _profile = in_field;
191     }
193 public:
194     /** \brief A constructor for \c SvgProfile which sets up the bitfield
195                based on the \c SvgProfileType getting passed in.
197         This function has basically two different modes of operation
198         depending on whether the requested value is a pure profile or
199         and aggregate.  If it is pure, then that bit is set in \c _profile
200         and the function exits.  Otherwise a case statement is used to
201         determine which aggregate is called, and then setting all of
202         the bits for that aggregate.
203     */
204     inline SvgProfile (SvgProfileType type) {
205         if (type < PROFILE_UNIQUE_CNT) {
206             _profile.set(type);
207         } else {
208             /* Okay, so this could be done by OR'ing a bunch of these
209                together, but I thought that would reduce the chance of
210                the compiler actually figuring it all out and optimizing
211                everything.  This is already getting pretty complex. */
212             switch (type) {
213                 case SVG_BASE_ALL:
214                     _profile.set(SVG_BASE_1_0);
215                     _profile.set(SVG_BASE_1_1);
216                     _profile.set(SVG_BASE_1_2);
217                     _profile.set(SVG_BASE_2_0);
218                     break;
219                 case SVG_BASIC_ALL:
220                     _profile.set(SVG_MOBILE_BASIC_1_1);
221                     _profile.set(SVG_MOBILE_BASIC_1_2);
222                     break;
223                 case SVG_TINY_ALL:
224                     _profile.set(SVG_MOBILE_TINY_1_1);
225                     _profile.set(SVG_MOBILE_TINY_1_2);
226                     break;
227                 case SVG_MOBILE_ALL:
228                     _profile.set(SVG_MOBILE_BASIC_1_1);
229                     _profile.set(SVG_MOBILE_BASIC_1_2);
230                     _profile.set(SVG_MOBILE_TINY_1_1);
231                     _profile.set(SVG_MOBILE_TINY_1_2);
232                     break;
233                 case ALL:
234                     _profile.set(SVG_BASE_1_0);
235                     _profile.set(SVG_BASE_1_1);
236                     _profile.set(SVG_BASE_1_2);
237                     _profile.set(SVG_BASE_2_0);
239                     _profile.set(SVG_MOBILE_BASIC_1_1);
240                     _profile.set(SVG_MOBILE_BASIC_1_2);
242                     _profile.set(SVG_MOBILE_TINY_1_1);
243                     _profile.set(SVG_MOBILE_TINY_1_2);
244                     break;
245             };
246         }
247         return;    
248     };
250     /** \brief A function to check equality of two \c SvgProfiles.
251                It doesn't quite check equality though, it more ensures
252                that there is a profile supported by both objects.  This
253                would be similar to: (a & b) != 0 in a standard bitfield
254                impelemtation.  But is done this way for simplicity. */
255     inline bool operator == (const SvgProfile &in_profile) const {
256         return _profile == in_profile._profile;
257     };
259     /** \brief A function allow combining of \c SvgProfiles with each
260                other into a larger \c SvgProfile. */
261     inline SvgProfile operator | (const SvgProfile &other) const {
262         return SvgProfile(_profile | other._profile);
263     }
265     /** \brief A quick way to add additional profiles to the currently
266                allocated object. */
267     inline SvgProfile & operator |= (const SvgProfile &other) {
268         _profile |= other._profile;
269         return *this;
270     }
271 };
274 }  /* namespace Inkscape */
276 #endif /* __INK_SVG_PROFILE_H__ */
278 /*
279   Local Variables:
280   mode:c++
281   c-file-style:"stroustrup"
282   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
283   indent-tabs-mode:nil
284   fill-column:99
285   End:
286 */
287 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :