File indexing completed on 2024-04-21 14:56:55

0001 /*
0002  * This file is part of the CSS implementation for KDE.
0003  *
0004  * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org)
0005  * Copyright (C) 2003, 2005, 2006 Apple Computer, Inc.
0006  *
0007  * This library is free software; you can redistribute it and/or
0008  * modify it under the terms of the GNU Library General Public
0009  * License as published by the Free Software Foundation; either
0010  * version 2 of the License, or (at your option) any later version.
0011  *
0012  * This library is distributed in the hope that it will be useful,
0013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0015  * Library General Public License for more details.
0016  *
0017  * You should have received a copy of the GNU Library General Public License
0018  * along with this library; see the file COPYING.LIB.  If not, write to
0019  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0020  * Boston, MA 02110-1301, USA.
0021  *
0022  */
0023 #ifndef _CSS_cssstyleselector_h_
0024 #define _CSS_cssstyleselector_h_
0025 
0026 #include "rendering/render_style.h"
0027 #include "dom/dom_string.h"
0028 #include "css/css_mediaquery.h"
0029 #include <QVarLengthArray>
0030 #include <QList>
0031 #include <wtf/HashMap.h>
0032 #include <wtf/Vector.h>
0033 #include <wtf/HashSet.h>
0034 
0035 class KHTMLSettings;
0036 class KHTMLView;
0037 class KHTMLPart;
0038 class QUrl;
0039 
0040 namespace DOM
0041 {
0042 class DocumentImpl;
0043 class NodeImpl;
0044 class ElementImpl;
0045 class StyleSheetImpl;
0046 class CSSStyleRuleImpl;
0047 class CSSStyleSheetImpl;
0048 class CSSSelector;
0049 class CSSStyleDeclarationImpl;
0050 class CSSProperty;
0051 class StyleSheetListImpl;
0052 class CSSValueImpl;
0053 class CSSFontSelector;
0054 }
0055 
0056 namespace khtml
0057 {
0058 class CSSStyleSelectorList;
0059 class CSSOrderedRule;
0060 class CSSOrderedPropertyList;
0061 class RenderStyle;
0062 class MediaQueryEvaluator;
0063 
0064 /*
0065  * to remember the source where a rule came from. Differentiates between
0066  * important and not important rules. This is ordered in the order they have to be applied
0067  * to the RenderStyle.
0068  */
0069 enum Source {
0070     Default = 0,
0071     User = 1,
0072     NonCSSHint = 2,
0073     Author = 3,
0074     Inline = 4,
0075     AuthorImportant = 5,
0076     InlineImportant = 6,
0077     UserImportant = 7
0078 };
0079 
0080 /*
0081  * List of properties that get applied to the Element. We need to collect them first
0082  * and then apply them one by one, because we have to change the apply order.
0083  * Some properties depend on other one already being applied (for example all properties specifying
0084  * some length need to have already the correct font size. Same applies to color
0085  *
0086  * While sorting them, we have to take care not to mix up the original order.
0087  */
0088 class CSSOrderedProperty
0089 {
0090 public:
0091     CSSOrderedProperty(DOM::CSSProperty *_prop, uint _selector,
0092                        bool first, Source source, unsigned int specificity,
0093                        unsigned int _position)
0094         : prop(_prop), pseudoId(RenderStyle::NOPSEUDO), selector(_selector),
0095           position(_position)
0096     {
0097         priority = (!first << 30) | (source << 24) | specificity;
0098     }
0099     CSSOrderedProperty(): prop(nullptr), pseudoId(RenderStyle::NOPSEUDO), selector(0),
0100         position(0)
0101     {
0102 
0103     }
0104 
0105     bool operator < (const CSSOrderedProperty &other) const
0106     {
0107         if (priority < other.priority) {
0108             return true;
0109         }
0110         if (priority > other.priority) {
0111             return false;
0112         }
0113         if (position < other.position) {
0114             return true;
0115         }
0116         return false;
0117     }
0118 
0119     DOM::CSSProperty *prop;
0120     RenderStyle::PseudoId pseudoId;
0121     unsigned int selector;
0122     unsigned int position;
0123 
0124     quint32 priority;
0125 };
0126 
0127 class MediaQueryResult
0128 {
0129 public:
0130     MediaQueryResult(const MediaQueryExp &expr, bool result)
0131         : m_expression(expr)
0132         , m_result(result)
0133     {}
0134 
0135     MediaQueryExp m_expression;
0136     bool m_result;
0137 };
0138 
0139 /**
0140  * this class selects a RenderStyle for a given Element based on the
0141  * collection of stylesheets it contains. This is just a virtual base class
0142  * for specific implementations of the Selector. At the moment only CSSStyleSelector
0143  * exists, but someone may wish to implement XSL...
0144  */
0145 class StyleSelector
0146 {
0147 public:
0148     StyleSelector() {}
0149 
0150     /* as nobody has implemented a second style selector up to now comment out
0151        the virtual methods until then, so the class has no vptr.
0152     */
0153 //  virtual ~StyleSelector() {}
0154 //  virtual RenderStyle *styleForElement(DOM::ElementImpl *e) = 0;
0155 
0156     enum State {
0157         None = 0x00,
0158         Hover = 0x01,
0159         Focus = 0x02,
0160         Active = 0x04
0161     };
0162 };
0163 
0164 /**
0165  * the StyleSelector implementation for CSS.
0166  */
0167 class CSSStyleSelector : public StyleSelector
0168 {
0169 public:
0170     /**
0171      * creates a new StyleSelector for a Document.
0172      * goes through all StyleSheets defined in the document and
0173      * creates a list of rules it needs to apply to objects
0174      *
0175      * Also takes into account special cases for HTML documents,
0176      * including the defaultStyle (which is html only)
0177      */
0178     CSSStyleSelector(DOM::DocumentImpl *doc, QString userStyleSheet, DOM::StyleSheetListImpl *styleSheets, const QUrl &url,
0179                      bool _strictParsing);
0180     /**
0181      * same as above but for a single stylesheet.
0182      */
0183     CSSStyleSelector(DOM::CSSStyleSheetImpl *sheet);
0184 
0185     ~CSSStyleSelector();
0186 
0187     void addSheet(DOM::CSSStyleSheetImpl *sheet);
0188     KHTML_EXPORT static void clear();
0189     static void reparseConfiguration();
0190 
0191     static void loadDefaultStyle(const KHTMLSettings *s, DOM::DocumentImpl *doc);
0192 
0193     // fallbackParentStyle will be inheritted from if the parent doesn't have style info
0194     RenderStyle *styleForElement(DOM::ElementImpl *e, RenderStyle *fallbackParentStyle = nullptr);
0195 
0196     bool isMatchedByAnySelector(DOM::ElementImpl *e, const QList<DOM::CSSSelector *> &sels);
0197 
0198     QVector<int> fontSizes() const
0199     {
0200         return m_fontSizes;
0201     }
0202     QVector<int> fixedFontSizes() const
0203     {
0204         return m_fixedFontSizes;
0205     }
0206 
0207     bool strictParsing;
0208     struct Encodedurl {
0209         QString host; //also contains protocol
0210         QString path;
0211         QString file;
0212     } encodedurl;
0213 
0214     // called from KHTMLView::print()
0215     void computeFontSizes(int logicalDpiY, int zoomFactor);
0216     void computeFontSizesFor(int logicalDpiY, int zoomFactor, QVector<int> &fontSizes, bool isFixed);
0217 
0218     static void precomputeAttributeDependencies(DOM::DocumentImpl *doc, DOM::CSSSelector *sel);
0219     void addViewportDependentMediaQueryResult(const MediaQueryExp *, bool result);
0220     bool affectedByViewportChange() const;
0221     DOM::CSSFontSelector *fontSelector() const
0222     {
0223         return m_fontSelector;
0224     }
0225 protected:
0226     /* checks if the complete selector (which can be build up from a few CSSSelector's
0227         with given relationships matches the given Element */
0228     void checkSelector(int selector, DOM::ElementImpl *e);
0229     /* checks if the selector matches the given Element */
0230     bool checkSimpleSelector(DOM::CSSSelector *selector, DOM::ElementImpl *e, bool isAncestor, bool isSubSelector = false);
0231 
0232     enum SelectorMatch {SelectorMatches = 0, SelectorFailsLocal, SelectorFails};
0233     SelectorMatch checkSelector(DOM::CSSSelector *sel, DOM::ElementImpl *e, bool isAncestor, bool isSubSelector = false);
0234 
0235     // computes various summaries of the documents' properties, which are used in
0236     // the various checkSelector methods for optimizations
0237     void prepareToMatchElement(DOM::ElementImpl *e, bool withDeps);
0238 
0239     void addDependency(int dependencyType, DOM::ElementImpl *dependency);
0240     void setupDefaultRootStyle(DOM::DocumentImpl *d = nullptr);
0241 #ifdef APPLE_CHANGES
0242     /* This function fixes up the default font size if it detects that the
0243        current generic font family has changed. -dwh */
0244     void checkForGenericFamilyChange(RenderStyle *aStyle, RenderStyle *aParentStyle);
0245 #endif
0246     // locates potentially similar style
0247     RenderStyle *locateSimilarStyle();
0248 
0249     /* builds up the selectors and properties lists from the CSSStyleSelectorList's */
0250     void buildLists();
0251     void clearLists();
0252 
0253     void adjustRenderStyle(RenderStyle *style, DOM::ElementImpl *e);
0254 
0255     void addInlineDeclarations(DOM::ElementImpl *e);
0256 
0257     static DOM::CSSStyleSheetImpl *s_defaultSheet;
0258     static DOM::CSSStyleSheetImpl *s_defaultNonCSSHintsSheet;
0259     static DOM::CSSStyleSheetImpl *s_quirksSheet;
0260     static CSSStyleSelectorList *s_defaultStyle;
0261     static CSSStyleSelectorList *s_defaultQuirksStyle;
0262     static CSSStyleSelectorList *s_defaultPrintStyle;
0263     static CSSStyleSelectorList *s_defaultNonCSSHintsStyle;
0264     static RenderStyle *styleNotYetAvailable;
0265 
0266     CSSStyleSelectorList *defaultStyle;
0267     CSSStyleSelectorList *defaultQuirksStyle;
0268     CSSStyleSelectorList *defaultNonCSSHintsStyle;
0269     CSSStyleSelectorList *defaultPrintStyle;
0270 
0271     CSSStyleSelectorList *authorStyle;
0272     CSSStyleSelectorList *implicitStyle;
0273     CSSStyleSelectorList *userStyle;
0274     DOM::CSSStyleSheetImpl *userSheet;
0275 
0276 public:
0277 
0278 private:
0279     void init(const KHTMLSettings *settings, DOM::DocumentImpl *doc);
0280 
0281     void mapBackgroundAttachment(BackgroundLayer *layer, DOM::CSSValueImpl *value);
0282     void mapBackgroundClip(BackgroundLayer *layer, DOM::CSSValueImpl *value);
0283     void mapBackgroundOrigin(BackgroundLayer *layer, DOM::CSSValueImpl *value);
0284     void mapBackgroundImage(BackgroundLayer *layer, DOM::CSSValueImpl *value);
0285     void mapBackgroundRepeat(BackgroundLayer *layer, DOM::CSSValueImpl *value);
0286     void mapBackgroundSize(BackgroundLayer *layer, DOM::CSSValueImpl *value);
0287     void mapBackgroundXPosition(BackgroundLayer *layer, DOM::CSSValueImpl *value);
0288     void mapBackgroundYPosition(BackgroundLayer *layer, DOM::CSSValueImpl *value);
0289 
0290 public: // we need to make the enum public for SelectorCache
0291     enum SelectorState {
0292         Unknown = 0,
0293         Applies,
0294         AppliesPseudo,
0295         Invalid
0296     };
0297 
0298     enum SelectorMedia {
0299         MediaAural = 1,
0300         MediaBraille,
0301         MediaEmboss,
0302         MediaHandheld,
0303         MediaPrint,
0304         MediaProjection,
0305         MediaScreen,
0306         MediaTTY,
0307         MediaTV
0308     };
0309 protected:
0310 
0311     struct SelectorCache {
0312         SelectorState state;
0313         unsigned firstPropertyIndex;
0314     };
0315 
0316     unsigned int selectors_size;
0317     DOM::CSSSelector **selectors;
0318     SelectorCache *selectorCache;
0319     unsigned *nextPropertyIndexes;
0320     unsigned int properties_size;
0321     unsigned *nextSimilarSelector;
0322     CSSOrderedProperty *propertiesBuffer;
0323     QVarLengthArray<CSSOrderedProperty> inlineProps;
0324     MediaQueryEvaluator *m_medium;
0325     WTF::Vector<CSSOrderedProperty *> propsToApply;
0326     WTF::Vector<CSSOrderedProperty *> pseudoProps;
0327 
0328     // hashes for faster styleForElement
0329     WTF::HashMap<quintptr, int> classSelector, idSelector;
0330     WTF::HashMap<unsigned, int> tagSelector;
0331     int otherSelector;
0332 
0333     WTF::HashSet<unsigned> tagCache;
0334     WTF::HashSet<quintptr> classCache, idCache;
0335 
0336     RenderStyle::PseudoId dynamicPseudo;
0337 
0338     RenderStyle *style;
0339     RenderStyle *parentStyle;
0340     RenderStyle *m_rootStyle; // needed to compute 'rem' lengths
0341     DOM::ElementImpl *element;
0342     DOM::NodeImpl *parentNode;
0343     KHTMLView *view;
0344     KHTMLPart *part;
0345     const KHTMLSettings *settings;
0346     bool rememberDependencies;
0347     int logicalDpiY;
0348     RenderStyle     *m_rootDefaultStyle;
0349     QVector<int>     m_fontSizes;
0350     QVector<int>     m_fixedFontSizes;
0351     int m_minFontSize;
0352 
0353     bool fontDirty;
0354     DOM::CSSFontSelector *m_fontSelector;
0355     QList<MediaQueryResult *> m_viewportDependentMediaQueryResults;
0356 
0357     void applyRule(int id, DOM::CSSValueImpl *value);
0358     void applySVGRule(int id, DOM::CSSValueImpl *value);
0359 };
0360 
0361 /*
0362  * This is the list we will collect all properties we need to apply in.
0363  * It will get sorted once before applying.
0364  */
0365 class CSSOrderedPropertyList : public QVector<CSSOrderedProperty>
0366 {
0367 public:
0368     void append(DOM::CSSStyleDeclarationImpl *decl, uint selector, uint specificity,
0369                 Source regular, Source important);
0370 };
0371 
0372 class CSSOrderedRule
0373 {
0374 public:
0375     CSSOrderedRule(DOM::CSSStyleRuleImpl *r, DOM::CSSSelector *s, int _index);
0376     ~CSSOrderedRule();
0377 
0378     DOM::CSSSelector *selector;
0379     DOM::CSSStyleRuleImpl *rule;
0380     int index;
0381 };
0382 
0383 class CSSStyleSelectorList : public QList<CSSOrderedRule *>
0384 {
0385 public:
0386     CSSStyleSelectorList();
0387     virtual ~CSSStyleSelectorList();
0388 
0389     void append(DOM::CSSStyleSheetImpl *sheet,
0390                 MediaQueryEvaluator *medium, CSSStyleSelector *styleSelector);
0391 
0392     void collect(WTF::HashMap<DOM::CSSSelector *, int> *selectorsCache, QList<DOM::CSSSelector *> *selectorList,
0393                  CSSOrderedPropertyList *propList, Source regular, Source important);
0394 };
0395 
0396 }
0397 #endif