/* * This file is part of the CSS implementation for KDE. * * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org) * Copyright (C) 2003, 2005, 2006 Apple Computer, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */ #ifndef _CSS_cssstyleselector_h_ #define _CSS_cssstyleselector_h_ #include "rendering/render_style.h" #include "dom/dom_string.h" #include "css/css_mediaquery.h" #include #include #include #include #include class KHTMLSettings; class KHTMLView; class KHTMLPart; class KUrl; namespace DOM { class DocumentImpl; class NodeImpl; class ElementImpl; class StyleSheetImpl; class CSSStyleRuleImpl; class CSSStyleSheetImpl; class CSSSelector; class CSSStyleDeclarationImpl; class CSSProperty; class StyleSheetListImpl; class CSSValueImpl; class CSSFontSelector; } namespace khtml { class CSSStyleSelectorList; class CSSOrderedRule; class CSSOrderedPropertyList; class RenderStyle; class MediaQueryEvaluator; /* * to remember the source where a rule came from. Differentiates between * important and not important rules. This is ordered in the order they have to be applied * to the RenderStyle. */ enum Source { Default = 0, User = 1, NonCSSHint = 2, Author = 3, Inline = 4, AuthorImportant = 5, InlineImportant = 6, UserImportant =7 }; /* * List of properties that get applied to the Element. We need to collect them first * and then apply them one by one, because we have to change the apply order. * Some properties depend on other one already being applied (for example all properties specifying * some length need to have already the correct font size. Same applies to color * * While sorting them, we have to take care not to mix up the original order. */ class CSSOrderedProperty { public: CSSOrderedProperty(DOM::CSSProperty *_prop, uint _selector, bool first, Source source, unsigned int specificity, unsigned int _position ) : prop ( _prop ), pseudoId( RenderStyle::NOPSEUDO ), selector( _selector ), position( _position ) { priority = (!first << 30) | (source << 24) | specificity; } CSSOrderedProperty(): prop( 0 ), pseudoId( RenderStyle::NOPSEUDO ), selector(0), position( 0 ) { } bool operator < ( const CSSOrderedProperty &other ) const { if (priority < other.priority) return true; if (priority > other.priority) return false; if (position < other.position) return true; return false; } DOM::CSSProperty *prop; RenderStyle::PseudoId pseudoId; unsigned int selector; unsigned int position; quint32 priority; }; class MediaQueryResult { public: MediaQueryResult(const MediaQueryExp& expr, bool result) : m_expression(expr) , m_result(result) {} MediaQueryExp m_expression; bool m_result; }; /** * this class selects a RenderStyle for a given Element based on the * collection of stylesheets it contains. This is just a virtual base class * for specific implementations of the Selector. At the moment only CSSStyleSelector * exists, but someone may wish to implement XSL... */ class StyleSelector { public: StyleSelector() {} /* as nobody has implemented a second style selector up to now comment out the virtual methods until then, so the class has no vptr. */ // virtual ~StyleSelector() {} // virtual RenderStyle *styleForElement(DOM::ElementImpl *e) = 0; enum State { None = 0x00, Hover = 0x01, Focus = 0x02, Active = 0x04 }; }; /** * the StyleSelector implementation for CSS. */ class CSSStyleSelector : public StyleSelector { public: /** * creates a new StyleSelector for a Document. * goes through all StyleSheets defined in the document and * creates a list of rules it needs to apply to objects * * Also takes into account special cases for HTML documents, * including the defaultStyle (which is html only) */ CSSStyleSelector( DOM::DocumentImpl* doc, QString userStyleSheet, DOM::StyleSheetListImpl *styleSheets, const KUrl &url, bool _strictParsing ); /** * same as above but for a single stylesheet. */ CSSStyleSelector( DOM::CSSStyleSheetImpl *sheet ); ~CSSStyleSelector(); void addSheet( DOM::CSSStyleSheetImpl *sheet ); KHTML_EXPORT static void clear(); static void reparseConfiguration(); static void loadDefaultStyle(const KHTMLSettings *s, DOM::DocumentImpl *doc); // fallbackParentStyle will be inheritted from if the parent doesn't have style info RenderStyle *styleForElement(DOM::ElementImpl *e, RenderStyle* fallbackParentStyle = 0); bool isMatchedByAnySelector(DOM::ElementImpl* e, const QList& sels); QVector fontSizes() const { return m_fontSizes; } QVector fixedFontSizes() const { return m_fixedFontSizes; } bool strictParsing; struct Encodedurl { QString host; //also contains protocol QString path; QString file; } encodedurl; // called from KHTMLView::print() void computeFontSizes(int logicalDpiY, int zoomFactor); void computeFontSizesFor(int logicalDpiY, int zoomFactor, QVector& fontSizes, bool isFixed); static void precomputeAttributeDependencies(DOM::DocumentImpl* doc, DOM::CSSSelector* sel); void addViewportDependentMediaQueryResult(const MediaQueryExp*, bool result); bool affectedByViewportChange() const; DOM::CSSFontSelector* fontSelector() const { return m_fontSelector; } protected: /* checks if the complete selector (which can be build up from a few CSSSelector's with given relationships matches the given Element */ void checkSelector(int selector, DOM::ElementImpl *e); /* checks if the selector matches the given Element */ bool checkSimpleSelector(DOM::CSSSelector *selector, DOM::ElementImpl *e, bool isAncestor, bool isSubSelector = false); enum SelectorMatch {SelectorMatches = 0, SelectorFailsLocal, SelectorFails}; SelectorMatch checkSelector(DOM::CSSSelector *sel, DOM::ElementImpl *e, bool isAncestor, bool isSubSelector = false); // computes various summaries of the documents' properties, which are used in // the various checkSelector methods for optimizations void prepareToMatchElement(DOM::ElementImpl* e, bool withDeps); void addDependency(int dependencyType, DOM::ElementImpl* dependency); void setupDefaultRootStyle(DOM::DocumentImpl *d=0); // locates potentially similar style RenderStyle* locateSimilarStyle(); /* builds up the selectors and properties lists from the CSSStyleSelectorList's */ void buildLists(); void clearLists(); void adjustRenderStyle(RenderStyle* style, DOM::ElementImpl *e); void addInlineDeclarations(DOM::ElementImpl* e); static DOM::CSSStyleSheetImpl *s_defaultSheet; static DOM::CSSStyleSheetImpl *s_defaultNonCSSHintsSheet; static DOM::CSSStyleSheetImpl *s_quirksSheet; static CSSStyleSelectorList *s_defaultStyle; static CSSStyleSelectorList *s_defaultQuirksStyle; static CSSStyleSelectorList *s_defaultPrintStyle; static CSSStyleSelectorList *s_defaultNonCSSHintsStyle; static RenderStyle* styleNotYetAvailable; CSSStyleSelectorList *defaultStyle; CSSStyleSelectorList *defaultQuirksStyle; CSSStyleSelectorList *defaultNonCSSHintsStyle; CSSStyleSelectorList *defaultPrintStyle; CSSStyleSelectorList *authorStyle; CSSStyleSelectorList *implicitStyle; CSSStyleSelectorList *userStyle; DOM::CSSStyleSheetImpl *userSheet; public: private: void init(const KHTMLSettings* settings, DOM::DocumentImpl* doc); void mapBackgroundAttachment(BackgroundLayer* layer, DOM::CSSValueImpl* value); void mapBackgroundClip(BackgroundLayer* layer, DOM::CSSValueImpl* value); void mapBackgroundOrigin(BackgroundLayer* layer, DOM::CSSValueImpl* value); void mapBackgroundImage(BackgroundLayer* layer, DOM::CSSValueImpl* value); void mapBackgroundRepeat(BackgroundLayer* layer, DOM::CSSValueImpl* value); void mapBackgroundSize(BackgroundLayer* layer, DOM::CSSValueImpl* value); void mapBackgroundXPosition(BackgroundLayer* layer, DOM::CSSValueImpl* value); void mapBackgroundYPosition(BackgroundLayer* layer, DOM::CSSValueImpl* value); public: // we need to make the enum public for SelectorCache enum SelectorState { Unknown = 0, Applies, AppliesPseudo, Invalid }; enum SelectorMedia { MediaAural = 1, MediaBraille, MediaEmboss, MediaHandheld, MediaPrint, MediaProjection, MediaScreen, MediaTTY, MediaTV }; protected: struct SelectorCache { SelectorState state; unsigned firstPropertyIndex; }; unsigned int selectors_size; DOM::CSSSelector **selectors; SelectorCache *selectorCache; unsigned *nextPropertyIndexes; unsigned int properties_size; unsigned *nextSimilarSelector; CSSOrderedProperty *propertiesBuffer; QVarLengthArray inlineProps; MediaQueryEvaluator* m_medium; WTF::Vector propsToApply; WTF::Vector pseudoProps; // hashes for faster styleForElement WTF::HashMap classSelector, idSelector; WTF::HashMap tagSelector; int otherSelector; WTF::HashSet tagCache; WTF::HashSet classCache, idCache; RenderStyle::PseudoId dynamicPseudo; RenderStyle *style; RenderStyle *parentStyle; RenderStyle *m_rootStyle; // needed to compute 'rem' lengths DOM::ElementImpl *element; DOM::NodeImpl *parentNode; KHTMLView *view; KHTMLPart *part; const KHTMLSettings *settings; bool rememberDependencies; int logicalDpiY; RenderStyle* m_rootDefaultStyle; QVector m_fontSizes; QVector m_fixedFontSizes; int m_minFontSize; bool fontDirty; DOM::CSSFontSelector* m_fontSelector; QList m_viewportDependentMediaQueryResults; void applyRule(int id, DOM::CSSValueImpl *value); void applySVGRule(int id, DOM::CSSValueImpl *value); }; /* * This is the list we will collect all properties we need to apply in. * It will get sorted once before applying. */ class CSSOrderedPropertyList : public QVector { public: void append(DOM::CSSStyleDeclarationImpl *decl, uint selector, uint specificity, Source regular, Source important); }; class CSSOrderedRule { public: CSSOrderedRule(DOM::CSSStyleRuleImpl *r, DOM::CSSSelector *s, int _index); ~CSSOrderedRule(); DOM::CSSSelector *selector; DOM::CSSStyleRuleImpl *rule; int index; }; class CSSStyleSelectorList : public QList { public: CSSStyleSelectorList(); virtual ~CSSStyleSelectorList(); void append( DOM::CSSStyleSheetImpl *sheet, MediaQueryEvaluator *medium, CSSStyleSelector* styleSelector ); void collect(WTF::HashMap* selectorsCache, QList *selectorList, CSSOrderedPropertyList *propList, Source regular, Source important); }; } #endif