Pseudo elements

David Hyatt hyatt at apple.com
Tue Oct 21 16:20:59 CEST 2003


This is the first of several patches to clean up pseudo element 
handling.  This patch is probably not something you can merge easily 
yet, since it depends on changes that have been made since Safari v85, 
but I'll log it here so that when we do get the newest WebCore pushed, 
you'll be able to see the diff.

This patch changes style resolution on pseudo-element styles to be lazy 
and to only happen if the front end explicitly asks for a pseudo-style. 
  It also paves the way for resolving styles relative to arbitrary 
parent styles (necessary for first-line and first-letter).

My second patch is going to be a general first-line cleanup, and then 
my third patch will be a general first-letter cleanup.

dave
(hyatt at apple.com)

-------------- next part --------------
Index: khtml/css/cssstyleselector.cpp
===================================================================
RCS file: /local/home/cvs/Labyrinth/WebCore/khtml/css/cssstyleselector.cpp,v
retrieving revision 1.101
diff -u -p -r1.101 khtml/css/cssstyleselector.cpp
--- khtml/css/cssstyleselector.cpp	2003/10/20 18:18:02	1.101
+++ khtml/css/cssstyleselector.cpp	2003/10/21 22:10:36
@@ -308,29 +308,39 @@ static inline void bubbleSort( CSSOrdere
     }
 }
 
-RenderStyle *CSSStyleSelector::styleForElement(ElementImpl *e)
+void CSSStyleSelector::initForStyleResolve(ElementImpl* e, RenderStyle* defaultParent)
 {
-    if (!e->getDocument()->haveStylesheetsLoaded()) {
-        if (!styleNotYetAvailable) {
-            styleNotYetAvailable = new RenderStyle();
-            styleNotYetAvailable->setDisplay(NONE);
-            styleNotYetAvailable->ref();
-        }
-        return styleNotYetAvailable;
-    }
-  
     // set some variables we will need
     ::encodedurl = &encodedurl;
     pseudoState = PseudoUnknown;
-
+    
     element = e;
     parentNode = e->parentNode();
-    parentStyle = ( parentNode && parentNode->renderer()) ? parentNode->renderer()->style() : 0;
+    if (defaultParent)
+        parentStyle = defaultParent;
+    else
+        parentStyle = (parentNode && parentNode->renderer()) ? parentNode->renderer()->style() : 0;
     view = element->getDocument()->view();
     isXMLDoc = !element->getDocument()->isHTMLDocument();
     part = view->part();
     settings = part->settings();
     paintDeviceMetrics = element->getDocument()->paintDeviceMetrics();
+    
+    style = 0;
+}
+
+RenderStyle* CSSStyleSelector::styleForElement(ElementImpl* e, RenderStyle* defaultParent)
+{
+    if (!e->getDocument()->haveStylesheetsLoaded()) {
+        if (!styleNotYetAvailable) {
+            styleNotYetAvailable = new RenderStyle();
+            styleNotYetAvailable->setDisplay(NONE);
+            styleNotYetAvailable->ref();
+        }
+        return styleNotYetAvailable;
+    }
+    
+    initForStyleResolve(e, defaultParent);
 
     style = new RenderStyle();
     if( parentStyle )
@@ -339,8 +349,7 @@ RenderStyle *CSSStyleSelector::styleForE
         parentStyle = style;
     
     unsigned int numPropsToApply = 0;
-    unsigned int numPseudoProps = 0;
-
+    
     // try to sort out most style rules as early as possible.
     // ### implement CSS3 namespace support
     int cssTagId = (e->id() & NodeImpl::IdLocalMask);
@@ -366,17 +375,9 @@ RenderStyle *CSSStyleSelector::styleForE
 			}
 			propsToApply[numPropsToApply++] = properties[selectorCache[i].props[p]+j];
 		    }
-	    } else if ( selectorCache[i].state == AppliesPseudo ) {
-		for ( unsigned int p = 0; p < selectorCache[i].props_size; p += 2 )
-		    for ( unsigned int j = 0; j < (unsigned int) selectorCache[i].props[p+1]; ++j ) {
-                        if (numPseudoProps >= pseudoPropsSize ) {
-                            pseudoPropsSize *= 2;
-			    pseudoProps = (CSSOrderedProperty **)realloc( pseudoProps, pseudoPropsSize*sizeof( CSSOrderedProperty * ) );
-			}
-			pseudoProps[numPseudoProps++] = properties[selectorCache[i].props[p]+j];
-			properties[selectorCache[i].props[p]+j]->pseudoId = (RenderStyle::PseudoId) selectors[i]->pseudoId;
-		    }
 	    }
+            else if (selectorCache[i].state == AppliesPseudo)
+                style->setHasPseudoStyle((RenderStyle::PseudoId)selectors[i]->pseudoId);
 	}
 	else
 	    selectorCache[i].state = Invalid;
@@ -392,8 +393,7 @@ RenderStyle *CSSStyleSelector::styleForE
     numPropsToApply = addInlineDeclarations( e, e->m_styleDecls, numPropsToApply );
             
     bubbleSort( propsToApply, propsToApply+numPropsToApply-1 );
-    bubbleSort( pseudoProps, pseudoProps+numPseudoProps-1 );
-
+    
     //qDebug("applying properties, count=%d", propsToApply->count() );
 
     // we can't apply style rules without a view() and a part. This
@@ -422,63 +422,100 @@ RenderStyle *CSSStyleSelector::styleForE
 
         // Clean up our style object's display and text decorations (among other fixups).
         adjustRenderStyle(style, e);
+    }
+
+    // Now return the style.
+    return style;
+}
+
+RenderStyle* CSSStyleSelector::pseudoStyleForElement(RenderStyle::PseudoId pseudoStyle, 
+                                                     ElementImpl* e, RenderStyle* parentStyle)
+{
+    if (!e)
+        return 0;
+    
+    if (!e->getDocument()->haveStylesheetsLoaded()) {
+        if (!styleNotYetAvailable) {
+            styleNotYetAvailable = new RenderStyle();
+            styleNotYetAvailable->setDisplay(NONE);
+            styleNotYetAvailable->ref();
+        }
+        return styleNotYetAvailable;
+    }
+    
+    initForStyleResolve(e, parentStyle);
+    
+    unsigned int numPseudoProps = 0;
+    
+    // try to sort out most style rules as early as possible.
+    // ### implement CSS3 namespace support
+    int cssTagId = (e->id() & NodeImpl::IdLocalMask);
+    int schecked = 0;
+    
+    for ( unsigned int i = 0; i < selectors_size; i++ ) {
+        int tag = selectors[i]->tag;
+        if ( cssTagId == tag || tag == -1 ) {
+            ++schecked;
+            
+            checkSelector( i, e, pseudoStyle );
+            
+            if ( selectorCache[i].state == AppliesPseudo ) {
+                for ( unsigned int p = 0; p < selectorCache[i].props_size; p += 2 )
+                    for ( unsigned int j = 0; j < (unsigned int) selectorCache[i].props[p+1]; ++j ) {
+                        if (numPseudoProps >= pseudoPropsSize ) {
+                            pseudoPropsSize *= 2;
+                            pseudoProps = (CSSOrderedProperty **)realloc( pseudoProps, pseudoPropsSize*sizeof( CSSOrderedProperty * ) );
+                        }
+                        pseudoProps[numPseudoProps++] = properties[selectorCache[i].props[p]+j];
+                        properties[selectorCache[i].props[p]+j]->pseudoId = (RenderStyle::PseudoId) selectors[i]->pseudoId;
+                    }
+            }
+        }
+        else
+            selectorCache[i].state = Invalid;
+    }
+    
+    if (numPseudoProps == 0)
+        return 0;
+    
+    style = new RenderStyle();
+    if( parentStyle )
+        style->inheritFrom( parentStyle );
+    else
+        parentStyle = style;
+    style->noninherited_flags._styleType = pseudoStyle;
         
+    bubbleSort( pseudoProps, pseudoProps+numPseudoProps-1 );
+        
+    // we can't apply style rules without a view() and a part. This
+    // tends to happen on delayed destruction of widget Renderobjects
+    if ( part ) {
+        fontDirty = false;
         if ( numPseudoProps ) {
-	    fontDirty = false;
+            fontDirty = false;
             //qDebug("%d applying %d pseudo props", e->cssTagId(), pseudoProps->count() );
             for (unsigned int i = 0; i < numPseudoProps; ++i) {
-		if ( fontDirty && pseudoProps[i]->priority >= (1 << 30) ) {
-		    // we are past the font properties, time to update to the
-		    // correct font
-		    //We have to do this for all pseudo styles
-		    RenderStyle *pseudoStyle = style->pseudoStyle;
-		    while ( pseudoStyle ) {
-                        checkForGenericFamilyChange(pseudoStyle, style);
-			pseudoStyle->htmlFont().update( paintDeviceMetrics );
-			pseudoStyle = pseudoStyle->pseudoStyle;
-		    }
-		    fontDirty = false;
-		}
-
-                RenderStyle *pseudoStyle;
-                pseudoStyle = style->getPseudoStyle(pseudoProps[i]->pseudoId);
-                if (!pseudoStyle)
-                {
-                    pseudoStyle = style->addPseudoStyle(pseudoProps[i]->pseudoId);
-                    if (pseudoStyle)
-                        pseudoStyle->inheritFrom( style );
-                }
-
-                RenderStyle* oldStyle = style;
-                RenderStyle* oldParentStyle = parentStyle;
-                parentStyle = style;
-                style = pseudoStyle;
-                if ( pseudoStyle ) {
-                    DOM::CSSProperty *prop = pseudoProps[i]->prop;
-                    applyRule( prop->m_id, prop->value() );
+                if ( fontDirty && pseudoProps[i]->priority >= (1 << 30) ) {
+                    // we are past the font properties, time to update to the
+                    // correct font
+                    style->htmlFont().update( paintDeviceMetrics );
+                    fontDirty = false;
                 }
-                style = oldStyle;
-                parentStyle = oldParentStyle;
+                
+               DOM::CSSProperty *prop = pseudoProps[i]->prop;
+               applyRule( prop->m_id, prop->value() );
             }
-
-	    if ( fontDirty ) {
-		RenderStyle *pseudoStyle = style->pseudoStyle;
-		while ( pseudoStyle ) {
-                    checkForGenericFamilyChange(pseudoStyle, style);
-		    pseudoStyle->htmlFont().update( paintDeviceMetrics );
-		    pseudoStyle = pseudoStyle->pseudoStyle;
-		}
-	    }
+            
+            if ( fontDirty ) {
+                checkForGenericFamilyChange(style, parentStyle);
+                style->htmlFont().update( paintDeviceMetrics );
+            }
         }
     }
-
-    // Now adjust all our pseudo-styles.
-    RenderStyle *pseudoStyle = style->pseudoStyle;
-    while (pseudoStyle) {
-        adjustRenderStyle(pseudoStyle, 0);
-        pseudoStyle = pseudoStyle->pseudoStyle;
-    }
-
+    
+    // Do the post-resolve fixups on the style.
+    adjustRenderStyle(style, 0);
+        
     // Now return the style.
     return style;
 }
@@ -685,7 +722,7 @@ static void checkPseudoState( DOM::Eleme
     pseudoState = KHTMLFactory::vLinks()->contains( u ) ? PseudoVisited : PseudoLink;
 }
 
-void CSSStyleSelector::checkSelector(int selIndex, DOM::ElementImpl *e)
+void CSSStyleSelector::checkSelector(int selIndex, DOM::ElementImpl *e, RenderStyle::PseudoId pseudo)
 {
     dynamicPseudo = RenderStyle::NOPSEUDO;
     
@@ -704,8 +741,9 @@ void CSSStyleSelector::checkSelector(int
                             (sel->match == CSSSelector::Pseudo &&
                               (sel->pseudoType() == CSSSelector::PseudoHover ||
                                sel->pseudoType() == CSSSelector::PseudoActive)));
-    bool affectedByHover = style->affectedByHoverRules();
-    bool affectedByActive = style->affectedByActiveRules();
+    bool affectedByHover = style ? style->affectedByHoverRules() : false;
+    bool affectedByActive = style ? style->affectedByActiveRules() : false;
+    bool havePseudo = pseudo != RenderStyle::NOPSEUDO;
     
     // first selector has to match
     if(!checkOneSelector(sel, e)) return;
@@ -715,6 +753,12 @@ void CSSStyleSelector::checkSelector(int
     while((sel = sel->tagHistory))
     {
         if (!n->isElementNode()) return;
+        if (relation != CSSSelector::SubSelector) {
+            subject = false;
+            if (havePseudo && dynamicPseudo != pseudo)
+                return;
+        }
+        
         switch(relation)
         {
         case CSSSelector::Descendant:
@@ -722,8 +766,7 @@ void CSSStyleSelector::checkSelector(int
             bool found = false;
             while(!found)
             {
-		subject = false;
-                n = n->parentNode();
+		n = n->parentNode();
                 if(!n || !n->isElementNode()) return;
                 ElementImpl *elem = static_cast<ElementImpl *>(n);
                 if(checkOneSelector(sel, elem)) found = true;
@@ -732,7 +775,6 @@ void CSSStyleSelector::checkSelector(int
         }
         case CSSSelector::Child:
         {
-            subject = false;
             n = n->parentNode();
             if (!strictParsing)
                 while (n && n->implicitNode()) n = n->parentNode();
@@ -743,7 +785,6 @@ void CSSStyleSelector::checkSelector(int
         }
         case CSSSelector::Sibling:
         {
-            subject = false;
             n = n->previousSibling();
 	    while( n && !n->isElementNode() )
 		n = n->previousSibling();
@@ -773,6 +814,9 @@ void CSSStyleSelector::checkSelector(int
         relation = sel->relation;
     }
 
+    if (subject && havePseudo && dynamicPseudo != pseudo)
+        return;
+    
     // disallow *:hover, *:active, and *:hover:active except for links
     if (onlyHoverActive && subject) {
         if (pseudoState == PseudoUnknown)
@@ -799,7 +843,6 @@ void CSSStyleSelector::checkSelector(int
 
 bool CSSStyleSelector::checkOneSelector(DOM::CSSSelector *sel, DOM::ElementImpl *e)
 {
-
     if(!e)
         return false;
 
@@ -985,7 +1028,7 @@ bool CSSStyleSelector::checkOneSelector(
                 // If we're in quirks mode, then hover should never match anchors with no
                 // href.  This is important for sites like wsj.com.
                 if (strictParsing || e->id() != ID_A || e->hasAnchor()) {
-                    if (element == e)
+                    if (element == e && style)
                         style->setAffectedByHoverRules(true);
                     if (e->renderer()) {
                         if (element != e)
@@ -1005,7 +1048,7 @@ bool CSSStyleSelector::checkOneSelector(
                 // If we're in quirks mode, then :active should never match anchors with no
                 // href. 
                 if (strictParsing || e->id() != ID_A || e->hasAnchor()) {
-                    if (element == e)
+                    if (element == e && style)
                         style->setAffectedByActiveRules(true);
                     else if (e->renderer())
                         e->renderer()->style()->setAffectedByActiveRules(true);
Index: khtml/css/cssstyleselector.h
===================================================================
RCS file: /local/home/cvs/Labyrinth/WebCore/khtml/css/cssstyleselector.h,v
retrieving revision 1.18
diff -u -p -r1.18 khtml/css/cssstyleselector.h
--- khtml/css/cssstyleselector.h	2003/08/20 22:03:24	1.18
+++ khtml/css/cssstyleselector.h	2003/10/21 22:10:36
@@ -125,8 +125,11 @@ namespace khtml
 	static void loadDefaultStyle(const KHTMLSettings *s = 0);
 	static void clear();
 
-	RenderStyle *styleForElement(DOM::ElementImpl *e);
-
+        void initForStyleResolve(DOM::ElementImpl* e, RenderStyle* parentStyle);
+	RenderStyle *styleForElement(DOM::ElementImpl* e, RenderStyle* parentStyle=0);
+        RenderStyle* pseudoStyleForElement(RenderStyle::PseudoId pseudoStyle, 
+                                           DOM::ElementImpl* e, RenderStyle* parentStyle=0);
+        
         QValueList<int> fontSizes() const { return m_fontSizes; }
 	
 	bool strictParsing;
@@ -144,7 +147,8 @@ namespace khtml
 
 	/* 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);
+        void checkSelector(int selector, DOM::ElementImpl *e, 
+                           RenderStyle::PseudoId pseudo = RenderStyle::NOPSEUDO);
 	/* checks if the selector matches the given Element */
 	bool checkOneSelector(DOM::CSSSelector *selector, DOM::ElementImpl *e);
 
Index: khtml/rendering/render_block.cpp
===================================================================
RCS file: /local/home/cvs/Labyrinth/WebCore/khtml/rendering/render_block.cpp,v
retrieving revision 1.68
diff -u -p -r1.68 khtml/rendering/render_block.cpp
--- khtml/rendering/render_block.cpp	2003/10/20 07:07:54	1.68
+++ khtml/rendering/render_block.cpp	2003/10/21 22:10:36
@@ -103,8 +103,8 @@ void RenderBlock::addChildToFlow(RenderO
 
     RenderStyle* pseudoStyle=0;
     if ((!firstChild() || firstChild() == beforeChild) &&
-         (newChild->isInline() || newChild->isText()) &&
-         (pseudoStyle=style()->getPseudoStyle(RenderStyle::FIRST_LETTER)))
+         (newChild->isInline() || (newChild->isText() && !newChild->isBR())) &&
+         (pseudoStyle=getPseudoStyle(RenderStyle::FIRST_LETTER, style(true))))
     {
         // Drill into inlines looking for our first text child.
         RenderObject* textChild = newChild;
Index: khtml/rendering/render_container.cpp
===================================================================
RCS file: /local/home/cvs/Labyrinth/WebCore/khtml/rendering/render_container.cpp,v
retrieving revision 1.45
diff -u -p -r1.45 khtml/rendering/render_container.cpp
--- khtml/rendering/render_container.cpp	2003/10/20 18:18:02	1.45
+++ khtml/rendering/render_container.cpp	2003/10/21 22:10:36
@@ -215,7 +215,7 @@ void RenderContainer::updatePseudoChild(
     if (style()->styleType() == RenderStyle::BEFORE || style()->styleType() == RenderStyle::AFTER)
         return;
     
-    RenderStyle* pseudo = style()->getPseudoStyle(type);
+    RenderStyle* pseudo = getPseudoStyle(type);
 
     // Whether or not we currently have generated content attached.
     bool oldContentPresent = child && (child->style()->styleType() == type);
Index: khtml/rendering/render_object.cpp
===================================================================
RCS file: /local/home/cvs/Labyrinth/WebCore/khtml/rendering/render_object.cpp,v
retrieving revision 1.105
diff -u -p -r1.105 khtml/rendering/render_object.cpp
--- khtml/rendering/render_object.cpp	2003/10/17 22:32:13	1.105
+++ khtml/rendering/render_object.cpp	2003/10/21 22:10:36
@@ -29,6 +29,7 @@
 #include "rendering/render_canvas.h"
 #include "xml/dom_elementimpl.h"
 #include "xml/dom_docimpl.h"
+#include "css/cssstyleselector.h"
 #include "misc/htmlhashes.h"
 #include <kdebug.h>
 #include <qpainter.h>
@@ -1209,7 +1210,7 @@ void RenderObject::setStyle(RenderStyle 
 
     setShouldPaintBackgroundOrBorder(m_style->backgroundColor().isValid() || 
                                      m_style->hasBorder() || nb );
-    m_hasFirstLine = (style->getPseudoStyle(RenderStyle::FIRST_LINE) != 0);
+    m_hasFirstLine = getPseudoStyle(RenderStyle::FIRST_LINE);
 
     if (affectsParentBlock)
         handleDynamicFloatPositionChange();
@@ -1744,6 +1745,32 @@ InlineBox* RenderObject::createInlineBox
 {
     KHTMLAssert(!isRootLineBox);
     return new (renderArena()) InlineBox(this);
+}
+
+RenderStyle* RenderObject::style(bool firstLine) const {
+    RenderStyle *s = m_style;
+    if (firstLine && hasFirstLine()) {
+        RenderStyle *pseudoStyle  = getPseudoStyle(RenderStyle::FIRST_LINE);
+        if (pseudoStyle)
+            s = pseudoStyle;
+    }
+    return s;
+}
+
+RenderStyle* RenderObject::getPseudoStyle(RenderStyle::PseudoId pseudo, RenderStyle* parentStyle) const
+{
+    if (!style()->hasPseudoStyle(pseudo))
+        return 0;
+    
+    DOM::NodeImpl* node = element();
+    if (isText())
+        node = element()->parentNode();
+    if (!node) return 0;
+    
+    if (!parentStyle)
+        parentStyle = style();
+    
+    return document()->styleSelector()->pseudoStyleForElement(pseudo, static_cast<DOM::ElementImpl*>(node), parentStyle);
 }
 
 void RenderObject::getTextDecorationColors(int decorations, QColor& underline, QColor& overline,
Index: khtml/rendering/render_object.h
===================================================================
RCS file: /local/home/cvs/Labyrinth/WebCore/khtml/rendering/render_object.h,v
retrieving revision 1.86
diff -u -p -r1.86 khtml/rendering/render_object.h
--- khtml/rendering/render_object.h	2003/10/17 22:32:13	1.86
+++ khtml/rendering/render_object.h	2003/10/21 22:10:36
@@ -253,6 +253,8 @@ public:
     bool isSelectionBorder() const { return m_isSelectionBorder; }
     bool recalcMinMax() const { return m_recalcMinMax; }
 
+    RenderStyle* getPseudoStyle(RenderStyle::PseudoId pseudo, RenderStyle* parentStyle = 0) const;
+    
     RenderCanvas* canvas() const;
 
     // don't even think about making this method virtual!
@@ -558,15 +560,7 @@ public:
     virtual short maxWidth() const { return 0; }
 
     RenderStyle* style() const { return m_style; }
-    RenderStyle* style( bool firstLine ) const {
-	RenderStyle *s = m_style;
-	if( firstLine && hasFirstLine() ) {
-	    RenderStyle *pseudoStyle  = style()->getPseudoStyle(RenderStyle::FIRST_LINE);
-	    if ( pseudoStyle )
-		s = pseudoStyle;
-	}
-	return s;
-    }
+    RenderStyle* style( bool firstLine ) const;
 
     void getTextDecorationColors(int decorations, QColor& underline, QColor& overline,
                                  QColor& linethrough, bool quirksMode=false);
Index: khtml/rendering/render_style.cpp
===================================================================
RCS file: /local/home/cvs/Labyrinth/WebCore/khtml/rendering/render_style.cpp,v
retrieving revision 1.29
diff -u -p -r1.29 khtml/rendering/render_style.cpp
--- khtml/rendering/render_style.cpp	2003/10/17 22:32:13	1.29
+++ khtml/rendering/render_style.cpp	2003/10/21 22:10:36
@@ -332,36 +332,59 @@ bool RenderStyle::isStyleAvailable() con
     return this != CSSStyleSelector::styleNotYetAvailable;
 }
 
+enum EPseudoBit { NO_BIT = 0x0, BEFORE_BIT = 0x1, AFTER_BIT = 0x2, FIRST_LINE_BIT = 0x4,
+                  FIRST_LETTER_BIT = 0x8, SELECTION_BIT = 0x10 };
+
+static int pseudoBit(RenderStyle::PseudoId pseudo)
+{
+    switch (pseudo) {
+        case RenderStyle::BEFORE:
+            return BEFORE_BIT;
+        case RenderStyle::AFTER:
+            return AFTER_BIT;
+        case RenderStyle::FIRST_LINE:
+            return FIRST_LINE_BIT;
+        case RenderStyle::FIRST_LETTER:
+            return FIRST_LETTER_BIT;
+        case RenderStyle::SELECTION:
+            return SELECTION_BIT;
+        default:
+            return NO_BIT;
+    }
+}
+
+bool RenderStyle::hasPseudoStyle(PseudoId pseudo) const
+{
+    return (pseudoBit(pseudo) & noninherited_flags._pseudoBits) != 0;
+}
+
+void RenderStyle::setHasPseudoStyle(PseudoId pseudo)
+{
+    noninherited_flags._pseudoBits |= pseudoBit(pseudo);
+}
+
 RenderStyle* RenderStyle::getPseudoStyle(PseudoId pid)
 {
     RenderStyle *ps = 0;
     if (noninherited_flags._styleType==NOPSEUDO) {
 	ps = pseudoStyle;
-    while (ps) {
-        if (ps->noninherited_flags._styleType==pid)
-		break;
-
-        ps = ps->pseudoStyle;
+        while (ps) {
+            if (ps->noninherited_flags._styleType==pid)
+                    break;
+    
+            ps = ps->pseudoStyle;
+        }
     }
-    }
     return ps;
 }
 
-RenderStyle* RenderStyle::addPseudoStyle(PseudoId pid)
+void RenderStyle::addPseudoStyle(RenderStyle* pseudo)
 {
-    RenderStyle *ps = getPseudoStyle(pid);
-
-    if (!ps)
-    {
-        ps = new RenderStyle(); // So that noninherited flags are reset.
-        ps->ref();
-        ps->noninherited_flags._styleType = pid;
-        ps->pseudoStyle = pseudoStyle;
-
-        pseudoStyle = ps;
-    }
-
-    return ps;
+    if (!pseudo) return;
+    
+    pseudo->ref();
+    pseudo->pseudoStyle = pseudoStyle;
+    pseudoStyle = pseudo;
 }
 
 void RenderStyle::removePseudoStyle(PseudoId pid)
Index: khtml/rendering/render_style.h
===================================================================
RCS file: /local/home/cvs/Labyrinth/WebCore/khtml/rendering/render_style.h,v
retrieving revision 1.32
diff -u -p -r1.32 khtml/rendering/render_style.h
--- khtml/rendering/render_style.h	2003/10/17 22:32:13	1.32
+++ khtml/rendering/render_style.h	2003/10/21 22:10:36
@@ -685,6 +685,7 @@ protected:
             (_styleType == other._styleType) &&
             (_affectedByHover == other._affectedByHover) &&
             (_affectedByActive == other._affectedByActive) &&
+            (_pseudoBits == other._pseudoBits) &&
             (_unicodeBidi == other._unicodeBidi);
 	}
 
@@ -707,6 +708,7 @@ protected:
         PseudoId _styleType : 3;
         bool _affectedByHover : 1;
         bool _affectedByActive : 1;
+        int _pseudoBits : 5;
         EUnicodeBidi _unicodeBidi : 2;
     } noninherited_flags;
 
@@ -723,7 +725,7 @@ protected:
     
 // list of associated pseudo styles
     RenderStyle* pseudoStyle;
-
+    
     // added this here, so we can get rid of the vptr in this class.
     // makes up for the same size.
     ContentData *content;
@@ -766,6 +768,7 @@ protected:
 	noninherited_flags._styleType = NOPSEUDO;
         noninherited_flags._affectedByHover = false;
         noninherited_flags._affectedByActive = false;
+        noninherited_flags._pseudoBits = 0;
 	noninherited_flags._unicodeBidi = UBNormal;
     }
 
@@ -783,8 +786,7 @@ public:
     PseudoId styleType() { return  noninherited_flags._styleType; }
 
     RenderStyle* getPseudoStyle(PseudoId pi);
-    RenderStyle* addPseudoStyle(PseudoId pi);
-    bool hasPseudoStyle() const { return pseudoStyle; }
+    void addPseudoStyle(RenderStyle* pseudo);
     void removePseudoStyle(PseudoId pi);
 
     bool affectedByHoverRules() const { return  noninherited_flags._affectedByHover; }
@@ -803,6 +805,9 @@ public:
     void setVisuallyOrdered(bool b) {  inherited_flags._visuallyOrdered = b; }
 
     bool isStyleAvailable() const;
+    
+    bool hasPseudoStyle(PseudoId pseudo) const;
+    void setHasPseudoStyle(PseudoId pseudo);
     
 // attribute getter methods
 
Index: khtml/rendering/render_text.cpp
===================================================================
RCS file: /local/home/cvs/Labyrinth/WebCore/khtml/rendering/render_text.cpp,v
retrieving revision 1.87
diff -u -p -r1.87 khtml/rendering/render_text.cpp
--- khtml/rendering/render_text.cpp	2003/10/20 07:07:54	1.87
+++ khtml/rendering/render_text.cpp	2003/10/21 22:10:37
@@ -86,7 +86,7 @@ void InlineTextBox::paintSelection(const
     if (textColor == c)
         c = QColor(0xff - c.red(), 0xff - c.green(), 0xff - c.blue());
 
-    RenderStyle* pseudoStyle = object()->style()->getPseudoStyle(RenderStyle::SELECTION);
+    RenderStyle* pseudoStyle = object()->getPseudoStyle(RenderStyle::SELECTION);
     if (pseudoStyle && pseudoStyle->backgroundColor().isValid())
         c = pseudoStyle->backgroundColor();
     p->setPen(c); // Don't draw text at all!
@@ -577,7 +577,7 @@ void RenderText::paintObject(QPainter *p
                              int tx, int ty, PaintAction paintAction)
 {
     int ow = style()->outlineWidth();
-    RenderStyle* pseudoStyle = style()->getPseudoStyle(RenderStyle::FIRST_LINE);
+    RenderStyle* pseudoStyle = hasFirstLine() ? getPseudoStyle(RenderStyle::FIRST_LINE) : 0;
     int d = style()->textDecorationsInEffect();
     InlineTextBox f(0, y-ty);
     int si = m_lines.findFirstMatching(&f);
@@ -701,7 +701,7 @@ void RenderText::paintObject(QPainter *p
                 QColor selectionColor = p->pen().color();
                 ShadowData* selectionTextShadow = 0;
                 if (haveSelection) {
-                    RenderStyle* pseudoStyle = style()->getPseudoStyle(RenderStyle::SELECTION);
+                    RenderStyle* pseudoStyle = getPseudoStyle(RenderStyle::SELECTION);
                     if (pseudoStyle) {
                         if (pseudoStyle->color() != selectionColor || pseudoStyle->textShadow()) {
                             if (!paintSelectedTextOnly)
@@ -1338,7 +1338,7 @@ const Font *RenderText::htmlFont(bool fi
 {
     const Font *f = 0;
     if( firstLine && hasFirstLine() ) {
-	RenderStyle *pseudoStyle  = style()->getPseudoStyle(RenderStyle::FIRST_LINE);
+        RenderStyle* pseudoStyle = getPseudoStyle(RenderStyle::FIRST_LINE);
 	if ( pseudoStyle )
 	    f = &pseudoStyle->htmlFont();
     } else {
-------------- next part --------------






More information about the Khtml-devel mailing list