#ifndef __CSS_HH__ #define __CSS_HH__ #include "dw/core.hh" #include "doctree.hh" /* Origin and weight. Used only internally.*/ typedef enum { CSS_PRIMARY_USER_AGENT, CSS_PRIMARY_USER, CSS_PRIMARY_AUTHOR, CSS_PRIMARY_AUTHOR_IMPORTANT, CSS_PRIMARY_USER_IMPORTANT, CSS_PRIMARY_LAST, } CssPrimaryOrder; /* * Lengths are represented as int in the following way: * * +---+ - - - +---+---+- - - - - -+---+---+---+---+ * | integer part | decimal fraction | type | * +---+ - - - +---+---+- - - - - -+---+---+---+---+ * n-1 19 18 3 2 1 0 * * | <------ fixed point value ------> | * * where type is one of the CSS_LENGTH_TYPE_* values. */ typedef int CssLength; enum { CSS_LENGTH_TYPE_PX, CSS_LENGTH_TYPE_MM, /* "cm", "in", "pt" and "pc" are converted into millimeters. */ CSS_LENGTH_TYPE_EM, CSS_LENGTH_TYPE_EX, CSS_LENGTH_TYPE_PERCENTAGE, CSS_LENGTH_TYPE_RELATIVE, /* This does not exist in CSS but is used in HTML */ CSS_LENGTH_TYPE_AUTO /* This can be used as a simple value. */ }; #define CSS_CREATE_LENGTH(v, t) ( ( (int)((v) * (1 << 19)) & ~7 ) | (t) ) #define CSS_LENGTH_VALUE(l) ( ( (float)((l) & ~7) ) / (1 << 19) ) #define CSS_LENGTH_TYPE(l) ((l) & 7) /** * \brief This class holds a CSS property and value pair. */ class CssProperty { public: typedef union { int intVal; const char *strVal; } Value; typedef enum { CSS_PROPERTY_BACKGROUND_ATTACHMENT, CSS_PROPERTY_BACKGROUND_COLOR, CSS_PROPERTY_BACKGROUND_IMAGE, CSS_PROPERTY_BACKGROUND_POSITION, CSS_PROPERTY_BACKGROUND_REPEAT, CSS_PROPERTY_BORDER_BOTTOM_COLOR, CSS_PROPERTY_BORDER_BOTTOM_STYLE, CSS_PROPERTY_BORDER_BOTTOM_WIDTH, CSS_PROPERTY_BORDER_COLLAPSE, CSS_PROPERTY_BORDER_LEFT_COLOR, CSS_PROPERTY_BORDER_LEFT_STYLE, CSS_PROPERTY_BORDER_LEFT_WIDTH, CSS_PROPERTY_BORDER_RIGHT_COLOR, CSS_PROPERTY_BORDER_RIGHT_STYLE, CSS_PROPERTY_BORDER_RIGHT_WIDTH, CSS_PROPERTY_BORDER_SPACING, CSS_PROPERTY_BORDER_TOP_COLOR, CSS_PROPERTY_BORDER_TOP_STYLE, CSS_PROPERTY_BORDER_TOP_WIDTH, CSS_PROPERTY_BOTTOM, CSS_PROPERTY_CAPTION_SIDE, CSS_PROPERTY_CLEAR, CSS_PROPERTY_CLIP, CSS_PROPERTY_COLOR, CSS_PROPERTY_CONTENT, CSS_PROPERTY_COUNTER_INCREMENT, CSS_PROPERTY_COUNTER_RESET, CSS_PROPERTY_CURSOR, CSS_PROPERTY_DIRECTION, CSS_PROPERTY_DISPLAY, CSS_PROPERTY_EMPTY_CELLS, CSS_PROPERTY_FLOAT, CSS_PROPERTY_FONT_FAMILY, CSS_PROPERTY_FONT_SIZE, CSS_PROPERTY_FONT_SIZE_ADJUST, CSS_PROPERTY_FONT_STRETCH, CSS_PROPERTY_FONT_STYLE, CSS_PROPERTY_FONT_VARIANT, CSS_PROPERTY_FONT_WEIGHT, CSS_PROPERTY_HEIGHT, CSS_PROPERTY_LEFT, CSS_PROPERTY_LETTER_SPACING, CSS_PROPERTY_LINE_HEIGHT, CSS_PROPERTY_LIST_STYLE_IMAGE, CSS_PROPERTY_LIST_STYLE_POSITION, CSS_PROPERTY_LIST_STYLE_TYPE, CSS_PROPERTY_MARGIN_BOTTOM, CSS_PROPERTY_MARGIN_LEFT, CSS_PROPERTY_MARGIN_RIGHT, CSS_PROPERTY_MARGIN_TOP, CSS_PROPERTY_MARKER_OFFSET, CSS_PROPERTY_MARKS, CSS_PROPERTY_MAX_HEIGHT, CSS_PROPERTY_MAX_WIDTH, CSS_PROPERTY_MIN_HEIGHT, CSS_PROPERTY_MIN_WIDTH, CSS_PROPERTY_OUTLINE_COLOR, CSS_PROPERTY_OUTLINE_STYLE, CSS_PROPERTY_OUTLINE_WIDTH, CSS_PROPERTY_OVERFLOW, CSS_PROPERTY_PADDING_BOTTOM, CSS_PROPERTY_PADDING_LEFT, CSS_PROPERTY_PADDING_RIGHT, CSS_PROPERTY_PADDING_TOP, CSS_PROPERTY_POSITION, CSS_PROPERTY_QUOTES, CSS_PROPERTY_RIGHT, CSS_PROPERTY_TEXT_ALIGN, CSS_PROPERTY_TEXT_DECORATION, CSS_PROPERTY_TEXT_INDENT, CSS_PROPERTY_TEXT_SHADOW, CSS_PROPERTY_TEXT_TRANSFORM, CSS_PROPERTY_TOP, CSS_PROPERTY_UNICODE_BIDI, CSS_PROPERTY_VERTICAL_ALIGN, CSS_PROPERTY_VISIBILITY, CSS_PROPERTY_WHITE_SPACE, CSS_PROPERTY_WIDTH, CSS_PROPERTY_WORD_SPACING, CSS_PROPERTY_Z_INDEX, CSS_PROPERTY_X_LINK, CSS_PROPERTY_X_COLSPAN, CSS_PROPERTY_X_ROWSPAN, PROPERTY_X_LINK, PROPERTY_X_IMG, PROPERTY_X_TOOLTIP, CSS_PROPERTY_LAST } Name; typedef enum { CSS_FONT_WEIGHT_LIGHTER = -1, CSS_FONT_WEIGHT_BOLDER = -2, CSS_FONT_WEIGHT_STEP = 300, /* Some special font weights. */ CSS_FONT_WEIGHT_LIGHT = 100, CSS_FONT_WEIGHT_NORMAL = 400, CSS_FONT_WEIGHT_BOLD = 700, CSS_FONT_WEIGHT_MIN = 100, CSS_FONT_WEIGHT_MAX = 900, } FontWeightExtensions; Name name; Value value; void print (); }; /** * \brief A list of CssProperty objects. */ class CssPropertyList : public lout::misc::SimpleVector { int refCount; public: CssPropertyList() : lout::misc::SimpleVector (1) { refCount = 0; }; CssPropertyList(const CssPropertyList &p) : lout::misc::SimpleVector (p) { refCount = 0; }; void set (CssProperty::Name name, CssProperty::Value value); void set (CssProperty::Name name, const char *value) { CssProperty::Value v; v.strVal = value; set (name, v); }; void set (CssProperty::Name name, int value) { CssProperty::Value v; v.intVal = value; set (name, v); }; void apply (CssPropertyList *props); void print (); inline void ref () { refCount++; } inline void unref () { if(--refCount == 0) delete this; } }; class CssSimpleSelector { public: enum { ELEMENT_NONE = -1, ELEMENT_ANY = -2, }; int element; char *klass, *pseudo, *id; CssSimpleSelector (); ~CssSimpleSelector (); bool match (const DoctreeNode *node); void print (); }; /** * \brief CSS selector class. * \todo Implement missing selector options. */ class CssSelector { public: typedef enum { DESCENDENT, CHILD, ADJACENT_SIBLING, } Combinator; private: struct CombinatorAndSelector { int notMatchingBefore; // used for optimizing CSS selector matching Combinator combinator; CssSimpleSelector *selector; }; int refCount; lout::misc::SimpleVector *selectorList; public: CssSelector (); ~CssSelector (); void addSimpleSelector (Combinator c); inline CssSimpleSelector *top () { return selectorList->getRef (selectorList->size () - 1)->selector; }; inline int size () { return selectorList->size (); }; bool match (Doctree *dt, const DoctreeNode *node); void print (); inline void ref () { refCount++; } inline void unref () { if(--refCount == 0) delete this; } }; /** * \brief A CssSelector CssPropertyList pair. * The CssPropertyList is applied if the CssSelector matches. */ class CssRule { private: CssPropertyList *props; public: CssSelector *selector; CssRule (CssSelector *selector, CssPropertyList *props); ~CssRule (); void apply (CssPropertyList *props, Doctree *docTree, const DoctreeNode *node); void print (); }; /** * \brief A list of CssRules. * In apply () all matching rules are applied. */ class CssStyleSheet { private: class RuleList : public lout::misc::SimpleVector , public lout::object::Object { public: RuleList () : lout::misc::SimpleVector (1) {}; ~RuleList () { for (int i = 0; i < size (); i++) delete get (i); }; bool equals (lout::object::Object *other) { return this == other; }; int hashValue () { return (intptr_t) this; }; }; class RuleMap : public lout::container::typed::HashTable { public: RuleMap () : lout::container::typed::HashTable (true, true, 256) {}; }; static const int ntags = 90; // \todo replace 90 RuleList *elementTable[ntags]; RuleMap *idTable; RuleMap *classTable; RuleList *anyTable; public: CssStyleSheet(); ~CssStyleSheet(); void addRule (CssRule *rule); void addRule (CssSelector *selector, CssPropertyList *props); void apply (CssPropertyList *props, Doctree *docTree, const DoctreeNode *node); }; /** * \brief A set of CssStyleSheets. */ class CssContext { private: static CssStyleSheet *userAgentStyle; static CssStyleSheet *userStyle; static CssStyleSheet *userImportantStyle; CssStyleSheet *sheet[CSS_PRIMARY_USER_IMPORTANT + 1]; void buildUserAgentStyle (); void buildUserStyle (); public: CssContext (); ~CssContext (); void addRule (CssRule *rule, CssPrimaryOrder order); void apply (CssPropertyList *props, Doctree *docTree, CssPropertyList *tagStyle, CssPropertyList *nonCssHints); }; #endif