summaryrefslogtreecommitdiffstats
path: root/src/svg-profile.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/svg-profile.h')
-rw-r--r--src/svg-profile.h287
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 :