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.
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 };
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 :