diff options
Diffstat (limited to 'src/svg-profile.h')
| -rw-r--r-- | src/svg-profile.h | 287 |
1 files changed, 287 insertions, 0 deletions
diff --git a/src/svg-profile.h b/src/svg-profile.h new file mode 100644 index 000000000..9d221fc76 --- /dev/null +++ b/src/svg-profile.h @@ -0,0 +1,287 @@ +#ifndef __INK_SVG_PROFILE_H__ +#define __INK_SVG_PROFILE_H__ +/* + * A class for managing which SVG Profiles are used. + * + * Authors: + * Ted Gould <ted@gould.cx> + * + * Copyright (C) 2004 Authors + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +namespace Inkscape { + +/** + \brief A class that contains information on which SVG profiles are + marked for the object. + + The basic functionality here is to allow marking of which profiles + are supported or required by some other object. The basic + implementation of that is a bitfield, a data type that has bits + to be able to be set depending on whether or not that particular + feature is available. This implementation is a little more complex + for a coulple of reasons. + + The first reason for making it be more complex is to make it into + a nice C++ friendly class, where the actual bits aren't required + by the calling application. This is accomplished by use of the + \c SvgProfileType enum, and having the various fields in there. + + The second reason that this is more complex is that it is reasonable + that the enum will grow to be greater than the native integer of + a given system. As more profiles and distinctions are made, there + will have to be more entries in the enum. In order to combat this, + the \c BitField class was created. This creates consistent operations + independent of how many integers are used to represent the particular + bitfield. + + The entire class has been optimized for inlining and compiler reduction + of code. All entires should allow being put in a structure or other + static allocation. For most operations, simple and/or instructions + in the processor is required after optimization. + + Adding additional profiles to the class is as easy as adding entires + into the enum. Adding additional aggregates requires adding to the + enum, and adding the aggregate into the constructor for the class. +*/ +class SvgProfile { +public: + /** \brief The enum listing all the different profiles supported, and + some aggregate ones supported. + + \note This \c enum should not be used for anything other than passing + data into the constructor of \c SvgProfile. The optimization + of the constructor is best when it is passed a static value. + So, passing this enum through a function, and then constructing + the \c SvgProfile would be less than ideal. Plus, as far as + memory goes, today, they take up the same amount of memory. + */ + enum SvgProfileType { + BASIC_OPERATION = 0, /**< This describes a feature that is part + of the basic functionality of Inkscape + itself. This would be like save or open. */ + SVG_BASE_1_0, /**< The base SVG spec version 1.0 */ + SVG_BASE_1_1, /**< The base SVG spec version 1.1 */ + SVG_BASE_1_2, /**< The base SVG spec version 1.2 */ + SVG_BASE_2_0, /**< The base SVG spec version 2.0 */ + + SVG_MOBILE_TINY_1_1, /**< The mobile SVG spec Tiny profile version 1.1 */ + SVG_MOBILE_BASIC_1_1, /**< The mobile SVG spec Basic profile version 1.1 */ + SVG_MOBILE_TINY_1_2, /**< The mobile SVG spec Tiny profile version 1.2 */ + SVG_MOBILE_BASIC_1_2, /**< The mobile SVG spec Basic profile version 1.2 */ + + SVG_PRINT_1_1, /**< */ + + PROFILE_UNIQUE_CNT, /**< A marker to seperate between the entires + that are unique, and those which are + aggregates of them. */ + + SVG_BASE_ALL, /**< Every version of the SVG Base spec */ + SVG_MOBILE_ALL, /**< Every version and profile in SVG Mobile */ + SVG_TINY_ALL, /**< Every version of the tiny profile in SVG Mobile */ + SVG_BASIC_ALL, /**< Every version of the basic profile in SVG Mobile */ + ALL /**< All, everything, basically doesn't tell you anything at all */ + }; + +private: + /** \brief The core of the \c SvgProfile class, this implements a + bitfield which can be several integers large with standard + operations independent of size. */ + class BitField { + /** \brief A quick way identify the number of bits in an integer. */ + #define BITS_IN_INT (sizeof(int) * 8) + /** \brief The size of the array which is being used. */ + #define ARRAY_SIZE (((PROFILE_UNIQUE_CNT - 1) / BITS_IN_INT) + 1) + + /** \brief The actuall array holding the bitfield. */ + unsigned int bits[ARRAY_SIZE]; + + public: + /** \brief Constructor for the bitfield, it clears the \c bits + array by setting things to zero. */ + inline BitField(void) { + for (int i = 0; i < ARRAY_SIZE; i++) { + bits[i] = 0; + } + } + + /** \brief Constructs a bitfield by passing in another array + describing how the bits should look. The function + just copies the array into \c bits. */ + inline BitField(unsigned int in_bits[ARRAY_SIZE]) { + for (int i = 0; i < ARRAY_SIZE; i++) { + bits[i] = in_bits[i]; + } + } + + /** \brief The equals operator, but it doesn't do quite that. + This function checks to see if there are bits that + are similarly high in both bitfields. */ + inline bool operator == (const BitField &in_field) const { + for (int i = 0; i < ARRAY_SIZE; i++) { + if (bits[i] & in_field.bits[i] != 0) + return true; + } + return false; + } + + /** \brief A convience function to set a particular bit in the + bitfield + + This function first find which integer the bit is in by + dividing by \c BITS_IN_INT and then which bit in the + integer by getting the modulus. The selected integer is + the \c |= with a \c 1 shifted left by the possition. + */ + inline void set (const unsigned int pos) { + unsigned int array_pos = pos / BITS_IN_INT; + unsigned int bit_pos = pos % BITS_IN_INT; + bits[array_pos] |= 1 << bit_pos; + } + + /** \brief Does a bitwise \c OR on two bitfields. It does + this for the entire \c bits array. */ + inline BitField operator | (const BitField &other) const { + unsigned int local_bits[ARRAY_SIZE]; + + for (int i = 0; i < ARRAY_SIZE; i++) { + local_bits[i] = bits[i] | other.bits[i]; + } + + return BitField(local_bits); + } + + /** \brief Causes one \c BitField to take on the values + stored in a different bitfield. */ + inline BitField & operator = (const BitField &other) { + for (int i = 0; i < ARRAY_SIZE; i++) { + bits[i] = other.bits[i]; + } + + return *this; + } + + /** \brief Does a logical \c OR of the bitfield with another + bitfield. It does this by using \c |=. */ + inline BitField & operator |= (const BitField &other) { + for (int i = 0; i < ARRAY_SIZE; i++) { + bits[i] |= other.bits[i]; + } + return *this; + } + + #undef BITS_IN_INT + #undef ARRAY_SIZE + }; + + /** \brief The actual data stored on the profile. */ + BitField _profile; + + /** + \brief Create an SvgProfile with an already created bitfield + \param in_field The bitfield that should be used in the profile + + This function just copies the incoming bitfield into the one + which is allocated for this. + */ + inline SvgProfile (const BitField &in_field) { + _profile = in_field; + } + +public: + /** \brief A constructor for \c SvgProfile which sets up the bitfield + based on the \c SvgProfileType getting passed in. + + This function has basically two different modes of operation + depending on whether the requested value is a pure profile or + and aggregate. If it is pure, then that bit is set in \c _profile + and the function exits. Otherwise a case statement is used to + determine which aggregate is called, and then setting all of + the bits for that aggregate. + */ + inline SvgProfile (SvgProfileType type) { + if (type < PROFILE_UNIQUE_CNT) { + _profile.set(type); + } else { + /* Okay, so this could be done by OR'ing a bunch of these + together, but I thought that would reduce the chance of + the compiler actually figuring it all out and optimizing + everything. This is already getting pretty complex. */ + switch (type) { + case SVG_BASE_ALL: + _profile.set(SVG_BASE_1_0); + _profile.set(SVG_BASE_1_1); + _profile.set(SVG_BASE_1_2); + _profile.set(SVG_BASE_2_0); + break; + case SVG_BASIC_ALL: + _profile.set(SVG_MOBILE_BASIC_1_1); + _profile.set(SVG_MOBILE_BASIC_1_2); + break; + case SVG_TINY_ALL: + _profile.set(SVG_MOBILE_TINY_1_1); + _profile.set(SVG_MOBILE_TINY_1_2); + break; + case SVG_MOBILE_ALL: + _profile.set(SVG_MOBILE_BASIC_1_1); + _profile.set(SVG_MOBILE_BASIC_1_2); + _profile.set(SVG_MOBILE_TINY_1_1); + _profile.set(SVG_MOBILE_TINY_1_2); + break; + case ALL: + _profile.set(SVG_BASE_1_0); + _profile.set(SVG_BASE_1_1); + _profile.set(SVG_BASE_1_2); + _profile.set(SVG_BASE_2_0); + + _profile.set(SVG_MOBILE_BASIC_1_1); + _profile.set(SVG_MOBILE_BASIC_1_2); + + _profile.set(SVG_MOBILE_TINY_1_1); + _profile.set(SVG_MOBILE_TINY_1_2); + break; + }; + } + return; + }; + + /** \brief A function to check equality of two \c SvgProfiles. + It doesn't quite check equality though, it more ensures + that there is a profile supported by both objects. This + would be similar to: (a & b) != 0 in a standard bitfield + impelemtation. But is done this way for simplicity. */ + inline bool operator == (const SvgProfile &in_profile) const { + return _profile == in_profile._profile; + }; + + /** \brief A function allow combining of \c SvgProfiles with each + other into a larger \c SvgProfile. */ + inline SvgProfile operator | (const SvgProfile &other) const { + return SvgProfile(_profile | other._profile); + } + + /** \brief A quick way to add additional profiles to the currently + allocated object. */ + inline SvgProfile & operator |= (const SvgProfile &other) { + _profile |= other._profile; + return *this; + } +}; + + +} /* namespace Inkscape */ + +#endif /* __INK_SVG_PROFILE_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 : |
