[SCM] WebKit Debian packaging branch, debian/unstable, updated. debian/1.1.15-1-40151-g37bb677

hyatt hyatt at 268f45cc-cd09-0410-ab3c-d52691b4dbfc
Sat Sep 26 07:47:29 UTC 2009


The following commit has been merged in the debian/unstable branch:
commit be45e944692e542decce56581f6ae59aed496efc
Author: hyatt <hyatt at 268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Tue Jul 15 22:32:42 2003 +0000

    	Fix a problem where ems used for non-font values like width
    	and line-height would not zoom. (r=darin)
    
    	The rest is r=rjw.
    
    	An implementation of the CSS2 text-shadow property.
    
    	It uses a CoreGraphics API for drawing shadows
    	(via a custom API on QPainter) to paint the shadows.
    
            At the moment there are two limitations in CG's API.  The first
            is that the shadow color cannot be set.  This will be fixed for
            Panther, and the code passes the color through in preparation
            for this fix.
    
    	The second limitation is that CG only supports one shadow effect
    	and not multiple shadow effects.  The parsing code on the CSS
            side is set up to go ahead and parse all of the shadow effects,
            but the code that makes use of shadows will simply look at the
            first one for now.  CG will not support multiple shadow effects
            in the Panther time frame, so it will be a while before this
            is revisited.
    
    	This patch also fixes a slew of bugs with colors in KHTML.  When
    	we took the CSS parser and all of its associated code from Lars,
    	that code was using QRgb values that assumed RGBA (like the current
    	Qt toolkit uses).  The code even made use of an "invalid color"
    	that wasn't really invalid (kind of like the z-index hack we refused
    	to take, i.e., unlikely but not invalid).
    
    	Our KWQColor implementation has been rewritten in this patch to
    	work the way the current Qt toolkit expects.  That is, the top
    	eight bits actually do contain an alpha channel, and you can obtain
    	the alpha component using the qAlpha method and build a quadruple
    	using the qRgba method.
    
    	This patch adds support for rgba quadruples to CSS, so you can now
    	say, e.g.,color: rgba(255,0,0,0.5); in CSS.
    
            * khtml/css/css_valueimpl.cpp:
            (ShadowValueImpl::~ShadowValueImpl):
            * khtml/css/css_valueimpl.h:
            * khtml/css/cssparser.cpp:
            (CSSParser::parseValue):
            (parseColor):
            (CSSParser::parseColor):
            (CSSParser::parseColorFromValue):
            (CSSParser::parseShadow):
            * khtml/css/cssparser.h:
            * khtml/css/cssstyleselector.cpp:
            * khtml/misc/helper.h:
            * khtml/rendering/render_line.cpp:
            (InlineFlowBox::paintDecorations):
            * khtml/rendering/render_style.cpp:
            (StyleVisualData::StyleVisualData):
            (opacity):
            (flexibleBox):
            (StyleCSS3NonInheritedData::operator==):
            (textShadow):
            (StyleCSS3InheritedData):
            (StyleCSS3InheritedData::operator==):
            (StyleCSS3InheritedData::shadowDataEquivalent):
            (RenderStyle::RenderStyle):
            (RenderStyle::inheritFrom):
            (RenderStyle::operator==):
            (RenderStyle::inheritedNotEqual):
            (RenderStyle::diff):
            (ContentData::clearContent):
            (RenderStyle::setTextShadow):
            (ShadowData::operator==):
            * khtml/rendering/render_style.h:
            * khtml/rendering/render_text.cpp:
            (RenderText::paintObject):
            * khtml/xml/dom_nodeimpl.cpp:
            (NodeImpl::diff):
            * kwq/KWQColor.h:
            * kwq/KWQColor.mm:
            (qRgb):
            (qRgba):
            (qAlpha):
            (QColor::QColor):
            (QColor::setNamedColor):
            (QColor::getNSColor):
            * kwq/KWQNamespace.h:
            * kwq/KWQPainter.h:
            * kwq/KWQPainter.mm:
            (QPainter::drawRect):
            (QPainter::drawLine):
            (QPainter::_fillRect):
            (QPainter::fillRect):
            (QPainter::setShadow):
            (QPainter::clearShadow):
    
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@4656 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/WebCore/ChangeLog-2003-10-25 b/WebCore/ChangeLog-2003-10-25
index 3ade1c3..60a50f7 100644
--- a/WebCore/ChangeLog-2003-10-25
+++ b/WebCore/ChangeLog-2003-10-25
@@ -1,3 +1,98 @@
+2003-07-14  Dave Hyatt  <hyatt at apple.com>
+
+	Fix a problem where ems used for non-font values like width
+	and line-height would not zoom. (r=darin)
+
+	The rest is r=rjw.
+	
+	An implementation of the CSS2 text-shadow property. 
+
+	It uses a CoreGraphics API for drawing shadows 
+	(via a custom API on QPainter) to paint the shadows.
+
+        At the moment there are two limitations in CG's API.  The first
+        is that the shadow color cannot be set.  This will be fixed for
+        Panther, and the code passes the color through in preparation
+        for this fix.
+
+	The second limitation is that CG only supports one shadow effect
+	and not multiple shadow effects.  The parsing code on the CSS
+        side is set up to go ahead and parse all of the shadow effects,
+        but the code that makes use of shadows will simply look at the
+        first one for now.  CG will not support multiple shadow effects
+        in the Panther time frame, so it will be a while before this
+        is revisited.
+
+	This patch also fixes a slew of bugs with colors in KHTML.  When
+	we took the CSS parser and all of its associated code from Lars,
+	that code was using QRgb values that assumed RGBA (like the current
+	Qt toolkit uses).  The code even made use of an "invalid color"
+	that wasn't really invalid (kind of like the z-index hack we refused
+	to take, i.e., unlikely but not invalid).
+
+	Our KWQColor implementation has been rewritten in this patch to
+	work the way the current Qt toolkit expects.  That is, the top
+	eight bits actually do contain an alpha channel, and you can obtain
+	the alpha component using the qAlpha method and build a quadruple
+	using the qRgba method.
+
+	This patch adds support for rgba quadruples to CSS, so you can now
+	say, e.g.,color: rgba(255,0,0,0.5); in CSS.
+	
+        * khtml/css/css_valueimpl.cpp:
+        (ShadowValueImpl::~ShadowValueImpl):
+        * khtml/css/css_valueimpl.h:
+        * khtml/css/cssparser.cpp:
+        (CSSParser::parseValue):
+        (parseColor):
+        (CSSParser::parseColor):
+        (CSSParser::parseColorFromValue):
+        (CSSParser::parseShadow):
+        * khtml/css/cssparser.h:
+        * khtml/css/cssstyleselector.cpp:
+        * khtml/misc/helper.h:
+        * khtml/rendering/render_line.cpp:
+        (InlineFlowBox::paintDecorations):
+        * khtml/rendering/render_style.cpp:
+        (StyleVisualData::StyleVisualData):
+        (opacity):
+        (flexibleBox):
+        (StyleCSS3NonInheritedData::operator==):
+        (textShadow):
+        (StyleCSS3InheritedData):
+        (StyleCSS3InheritedData::operator==):
+        (StyleCSS3InheritedData::shadowDataEquivalent):
+        (RenderStyle::RenderStyle):
+        (RenderStyle::inheritFrom):
+        (RenderStyle::operator==):
+        (RenderStyle::inheritedNotEqual):
+        (RenderStyle::diff):
+        (ContentData::clearContent):
+        (RenderStyle::setTextShadow):
+        (ShadowData::operator==):
+        * khtml/rendering/render_style.h:
+        * khtml/rendering/render_text.cpp:
+        (RenderText::paintObject):
+        * khtml/xml/dom_nodeimpl.cpp:
+        (NodeImpl::diff):
+        * kwq/KWQColor.h:
+        * kwq/KWQColor.mm:
+        (qRgb):
+        (qRgba):
+        (qAlpha):
+        (QColor::QColor):
+        (QColor::setNamedColor):
+        (QColor::getNSColor):
+        * kwq/KWQNamespace.h:
+        * kwq/KWQPainter.h:
+        * kwq/KWQPainter.mm:
+        (QPainter::drawRect):
+        (QPainter::drawLine):
+        (QPainter::_fillRect):
+        (QPainter::fillRect):
+        (QPainter::setShadow):
+        (QPainter::clearShadow):
+
 2003-07-14  Darin Adler  <darin at apple.com>
 
         Reviewed by Maciej.
diff --git a/WebCore/ChangeLog-2005-08-23 b/WebCore/ChangeLog-2005-08-23
index 3ade1c3..60a50f7 100644
--- a/WebCore/ChangeLog-2005-08-23
+++ b/WebCore/ChangeLog-2005-08-23
@@ -1,3 +1,98 @@
+2003-07-14  Dave Hyatt  <hyatt at apple.com>
+
+	Fix a problem where ems used for non-font values like width
+	and line-height would not zoom. (r=darin)
+
+	The rest is r=rjw.
+	
+	An implementation of the CSS2 text-shadow property. 
+
+	It uses a CoreGraphics API for drawing shadows 
+	(via a custom API on QPainter) to paint the shadows.
+
+        At the moment there are two limitations in CG's API.  The first
+        is that the shadow color cannot be set.  This will be fixed for
+        Panther, and the code passes the color through in preparation
+        for this fix.
+
+	The second limitation is that CG only supports one shadow effect
+	and not multiple shadow effects.  The parsing code on the CSS
+        side is set up to go ahead and parse all of the shadow effects,
+        but the code that makes use of shadows will simply look at the
+        first one for now.  CG will not support multiple shadow effects
+        in the Panther time frame, so it will be a while before this
+        is revisited.
+
+	This patch also fixes a slew of bugs with colors in KHTML.  When
+	we took the CSS parser and all of its associated code from Lars,
+	that code was using QRgb values that assumed RGBA (like the current
+	Qt toolkit uses).  The code even made use of an "invalid color"
+	that wasn't really invalid (kind of like the z-index hack we refused
+	to take, i.e., unlikely but not invalid).
+
+	Our KWQColor implementation has been rewritten in this patch to
+	work the way the current Qt toolkit expects.  That is, the top
+	eight bits actually do contain an alpha channel, and you can obtain
+	the alpha component using the qAlpha method and build a quadruple
+	using the qRgba method.
+
+	This patch adds support for rgba quadruples to CSS, so you can now
+	say, e.g.,color: rgba(255,0,0,0.5); in CSS.
+	
+        * khtml/css/css_valueimpl.cpp:
+        (ShadowValueImpl::~ShadowValueImpl):
+        * khtml/css/css_valueimpl.h:
+        * khtml/css/cssparser.cpp:
+        (CSSParser::parseValue):
+        (parseColor):
+        (CSSParser::parseColor):
+        (CSSParser::parseColorFromValue):
+        (CSSParser::parseShadow):
+        * khtml/css/cssparser.h:
+        * khtml/css/cssstyleselector.cpp:
+        * khtml/misc/helper.h:
+        * khtml/rendering/render_line.cpp:
+        (InlineFlowBox::paintDecorations):
+        * khtml/rendering/render_style.cpp:
+        (StyleVisualData::StyleVisualData):
+        (opacity):
+        (flexibleBox):
+        (StyleCSS3NonInheritedData::operator==):
+        (textShadow):
+        (StyleCSS3InheritedData):
+        (StyleCSS3InheritedData::operator==):
+        (StyleCSS3InheritedData::shadowDataEquivalent):
+        (RenderStyle::RenderStyle):
+        (RenderStyle::inheritFrom):
+        (RenderStyle::operator==):
+        (RenderStyle::inheritedNotEqual):
+        (RenderStyle::diff):
+        (ContentData::clearContent):
+        (RenderStyle::setTextShadow):
+        (ShadowData::operator==):
+        * khtml/rendering/render_style.h:
+        * khtml/rendering/render_text.cpp:
+        (RenderText::paintObject):
+        * khtml/xml/dom_nodeimpl.cpp:
+        (NodeImpl::diff):
+        * kwq/KWQColor.h:
+        * kwq/KWQColor.mm:
+        (qRgb):
+        (qRgba):
+        (qAlpha):
+        (QColor::QColor):
+        (QColor::setNamedColor):
+        (QColor::getNSColor):
+        * kwq/KWQNamespace.h:
+        * kwq/KWQPainter.h:
+        * kwq/KWQPainter.mm:
+        (QPainter::drawRect):
+        (QPainter::drawLine):
+        (QPainter::_fillRect):
+        (QPainter::fillRect):
+        (QPainter::setShadow):
+        (QPainter::clearShadow):
+
 2003-07-14  Darin Adler  <darin at apple.com>
 
         Reviewed by Maciej.
diff --git a/WebCore/khtml/css/css_valueimpl.cpp b/WebCore/khtml/css/css_valueimpl.cpp
index 1c26b00..41bd325 100644
--- a/WebCore/khtml/css/css_valueimpl.cpp
+++ b/WebCore/khtml/css/css_valueimpl.cpp
@@ -543,7 +543,9 @@ double CSSPrimitiveValueImpl::computeLengthFloat( khtml::RenderStyle *style, QPa
     switch(type)
     {
     case CSSPrimitiveValue::CSS_EMS:
-        factor = style->htmlFont().getFontDef().specifiedSize;
+        factor = (selector && applyZoomFactor) ?
+          style->htmlFont().getFontDef().computedSize :
+          style->htmlFont().getFontDef().specifiedSize;
         break;
     case CSSPrimitiveValue::CSS_EXS:
         // FIXME: We have a bug right now where the zoom will be applied multiple times to EX units.
@@ -581,13 +583,7 @@ double CSSPrimitiveValueImpl::computeLengthFloat( khtml::RenderStyle *style, QPa
         return -1;
     }
 
-    float result = getFloatValue(type)*factor;
-    // FIXME: Will need to do this for EX units eventually as well, once they're patched
-    // to use specifiedSize and not a computed font size above.
-    // Need to adjust for the zoom and for the minimum font size.    
-    if (type == CSSPrimitiveValue::CSS_EMS && selector && applyZoomFactor)
-        selector->getComputedSizeFromSpecifiedSize(style->htmlFont().getFontDef().isAbsoluteSize, result);
-    return result;
+    return getFloatValue(type)*factor;
 }
 
 void CSSPrimitiveValueImpl::setFloatValue( unsigned short unitType, double floatValue, int &exceptioncode )
@@ -876,3 +872,18 @@ FontValueImpl::~FontValueImpl()
     delete lineHeight;
     delete family;
 }
+
+// Used for text-shadow and box-shadow
+ShadowValueImpl::ShadowValueImpl(CSSPrimitiveValueImpl* _x, CSSPrimitiveValueImpl* _y,
+                                 CSSPrimitiveValueImpl* _blur, CSSPrimitiveValueImpl* _color)
+:x(_x), y(_y), blur(_blur), color(_color)	
+{}
+
+ShadowValueImpl::~ShadowValueImpl()
+{
+    delete x;
+    delete y;
+    delete blur;
+    delete color;
+}
+
diff --git a/WebCore/khtml/css/css_valueimpl.h b/WebCore/khtml/css/css_valueimpl.h
index d790636..2172f71 100644
--- a/WebCore/khtml/css/css_valueimpl.h
+++ b/WebCore/khtml/css/css_valueimpl.h
@@ -322,6 +322,22 @@ public:
     CSSValueListImpl *family;
 };
 
+// Used for text-shadow and box-shadow
+class ShadowValueImpl : public CSSValueImpl
+{
+public:
+    ShadowValueImpl(CSSPrimitiveValueImpl* _x, CSSPrimitiveValueImpl* _y,
+                    CSSPrimitiveValueImpl* _blur, CSSPrimitiveValueImpl* _color);
+    virtual ~ShadowValueImpl();
+
+    virtual unsigned short cssValueType() const { return CSSValue::CSS_CUSTOM; }
+
+    CSSPrimitiveValueImpl* x;
+    CSSPrimitiveValueImpl* y;
+    CSSPrimitiveValueImpl* blur;
+    CSSPrimitiveValueImpl* color;
+};
+    
 // ------------------------------------------------------------------------------
 
 // another helper class
diff --git a/WebCore/khtml/css/cssparser.cpp b/WebCore/khtml/css/cssparser.cpp
index 43bb398..224eb38 100644
--- a/WebCore/khtml/css/cssparser.cpp
+++ b/WebCore/khtml/css/cssparser.cpp
@@ -975,6 +975,12 @@ bool CSSParser::parseValue( int propId, bool important )
     case CSS_PROP_OPACITY:
         valid_primitive = validUnit(value, FNumber, strict);
         break;
+    case CSS_PROP_TEXT_SHADOW: // CSS2 property, dropped in CSS2.1, back in CSS3, so treat as CSS3
+        if (id == CSS_VAL_NONE)
+            valid_primitive = true;
+        else
+            return parseShadow(propId, important);
+        break;
     case CSS_PROP_BOX_ALIGN:
         if (id == CSS_VAL_STRETCH || id == CSS_VAL_START || id == CSS_VAL_END ||
             id == CSS_VAL_CENTER || id == CSS_VAL_BASELINE)
@@ -1547,12 +1553,12 @@ CSSValueListImpl *CSSParser::parseFontFamily()
 }
 
 
-static QRgb parseColor(const QString &name)
+static bool parseColor(const QString &name, QRgb& rgb)
 {
     int len = name.length();
 
     if ( !len )
-        return khtml::invalidColor;
+        return false;
 
 
     bool ok;
@@ -1560,39 +1566,53 @@ static QRgb parseColor(const QString &name)
     if ( len == 3 || len == 6 ) {
 	int val = name.toInt(&ok, 16);
 	if ( ok ) {
-	    if (len == 6)
-		return (0xff << 24) | val;
-	    else if ( len == 3 )
+            if (len == 6) {
+		rgb =  (0xff << 24) | val;
+                return true;
+            }
+            else if ( len == 3 ) {
 		// #abc converts to #aabbcc according to the specs
-		return (0xff << 24) |
+		rgb = (0xff << 24) |
 		    (val&0xf00)<<12 | (val&0xf00)<<8 |
 		    (val&0xf0)<<8 | (val&0xf0)<<4 |
 		    (val&0xf)<<4 | (val&0xf);
+                return true;
+            }
 	}
     }
 
     // try a little harder
     QColor tc;
     tc.setNamedColor(name.lower());
-    if (tc.isValid()) return tc.rgb();
+    if (tc.isValid()) {
+        rgb = tc.rgb();
+        return true;
+    }
 
-    return khtml::invalidColor;
+    return false;
 }
 
 
 CSSPrimitiveValueImpl *CSSParser::parseColor()
 {
-    QRgb c = khtml::invalidColor;
-    Value *value = valueList->current();
+    return parseColorFromValue(valueList->current());
+}
+
+CSSPrimitiveValueImpl *CSSParser::parseColorFromValue(Value* value)
+{
+    QRgb c = khtml::transparentColor;
     if ( !strict && value->unit == CSSPrimitiveValue::CSS_NUMBER &&
         value->fValue >= 0. && value->fValue < 1000000. ) {
         QString str;
         str.sprintf( "%06d", (int)(value->fValue+.5) );
-        c = ::parseColor( str );
+        if (!::parseColor( str, c ))
+            return 0;
     } else if ( value->unit == CSSPrimitiveValue::CSS_RGBCOLOR ||
-              value->unit == CSSPrimitiveValue::CSS_IDENT ||
-              value->unit == CSSPrimitiveValue::CSS_DIMENSION )
-	c = ::parseColor( qString( value->string ));
+                value->unit == CSSPrimitiveValue::CSS_IDENT ||
+                value->unit == CSSPrimitiveValue::CSS_DIMENSION ) {
+	if (!::parseColor( qString( value->string ), c))
+            return 0;
+    }
     else if ( value->unit == Value::Function &&
 		value->function->args != 0 &&
 		value->function->args->numValues == 5 /* rgb + two commas */ &&
@@ -1621,12 +1641,184 @@ CSSPrimitiveValueImpl *CSSParser::parseColor()
 	b = QMAX( 0, QMIN( 255, b ) );
 	c = qRgb( r, g, b );
     }
-
-    if ( c != khtml::invalidColor )
-	return new CSSPrimitiveValueImpl(c);
-    return 0;
+    else if ( value->unit == Value::Function &&
+              value->function->args != 0 &&
+              value->function->args->numValues == 7 /* rgba + three commas */ &&
+              qString( value->function->name ).lower() == "rgba(" ) {
+        ValueList *args = value->function->args;
+        Value *v = args->current();
+        if ( !validUnit( v, FInteger|FPercent, true ) )
+            return 0;
+        int r = (int) ( v->fValue * (v->unit == CSSPrimitiveValue::CSS_PERCENTAGE ? 256./100. : 1.) );
+        v = args->next();
+        if ( v->unit != Value::Operator && v->iValue != ',' )
+            return 0;
+        v = args->next();
+        if ( !validUnit( v, FInteger|FPercent, true ) )
+            return 0;
+        int g = (int) ( v->fValue * (v->unit == CSSPrimitiveValue::CSS_PERCENTAGE ? 256./100. : 1.) );
+        v = args->next();
+        if ( v->unit != Value::Operator && v->iValue != ',' )
+            return 0;
+        v = args->next();
+        if ( !validUnit( v, FInteger|FPercent, true ) )
+            return 0;
+        int b = (int) ( v->fValue * (v->unit == CSSPrimitiveValue::CSS_PERCENTAGE ? 256./100. : 1.) );
+        v = args->next();
+        if ( v->unit != Value::Operator && v->iValue != ',' )
+            return 0;
+        v = args->next();
+        if ( !validUnit( v, FNumber, true ) )
+            return 0;
+        r = QMAX( 0, QMIN( 255, r ) );
+        g = QMAX( 0, QMIN( 255, g ) );
+        b = QMAX( 0, QMIN( 255, b ) );
+        int a = (int)(QMAX( 0, QMIN( 1.0f, v->fValue ) ) * 255);
+        c = qRgba( r, g, b, a );
+    }    
+
+    return new CSSPrimitiveValueImpl(c);
 }
 
+// This class tracks parsing state for shadow values.  If it goes out of scope (e.g., due to an early return)
+// without the allowBreak bit being set, then it will clean up all of the objects and destroy them.
+struct ShadowParseContext {
+    ShadowParseContext()
+    :values(0), x(0), y(0), blur(0), color(0),
+     allowX(true), allowY(false), allowBlur(false), allowColor(true),
+     allowBreak(true)
+    {}
+
+    ~ShadowParseContext() {
+        if (!allowBreak) {
+            delete values;
+            delete x;
+            delete y;
+            delete blur;
+            delete color;
+        }
+    }
+
+    bool allowLength() { return allowX || allowY || allowBlur; }
+
+    bool failed() { return allowBreak = false; }
+    
+    void commitValue() {
+        // Handle the ,, case gracefully by doing nothing.
+        if (x || y || blur || color) {
+            if (!values)
+                values = new CSSValueListImpl();
+            
+            // Construct the current shadow value and add it to the list.
+            values->append(new ShadowValueImpl(x, y, blur, color));
+        }
+        
+        // Now reset for the next shadow value.
+        x = y = blur = color = 0;
+        allowX = allowColor = allowBreak = true;
+        allowY = allowBlur = false;  
+    }
+
+    void commitLength(Value* v) {
+        CSSPrimitiveValueImpl* val = new CSSPrimitiveValueImpl(v->fValue,
+                                                               (CSSPrimitiveValue::UnitTypes)v->unit);
+        if (allowX) {
+            x = val;
+            allowX = false; allowY = true; allowColor = false; allowBreak = false;
+        }
+        else if (allowY) {
+            y = val;
+            allowY = false; allowBlur = true; allowColor = true; allowBreak = true;
+        }
+        else if (allowBlur) {
+            blur = val;
+            allowBlur = false;
+        }
+    }
+
+    void commitColor(CSSPrimitiveValueImpl* val) {
+        color = val;
+        allowColor = false;
+        if (allowX)
+            allowBreak = false;
+        else
+            allowBlur = false;
+    }
+    
+    CSSValueListImpl* values;
+    bool succeeded;
+    CSSPrimitiveValueImpl* x;
+    CSSPrimitiveValueImpl* y;
+    CSSPrimitiveValueImpl* blur;
+    CSSPrimitiveValueImpl* color;
+
+    bool allowX;
+    bool allowY;
+    bool allowBlur;
+    bool allowColor;
+    bool allowBreak;
+};
+
+bool CSSParser::parseShadow( int propId, bool important )
+{
+    ShadowParseContext context;
+    Value* val;
+    while ((val = valueList->current())) {
+        // Check for a comma break first.
+        if (val->unit == Value::Operator) {
+            if (val->iValue != ',' || !context.allowBreak)
+                // Other operators aren't legal or we aren't done with the current shadow
+                // value.  Treat as invalid.
+                return context.failed();
+            
+            // The value is good.  Commit it.
+            context.commitValue();
+        }
+        // Check to see if we're a length.
+        else if (validUnit(val, FLength, true)) {
+            // We required a length and didn't get one. Invalid.
+            if (!context.allowLength())
+                return context.failed();
+
+            // A length is allowed here.  Construct the value and add it.
+            context.commitLength(val);
+        }
+        else {
+            // The only other type of value that's ok is a color value.
+            CSSPrimitiveValueImpl* parsedColor = 0;
+            bool isColor = (val->id >= CSS_VAL_AQUA && val->id <= CSS_VAL_WINDOWTEXT || val->id == CSS_VAL_MENU ||
+                            (val->id >= CSS_VAL_GREY && val->id <= CSS_VAL__KONQ_TEXT && (nonCSSHint|!strict)));
+            if (isColor) {
+                if (!context.allowColor)
+                    return context.failed();
+                parsedColor = new CSSPrimitiveValueImpl(id);
+            }
+
+            if (!parsedColor)
+                // It's not built-in. Try to parse it as a color.
+                parsedColor = parseColorFromValue(val);
+
+            if (!parsedColor || !context.allowColor)
+                return context.failed(); // This value is not a color or length and is invalid or
+                                         // it is a color, but a color isn't allowed at this point.
+            
+            context.commitColor(parsedColor);
+        }
+        
+        valueList->next();
+    }
+
+    if (context.allowBreak) {
+        context.commitValue();
+        if (context.values->length()) {
+            addProperty(propId, context.values, important);
+            valueList->next();
+            return true;
+        }
+    }
+    
+    return context.failed();
+}
 
 static inline int yyerror( const char *str ) {
 #ifdef CSS_DEBUG
diff --git a/WebCore/khtml/css/cssparser.h b/WebCore/khtml/css/cssparser.h
index 32d45c1..f95532a 100644
--- a/WebCore/khtml/css/cssparser.h
+++ b/WebCore/khtml/css/cssparser.h
@@ -123,8 +123,12 @@ namespace DOM {
 	bool parseShape( int propId, bool important );
 	bool parseFont(bool important);
 	CSSValueListImpl *parseFontFamily();
-	CSSPrimitiveValueImpl *parseColor();
+        CSSPrimitiveValueImpl *parseColor();
+	CSSPrimitiveValueImpl *parseColorFromValue(Value* val);
 
+        // CSS3 Parsing Routines (for properties specific to CSS3)
+        bool parseShadow(int propId, bool important);
+        
 	int yyparse( void );
     public:
 	bool strict;
diff --git a/WebCore/khtml/css/cssstyleselector.cpp b/WebCore/khtml/css/cssstyleselector.cpp
index 6453598..ecccacf 100644
--- a/WebCore/khtml/css/cssstyleselector.cpp
+++ b/WebCore/khtml/css/cssstyleselector.cpp
@@ -2179,12 +2179,9 @@ void CSSStyleSelector::applyRule( int id, DOM::CSSValueImpl *value )
                 }
                 else
                     col = colorForCSSValue( ident );
-            } else if ( primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_RGBCOLOR ) {
-#if !APPLE_CHANGES
-                if(qAlpha(primitiveValue->getRGBColorValue()))
-#endif
+            } else if ( primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_RGBCOLOR )
                     col.setRgb(primitiveValue->getRGBColorValue());
-            } else {
+            else {
                 return;
             }
         }
@@ -3107,6 +3104,41 @@ void CSSStyleSelector::applyRule( int id, DOM::CSSValueImpl *value )
         break;
 
     // CSS3 Properties
+    case CSS_PROP_TEXT_SHADOW: {
+        if (value->cssValueType() == CSSValue::CSS_INHERIT) {
+            if (!parentNode) return;
+            style->setTextShadow(parentStyle->textShadow() ? new ShadowData(*parentStyle->textShadow()) : 0);
+            return;
+        }
+
+        if (primitiveValue) { // none
+            style->setTextShadow(0);
+            return;
+        }
+        
+        if (!value->isValueList()) return;
+        CSSValueListImpl *list = static_cast<CSSValueListImpl *>(value);
+        int len = list->length();
+        for (int i = 0; i < len; i++) {
+            ShadowValueImpl *item = static_cast<ShadowValueImpl*>(list->item(i));
+
+            int x = item->x->computeLength(style, paintDeviceMetrics, this);
+            int y = item->y->computeLength(style, paintDeviceMetrics, this);
+            int blur = item->blur ? item->blur->computeLength(style, paintDeviceMetrics, this) : 0;
+            QColor col = khtml::transparentColor;
+            if (item->color) {
+                int ident = item->color->getIdent();
+                if (ident)
+                    col = colorForCSSValue( ident );
+                else if (item->color->primitiveType() == CSSPrimitiveValue::CSS_RGBCOLOR)
+                    col.setRgb(primitiveValue->getRGBColorValue());
+            }
+            ShadowData* shadowData = new ShadowData(x, y, blur, col);
+            style->setTextShadow(shadowData, i != 0);
+        }
+
+        return;
+    }
     case CSS_PROP_OPACITY:
         if (value->cssValueType() == CSSValue::CSS_INHERIT) {
             if (!parentNode) return;
diff --git a/WebCore/khtml/misc/helper.h b/WebCore/khtml/misc/helper.h
index 9796bd2..537032e 100644
--- a/WebCore/khtml/misc/helper.h
+++ b/WebCore/khtml/misc/helper.h
@@ -30,9 +30,8 @@ class QPainter;
 namespace khtml
 {
     const QRgb transparentColor = 0x00000000;
-    const QRgb invalidColor     = 0x00000001;
-    const QRgb invertedColor    = 0x00000002;
-    const QRgb defaultTextColor = 0x00000003;
+    const QRgb invertedColor    = 0x00000002; // This really makes no sense. This is a valid color value, so why
+                                              // is it being given special meaning? -dwh
     
     extern QPainter *printpainter;
     void setPrintPainter( QPainter *printer );
diff --git a/WebCore/khtml/rendering/render_line.cpp b/WebCore/khtml/rendering/render_line.cpp
index 52b7d37..3e0be6d 100644
--- a/WebCore/khtml/rendering/render_line.cpp
+++ b/WebCore/khtml/rendering/render_line.cpp
@@ -563,6 +563,17 @@ void InlineFlowBox::paintDecorations(QPainter *p, int _x, int _y,
     RenderStyle* styleToUse = object()->style(m_firstLine);
     int deco = parent() ? styleToUse->textDecoration() : styleToUse->textDecorationsInEffect();
     if (deco != TDNONE && shouldDrawDecoration(object())) {
+#if APPLE_CHANGES
+        // Set up the appropriate text-shadow effect for the decoration.
+        // FIXME: Support multiple shadow effects.  Need more from the CG API before we can do this.
+        bool setShadow = false;
+        if (styleToUse->textShadow()) {
+            p->setShadow(styleToUse->textShadow()->x, styleToUse->textShadow()->y,
+                         styleToUse->textShadow()->blur, styleToUse->textShadow()->color);
+            setShadow = true;
+        }
+#endif
+        
         // We must have child boxes and have decorations defined.
         _tx += borderLeft() + paddingLeft();
         int w = m_width - (borderLeft() + paddingLeft() + borderRight() + paddingRight());
@@ -582,5 +593,10 @@ void InlineFlowBox::paintDecorations(QPainter *p, int _x, int _y,
             p->setPen(linethrough);
             p->drawLineForText(_tx, _ty, 2*m_baseline/3, w);
         }
+
+#if APPLE_CHANGES
+        if (setShadow)
+            p->clearShadow();
+#endif
     }
 }
diff --git a/WebCore/khtml/rendering/render_style.cpp b/WebCore/khtml/rendering/render_style.cpp
index 3857b6a..978fa0f 100644
--- a/WebCore/khtml/rendering/render_style.cpp
+++ b/WebCore/khtml/rendering/render_style.cpp
@@ -89,7 +89,7 @@ bool StyleBoxData::operator==(const StyleBoxData& o) const
 
 StyleVisualData::StyleVisualData()
     : hasClip(false), textDecoration(TDNONE), colspan( 1 ), counter_increment( 0 ), counter_reset( 0 ),
-      opacity(1.0f), palette( QApplication::palette() )
+      palette( QApplication::palette() )
 {
 }
 
@@ -100,7 +100,7 @@ StyleVisualData::StyleVisualData(const StyleVisualData& o )
     : Shared<StyleVisualData>(),
       clip( o.clip ), hasClip( o.hasClip ), textDecoration(o.textDecoration), colspan( o.colspan ),
       counter_increment( o.counter_increment ), counter_reset( o.counter_reset ),
-      opacity( o.opacity ), palette( o.palette )
+      palette( o.palette )
 {
 }
 
@@ -163,6 +163,48 @@ bool StyleFlexibleBoxData::operator==(const StyleFlexibleBoxData& o) const
            flexed_height == o.flexed_height;
 }
 
+StyleCSS3NonInheritedData::StyleCSS3NonInheritedData()
+:Shared<StyleCSS3NonInheritedData>(), opacity(1.0f)
+{
+    
+}
+
+StyleCSS3NonInheritedData::StyleCSS3NonInheritedData(const StyleCSS3NonInheritedData& o)
+:Shared<StyleCSS3NonInheritedData>(), opacity(o.opacity), flexibleBox(o.flexibleBox)
+{
+}
+
+bool StyleCSS3NonInheritedData::operator==(const StyleCSS3NonInheritedData& o) const
+{
+    return opacity == o.opacity && flexibleBox == o.flexibleBox;
+}
+
+StyleCSS3InheritedData::StyleCSS3InheritedData()
+:Shared<StyleCSS3InheritedData>(), textShadow(0)
+{
+
+}
+
+StyleCSS3InheritedData::StyleCSS3InheritedData(const StyleCSS3InheritedData& o)
+:Shared<StyleCSS3InheritedData>()
+{
+    textShadow = o.textShadow ? new ShadowData(*o.textShadow) : 0;
+}
+
+bool StyleCSS3InheritedData::operator==(const StyleCSS3InheritedData& o) const
+{
+    return shadowDataEquivalent(o);
+}
+
+bool StyleCSS3InheritedData::shadowDataEquivalent(const StyleCSS3InheritedData& o) const
+{
+    if (!textShadow && o.textShadow || textShadow && !o.textShadow)
+        return false;
+    if (textShadow && o.textShadow && (*textShadow != *o.textShadow))
+        return false;
+    return true;
+}
+
 StyleInheritedData::StyleInheritedData()
     : indent( Fixed ), line_height( -100, Percent ), style_image( 0 ),
       cursor_image( 0 ), font(), color( Qt::black ), border_spacing( 0 )
@@ -207,7 +249,8 @@ RenderStyle::RenderStyle()
     visual = _default->visual;
     background = _default->background;
     surround = _default->surround;
-    flexible_box = _default->flexible_box;
+    css3NonInheritedData = _default->css3NonInheritedData;
+    css3InheritedData = _default->css3InheritedData;
     
     inherited = _default->inherited;
 
@@ -225,8 +268,9 @@ RenderStyle::RenderStyle(bool)
     visual.init();
     background.init();
     surround.init();
-    flexible_box.init();
-    
+    css3NonInheritedData.init();
+    css3NonInheritedData.access()->flexibleBox.init();
+    css3InheritedData.init();
     inherited.init();
 
     pseudoStyle = 0;
@@ -237,13 +281,14 @@ RenderStyle::RenderStyle(const RenderStyle& o)
     : Shared<RenderStyle>(),
       inherited_flags( o.inherited_flags ), noninherited_flags( o.noninherited_flags ),
       box( o.box ), visual( o.visual ), background( o.background ), surround( o.surround ),
-      flexible_box( o.flexible_box ),
+      css3NonInheritedData( o.css3NonInheritedData ), css3InheritedData( o.css3InheritedData ),
       inherited( o.inherited ), pseudoStyle( 0 ), content( o.content )
 {
 }
 
 void RenderStyle::inheritFrom(const RenderStyle* inheritParent)
 {
+    css3InheritedData = inheritParent->css3InheritedData;
     inherited = inheritParent->inherited;
     inherited_flags = inheritParent->inherited_flags;
 }
@@ -274,7 +319,8 @@ bool RenderStyle::operator==(const RenderStyle& o) const
             visual == o.visual &&
             background == o.background &&
             surround == o.surround &&
-            flexible_box == o.flexible_box &&
+            css3NonInheritedData == o.css3NonInheritedData &&
+            css3InheritedData == o.css3InheritedData &&
             inherited == o.inherited);
 }
 
@@ -334,11 +380,9 @@ void RenderStyle::removePseudoStyle(PseudoId pid)
 
 bool RenderStyle::inheritedNotEqual( RenderStyle *other ) const
 {
-    return
-	(
-	    inherited_flags != other->inherited_flags ||
-	    inherited != other->inherited
-	    );
+    return inherited_flags != other->inherited_flags ||
+           inherited != other->inherited ||
+           css3InheritedData != other->css3InheritedData;
 }
 
 /*
@@ -377,7 +421,7 @@ RenderStyle::Diff RenderStyle::diff( const RenderStyle *other ) const
 
     if ( *box.get() != *other->box.get() ||
         *surround.get() != *other->surround.get() ||
-         *flexible_box.get() != *other->flexible_box.get() ||
+         *css3NonInheritedData->flexibleBox.get() != *other->css3NonInheritedData->flexibleBox.get() ||
         !(inherited->indent == other->inherited->indent) ||
         !(inherited->line_height == other->inherited->line_height) ||
         !(inherited->style_image == other->inherited->style_image) ||
@@ -464,7 +508,8 @@ RenderStyle::Diff RenderStyle::diff( const RenderStyle *other ) const
         !(visual->clip == other->visual->clip) ||
         visual->hasClip != other->visual->hasClip ||
         visual->textDecoration != other->visual->textDecoration ||
-        visual->opacity != other->visual->opacity ||
+        css3NonInheritedData->opacity != other->css3NonInheritedData->opacity ||
+        !css3InheritedData->shadowDataEquivalent(*other->css3InheritedData.get()) ||
         !(visual->palette == other->visual->palette)
 	)
         return Visible;
@@ -620,3 +665,32 @@ void ContentData::clearContent()
             ;
     }
 }
+
+void RenderStyle::setTextShadow(ShadowData* val, bool add)
+{
+    StyleCSS3InheritedData* css3Data = css3InheritedData.access(); 
+    if (!add) {
+        delete css3Data->textShadow;
+        css3Data->textShadow = val;
+        return;
+    }
+
+    ShadowData* last = css3Data->textShadow;
+    while (last->next) last = last->next;
+    last->next = val;
+}
+
+ShadowData::ShadowData(const ShadowData& o)
+:x(o.x), y(o.y), blur(o.blur), color(o.color)
+{
+    next = o.next ? new ShadowData(*o.next) : 0;
+}
+
+bool ShadowData::operator==(const ShadowData& o) const
+{
+    if ((next && !o.next) || (!next && o.next) ||
+        (next && o.next && *next != *o.next))
+        return false;
+    
+    return x == o.x && y == o.y && blur == o.blur && color == o.color;
+}
diff --git a/WebCore/khtml/rendering/render_style.h b/WebCore/khtml/rendering/render_style.h
index ec2294d..ef967b2 100644
--- a/WebCore/khtml/rendering/render_style.h
+++ b/WebCore/khtml/rendering/render_style.h
@@ -54,6 +54,7 @@
 
 namespace DOM {
     class DOMStringImpl;
+    class ShadowValueImpl;
 }
 
 namespace khtml {
@@ -348,8 +349,6 @@ public:
     short counter_increment; //ok, so these are not visual mode spesific
     short counter_reset;     //can't go to inherited, since these are not inherited
 
-    float opacity;         // Whether or not we're transparent.
-    
     QPalette palette;      //widget styling with IE attributes
 };
 
@@ -411,14 +410,67 @@ public:
     EBoxLines lines : 1;
 };
 
+// This struct holds information about shadows for the text-shadow and box-shadow properties.
+struct ShadowData {
+    ShadowData(int _x, int _y, int _blur, const QColor& _color)
+    :x(_x), y(_y), blur(_blur), color(_color), next(0) {}
+    ShadowData(const ShadowData& o);
+    
+    ~ShadowData() { delete next; }
+
+    bool operator==(const ShadowData& o) const;
+    bool operator!=(const ShadowData &o) const {
+        return !(*this == o);
+    }
+    
+    int x;
+    int y;
+    int blur;
+    QColor color;
+    ShadowData* next;
+};
+
+// This struct is for rarely used non-inherited CSS3 properties.  By grouping them together,
+// we save space, and only allocate this object when someone actually uses
+// a non-inherited CSS3 property.
+class StyleCSS3NonInheritedData : public Shared<StyleCSS3NonInheritedData>
+{
+public:
+    StyleCSS3NonInheritedData();
+    ~StyleCSS3NonInheritedData() {}
+    StyleCSS3NonInheritedData(const StyleCSS3NonInheritedData& o);
+
+    bool operator==(const StyleCSS3NonInheritedData& o) const;
+    bool operator!=(const StyleCSS3NonInheritedData &o) const {
+        return !(*this == o);
+    }
+    
+    float opacity;         // Whether or not we're transparent.
+    DataRef<StyleFlexibleBoxData> flexibleBox; // Flexible box properties 
+};
+
+// This struct is for rarely used inherited CSS3 properties.  By grouping them together,
+// we save space, and only allocate this object when someone actually uses
+// a non-inherited CSS3 property.
+class StyleCSS3InheritedData : public Shared<StyleCSS3InheritedData>
+{
+public:
+    StyleCSS3InheritedData();
+    ~StyleCSS3InheritedData() {}
+    StyleCSS3InheritedData(const StyleCSS3InheritedData& o);
+
+    bool operator==(const StyleCSS3InheritedData& o) const;
+    bool operator!=(const StyleCSS3InheritedData &o) const {
+        return !(*this == o);
+    }
+    bool shadowDataEquivalent(const StyleCSS3InheritedData& o) const;
+
+    ShadowData* textShadow;  // Our text shadow information for shadowed text drawing.
+};
+
 //------------------------------------------------
 // Inherited attributes.
 //
-// the inherited-decoration and inherited-shadow attributes
-// are inherited from the
-// first parent which is block level
-//
-// this applies to decoration_color too
 
 enum EWhiteSpace {
     NORMAL, PRE, NOWRAP, KONQ_NOWRAP
@@ -523,7 +575,7 @@ struct ContentData {
 
     ContentData* _nextContent;
 };
-
+    
 //------------------------------------------------
 
 enum EDisplay {
@@ -622,11 +674,12 @@ protected:
     DataRef<StyleVisualData> visual;
     DataRef<StyleBackgroundData> background;
     DataRef<StyleSurroundData> surround;
-    DataRef<StyleFlexibleBoxData> flexible_box;
+    DataRef<StyleCSS3NonInheritedData> css3NonInheritedData;
     
 // inherited attributes
+    DataRef<StyleCSS3InheritedData> css3InheritedData;
     DataRef<StyleInheritedData> inherited;
-
+    
 // list of associated pseudo styles
     RenderStyle* pseudoStyle;
 
@@ -832,17 +885,19 @@ public:
     CachedImage *cursorImage() const { return inherited->cursor_image; }
 
     // CSS3 Getter Methods
-    float opacity() { return visual->opacity; }
-    EBoxAlignment boxAlign() { return flexible_box->align; }
+    ShadowData* textShadow() const { return css3InheritedData->textShadow; }
+    float opacity() { return css3NonInheritedData->opacity; }
+    EBoxAlignment boxAlign() { return css3NonInheritedData->flexibleBox->align; }
     EBoxDirection boxDirection() { return inherited_flags._box_direction; }
-    float boxFlex() { return flexible_box->flex; }
-    unsigned int boxFlexGroup() { return flexible_box->flex_group; }
-    EBoxLines boxLines() { return flexible_box->lines; }
-    unsigned int boxOrdinalGroup() { return flexible_box->ordinal_group; }
-    EBoxOrient boxOrient() { return flexible_box->orient; }
-    EBoxAlignment boxPack() { return flexible_box->pack; }
-    int boxFlexedHeight() { return flexible_box->flexed_height; }
-    
+    float boxFlex() { return css3NonInheritedData->flexibleBox->flex; }
+    unsigned int boxFlexGroup() { return css3NonInheritedData->flexibleBox->flex_group; }
+    EBoxLines boxLines() { return css3NonInheritedData->flexibleBox->lines; }
+    unsigned int boxOrdinalGroup() { return css3NonInheritedData->flexibleBox->ordinal_group; }
+    EBoxOrient boxOrient() { return css3NonInheritedData->flexibleBox->orient; }
+    EBoxAlignment boxPack() { return css3NonInheritedData->flexibleBox->pack; }
+    int boxFlexedHeight() { return css3NonInheritedData->flexibleBox->flexed_height; }
+    // End CSS3 Getters
+
 // attribute setter methods
 
     void setDisplay(EDisplay v) {  noninherited_flags._effectiveDisplay = v; }
@@ -983,16 +1038,18 @@ public:
     void setZIndex(int v) { SET_VAR(box, z_auto, false); SET_VAR(box,z_index,v) }
 
     // CSS3 Setters
-    void setOpacity(float f) { SET_VAR(visual, opacity, f); }
-    void setBoxAlign(EBoxAlignment a) { SET_VAR(flexible_box, align, a); }
+    void setTextShadow(ShadowData* val, bool add=false);
+    void setOpacity(float f) { SET_VAR(css3NonInheritedData, opacity, f); }
+    void setBoxAlign(EBoxAlignment a) { SET_VAR(css3NonInheritedData.access()->flexibleBox, align, a); }
     void setBoxDirection(EBoxDirection d) { inherited_flags._box_direction = d; }
-    void setBoxFlex(float f) { SET_VAR(flexible_box, flex, f); }
-    void setBoxFlexGroup(unsigned int fg) { SET_VAR(flexible_box, flex_group, fg); }
-    void setBoxLines(EBoxLines l) { SET_VAR(flexible_box, lines, l); }
-    void setBoxOrdinalGroup(unsigned int og) { SET_VAR(flexible_box, ordinal_group, og); }
-    void setBoxOrient(EBoxOrient o) { SET_VAR(flexible_box, orient, o); }
-    void setBoxPack(EBoxAlignment p) { SET_VAR(flexible_box, pack, p); }
-    void setBoxFlexedHeight(int h) { SET_VAR(flexible_box, flexed_height, h); }
+    void setBoxFlex(float f) { SET_VAR(css3NonInheritedData.access()->flexibleBox, flex, f); }
+    void setBoxFlexGroup(unsigned int fg) { SET_VAR(css3NonInheritedData.access()->flexibleBox, flex_group, fg); }
+    void setBoxLines(EBoxLines l) { SET_VAR(css3NonInheritedData.access()->flexibleBox, lines, l); }
+    void setBoxOrdinalGroup(unsigned int og) { SET_VAR(css3NonInheritedData.access()->flexibleBox, ordinal_group, og); }
+    void setBoxOrient(EBoxOrient o) { SET_VAR(css3NonInheritedData.access()->flexibleBox, orient, o); }
+    void setBoxPack(EBoxAlignment p) { SET_VAR(css3NonInheritedData.access()->flexibleBox, pack, p); }
+    void setBoxFlexedHeight(int h) { SET_VAR(css3NonInheritedData.access()->flexibleBox, flexed_height, h); }
+    // End CSS3 Setters
     
     QPalette palette() const { return visual->palette; }
     void setPaletteColor(QPalette::ColorGroup g, QColorGroup::ColorRole r, const QColor& c);
diff --git a/WebCore/khtml/rendering/render_text.cpp b/WebCore/khtml/rendering/render_text.cpp
index b5329ed..03dbdff 100644
--- a/WebCore/khtml/rendering/render_text.cpp
+++ b/WebCore/khtml/rendering/render_text.cpp
@@ -681,17 +681,35 @@ void RenderText::paintObject(QPainter *p, int /*x*/, int y, int /*w*/, int h,
             if(_style->color() != p->pen().color())
                 p->setPen(_style->color());
 
+#if APPLE_CHANGES
+            // Set a text shadow if we have one.
+            // FIXME: Support multiple shadow effects.  Need more from the CG API before
+            // we can do this.
+            bool setShadow = false;
+            if (_style->textShadow()) {
+                p->setShadow(_style->textShadow()->x, _style->textShadow()->y,
+                             _style->textShadow()->blur, _style->textShadow()->color);
+                setShadow = true;
+            }
+#endif
+            
             if (s->m_len > 0) {
                 bool paintSelectedTextOnly = (paintAction == PaintActionSelection);
                 bool paintSelectedTextSeparately = false; // Whether or not we have to do multiple paints.  Only
                                                // necessary when a custom ::selection foreground color is applied.
                 QColor selectionColor = p->pen().color();
+                ShadowData* selectionTextShadow = 0;
                 if (haveSelection) {
                     RenderStyle* pseudoStyle = style()->getPseudoStyle(RenderStyle::SELECTION);
-                    if (pseudoStyle && pseudoStyle->color() != selectionColor) {
-                        if (!paintSelectedTextOnly)
-                            paintSelectedTextSeparately = true;
-                        selectionColor = pseudoStyle->color();
+                    if (pseudoStyle) {
+                        if (pseudoStyle->color() != selectionColor || pseudoStyle->textShadow()) {
+                            if (!paintSelectedTextOnly)
+                                paintSelectedTextSeparately = true;
+                            if (pseudoStyle->color() != selectionColor)
+                                selectionColor = pseudoStyle->color();
+                            if (pseudoStyle->textShadow())
+                                selectionTextShadow = pseudoStyle->textShadow();
+                        }
                     }
                 }
                 
@@ -724,14 +742,25 @@ void RenderText::paintObject(QPainter *p, int /*x*/, int y, int /*w*/, int h,
                     if ( sPos < ePos ) {
                         if (selectionColor != p->pen().color())
                             p->setPen(selectionColor);
-                        
+
+#if APPLE_CHANGES
+                        if (selectionTextShadow)
+                            p->setShadow(selectionTextShadow->x,
+                                         selectionTextShadow->y,
+                                         selectionTextShadow->blur,
+                                         selectionTextShadow->color);
+#endif                       
                         font->drawText(p, s->m_x + tx, s->m_y + ty + s->m_baseline, str->s,
                                        str->l, s->m_start, s->m_len,
                                        s->m_toAdd, s->m_reversed ? QPainter::RTL : QPainter::LTR, sPos, ePos);
+#if APPLE_CHANGES
+                        if (selectionTextShadow)
+                            p->clearShadow();
+#endif
                     }
                 } 
             }
-
+            
             if (d != TDNONE && paintAction == PaintActionForeground &&
                 style()->htmlHacks()) {
                 p->setPen(_style->color());
@@ -739,6 +768,9 @@ void RenderText::paintObject(QPainter *p, int /*x*/, int y, int /*w*/, int h,
             }
 
 #if APPLE_CHANGES
+            if (setShadow)
+                p->clearShadow();
+            
             } // drawText
 #endif
 
diff --git a/WebCore/khtml/xml/dom_nodeimpl.cpp b/WebCore/khtml/xml/dom_nodeimpl.cpp
index 055f745..fc6ed8f 100644
--- a/WebCore/khtml/xml/dom_nodeimpl.cpp
+++ b/WebCore/khtml/xml/dom_nodeimpl.cpp
@@ -885,6 +885,9 @@ bool NodeImpl::childAllowed( NodeImpl *newChild )
 
 NodeImpl::StyleChange NodeImpl::diff( khtml::RenderStyle *s1, khtml::RenderStyle *s2 ) const
 {
+    // FIXME: The behavior of this function is just totally wrong.  It doesn't handle
+    // explicit inheritance of non-inherited properties and so you end up not re-resolving
+    // style in cases where you need to.
     StyleChange ch = NoInherit;
     if ( !s1 || !s2 )
 	ch = Inherit;
diff --git a/WebCore/kwq/KWQColor.h b/WebCore/kwq/KWQColor.h
index 9ba417d..c32274b 100644
--- a/WebCore/kwq/KWQColor.h
+++ b/WebCore/kwq/KWQColor.h
@@ -34,30 +34,30 @@
 class NSColor;
 #endif
 
-typedef unsigned int QRgb;			// RGB triplet
+typedef unsigned int QRgb;			// RGBA quadruplet
 
 QRgb qRgb(int r, int g, int b);
-
-const QRgb KWQInvalidColor = 0x40000000;
+QRgb qRgba(int r, int g, int b, int a);
+int qAlpha(QRgb rgba);
 
 class QColor {
 public:
-    QColor() : color(KWQInvalidColor) { }
-    QColor(QRgb col) : color(col) { }
-    QColor(int r, int g, int b) : color(qRgb(r, g, b)) { }
+    QColor() : color(0), valid(false) { }
+    QColor(QRgb col) : color(col), valid(true) { }
+    QColor(int r, int g, int b) : color(qRgb(r, g, b)), valid(true) { }
     explicit QColor(const char *);
     
     QString name() const;
     void setNamedColor(const QString&);
 
-    bool isValid() const { return color != KWQInvalidColor; }
+    bool isValid() const { return valid; }
 
     int red() const { return (color >> 16) & 0xFF; }
     int green() const { return (color >> 8) & 0xFF; }
     int blue() const { return color & 0xFF; }
-    QRgb rgb() const { return color & 0xFFFFFF; }
-    void setRgb(int r, int g, int b) { color = qRgb(r, g, b); }
-    void setRgb(int rgb) { color = rgb; }
+    QRgb rgb() const { return color & 0xFFFFFFFF; } // Preserve the alpha.
+    void setRgb(int r, int g, int b) { color = qRgb(r, g, b); valid = true; }
+    void setRgb(int rgb) { color = rgb; valid = true; /* Alpha may be set. Preserve it. */ }
 
     void hsv(int *, int *, int *) const;
     void setHsv(int h, int s, int v);
@@ -72,6 +72,7 @@ public:
 
 private:
     QRgb color;
+    bool valid : 1;
 };
 
 inline bool operator==(const QColor &a, const QColor &b)
diff --git a/WebCore/kwq/KWQColor.mm b/WebCore/kwq/KWQColor.mm
index ebfb029..e184409 100644
--- a/WebCore/kwq/KWQColor.mm
+++ b/WebCore/kwq/KWQColor.mm
@@ -40,13 +40,29 @@ QRgb qRgb(int r, int g, int b)
     if (r < 0) r = 0; else if (r > 255) r = 255;
     if (g < 0) g = 0; else if (g > 255) g = 255;
     if (b < 0) b = 0; else if (b > 255) b = 255;
-    return r << 16 | g << 8 | b;
+    return (r << 16 | g << 8 | b) | 0xFF000000;
+}
+
+QRgb qRgba(int r, int g, int b, int a)
+{
+    if (r < 0) r = 0; else if (r > 255) r = 255;
+    if (g < 0) g = 0; else if (g > 255) g = 255;
+    if (b < 0) b = 0; else if (b > 255) b = 255;
+    if (a < 0) a = 0; else if (a > 255) a = 255;
+    return (a << 24 | r << 16 | g << 8 | b);
+}
+
+int qAlpha(QRgb rgba)
+{
+    return (rgba >> 24) & 0xFF; 
 }
 
 QColor::QColor(const char *name)
 {
     const Color *foundColor = findColor(name, strlen(name));
-    color = foundColor ? foundColor->RGBValue : KWQInvalidColor;
+    color = foundColor ? foundColor->RGBValue : 0;
+    color |= 0xFF000000;
+    valid = foundColor;
 }
 
 QString QColor::name() const
@@ -59,7 +75,9 @@ QString QColor::name() const
 void QColor::setNamedColor(const QString &name)
 {
     const Color *foundColor = name.isAllASCII() ? findColor(name.latin1(), name.length()) : 0;
-    color = foundColor ? foundColor->RGBValue : KWQInvalidColor;
+    color = foundColor ? foundColor->RGBValue : 0;
+    color |= 0xFF000000;
+    valid = foundColor;
 }
 
 void QColor::hsv(int *h, int *s, int *v) const
@@ -196,7 +214,7 @@ QColor QColor::dark(int factor) const
 
 NSColor *QColor::getNSColor() const
 {
-    unsigned c = color & 0xFFFFFF;
+    unsigned c = color & 0xFFFFFFFF;
     switch (c) {
         case Qt::black: {
             static NSColor *blackColor = [[NSColor blackColor] retain];
@@ -208,11 +226,11 @@ NSColor *QColor::getNSColor() const
         }
         default: {
             const int cacheSize = 32;
-            static unsigned cachedRGBValues[cacheSize];
+            static unsigned cachedRGBAValues[cacheSize];
             static NSColor *cachedColors[cacheSize];
 
             for (int i = 0; i != cacheSize; ++i) {
-                if (cachedRGBValues[i] == c) {
+                if (cachedRGBAValues[i] == c) {
                     return cachedColors[i];
                 }
             }
@@ -220,10 +238,10 @@ NSColor *QColor::getNSColor() const
             NSColor *result = [NSColor colorWithCalibratedRed:red() / 255.0
                                                         green:green() / 255.0
                                                          blue:blue() / 255.0
-                                                        alpha:1.0];
+                                                        alpha: qAlpha(color)/255.0];
 
             static int cursor;
-            cachedRGBValues[cursor] = c;
+            cachedRGBAValues[cursor] = c;
             [cachedColors[cursor] autorelease];
             cachedColors[cursor] = [result retain];
             if (++cursor == cacheSize) {
diff --git a/WebCore/kwq/KWQNamespace.h b/WebCore/kwq/KWQNamespace.h
index 3d9dfae..b7f8ea4 100644
--- a/WebCore/kwq/KWQNamespace.h
+++ b/WebCore/kwq/KWQNamespace.h
@@ -226,11 +226,11 @@ public:
         XorROP,
     };
 
-    static const unsigned black = 0x000000;
-    static const unsigned white = 0xFFFFFF;
-    static const unsigned darkGray = 0x808080;
-    static const unsigned gray = 0xA0A0A0;
-    static const unsigned lightGray = 0xC0C0C0;
+    static const unsigned black = 0xFF000000;
+    static const unsigned white = 0xFFFFFFFF;
+    static const unsigned darkGray = 0xFF808080;
+    static const unsigned gray = 0xFFA0A0A0;
+    static const unsigned lightGray = 0xFFC0C0C0;
 
 };
 
diff --git a/WebCore/kwq/KWQPainter.h b/WebCore/kwq/KWQPainter.h
index c7f51cf..21a42da 100644
--- a/WebCore/kwq/KWQPainter.h
+++ b/WebCore/kwq/KWQPainter.h
@@ -107,6 +107,9 @@ public:
         
     void beginTransparencyLayer(float opacity);
     void endTransparencyLayer();
+
+    void setShadow(int x, int y, int blur, const QColor& color);
+    void clearShadow();
     
 private:
     // no copying or assignment
@@ -116,6 +119,9 @@ private:
     void _setColorFromBrush();
     void _setColorFromPen();
 
+    // A fillRect designed to work around buggy behavior in NSRectFill.
+    void _fillRect(float x, float y, float w, float h, const QColor& color);
+    
     void _drawPoints(const QPointArray &_points, bool winding, int index, int _npoints, bool fill);
 
     void _updateRenderer(NSString **families);
diff --git a/WebCore/kwq/KWQPainter.mm b/WebCore/kwq/KWQPainter.mm
index 275fb38..19148a4 100644
--- a/WebCore/kwq/KWQPainter.mm
+++ b/WebCore/kwq/KWQPainter.mm
@@ -169,11 +169,9 @@ void QPainter::drawRect(int x, int y, int w, int h)
     if (data->state.paintingDisabled)
         return;
         
-    if (data->state.brush.style() != NoBrush) {
-        _setColorFromBrush();
-        
-        NSRectFillUsingOperation (NSMakeRect(x,y,w,h), NSCompositeSourceOver);
-    }
+    if (data->state.brush.style() != NoBrush)
+        _fillRect(x, y, w, h, data->state.brush.color());
+
     if (data->state.pen.style() != NoPen) {
         _setColorFromPen();
         NSFrameRect(NSMakeRect(x, y, w, h));
@@ -195,7 +193,7 @@ void QPainter::drawLine(int x1, int y1, int x2, int y2)
 {
     if (data->state.paintingDisabled)
         return;
-        
+
     PenStyle penStyle = data->state.pen.style();
     if (penStyle == NoPen)
         return;
@@ -251,6 +249,7 @@ void QPainter::drawLine(int x1, int y1, int x2, int y2)
     }
 
     _setColorFromPen();
+    
     NSGraphicsContext *graphicsContext = [NSGraphicsContext currentContext];
     BOOL flag = [graphicsContext shouldAntialias];
     [graphicsContext setShouldAntialias: NO];
@@ -259,12 +258,12 @@ void QPainter::drawLine(int x1, int y1, int x2, int y2)
         // Do a rect fill of our endpoints.  This ensures we always have the
         // appearance of being a border.  We then draw the actual dotted/dashed line.
         if (x1 == x2) {
-            NSRectFill(NSMakeRect(p1.x-width/2, p1.y-width, width, width));
-            NSRectFill(NSMakeRect(p2.x-width/2, p2.y, width, width));
+            _fillRect(p1.x-width/2, p1.y-width, width, width, data->state.pen.color());
+            _fillRect(p2.x-width/2, p2.y, width, width, data->state.pen.color());
         }
         else {
-            NSRectFill(NSMakeRect(p1.x-width, p1.y-width/2, width, width));
-            NSRectFill(NSMakeRect(p2.x, p2.y-width/2, width, width));
+            _fillRect(p1.x-width, p1.y-width/2, width, width, data->state.pen.color());
+            _fillRect(p2.x, p2.y-width/2, width, width, data->state.pen.color());
         }
         
         // Example: 80 pixels with a width of 30 pixels.
@@ -533,15 +532,19 @@ QColor QPainter::selectedTextBackgroundColor() const
     return QColor((int)(255 * [color redComponent]), (int)(255 * [color greenComponent]), (int)(255 * [color blueComponent]));
 }
 
+void QPainter::_fillRect(float x, float y, float w, float h, const QColor& col)
+{
+    [col.getNSColor() set];
+    NSRectFillUsingOperation(NSMakeRect(x,y,w,h), NSCompositeSourceOver);
+}
+
 void QPainter::fillRect(int x, int y, int w, int h, const QBrush &brush)
 {
     if (data->state.paintingDisabled)
         return;
-    
-    if (brush.style() == SolidPattern) {
-        [brush.color().getNSColor() set];
-        NSRectFill(NSMakeRect(x, y, w, h));
-    }
+
+    if (brush.style() == SolidPattern)
+        _fillRect(x, y, w, h, brush.color());
 }
 
 void QPainter::addClip(const QRect &rect)
@@ -571,8 +574,8 @@ bool QPainter::paintingDisabled() const
 void QPainter::beginTransparencyLayer(float opacity)
 {
     CGContextRef context = (CGContextRef)([[NSGraphicsContext currentContext] graphicsPort]);
-    CGContextBeginTransparencyLayer(context, 0);
     CGContextSetAlpha(context, opacity);
+    CGContextBeginTransparencyLayer(context, 0);
 }
 
 void QPainter::endTransparencyLayer()
@@ -581,3 +584,18 @@ void QPainter::endTransparencyLayer()
     CGContextEndTransparencyLayer(context);
 }
 
+void QPainter::setShadow(int x, int y, int blur, const QColor& color)
+{
+    // FIXME: When CG supports setting the shadow color, we will use it here. An invalid
+    // color should be checked for, as this means that the color was not set for the shadow
+    // and we should therefore do nothing in that case.
+    CGContextRef context = (CGContextRef)([[NSGraphicsContext currentContext] graphicsPort]);
+    CGContextSetShadow(context, CGSizeMake(x,-y), blur); // y is flipped.
+}
+
+void QPainter::clearShadow()
+{
+    CGContextRef context = (CGContextRef)([[NSGraphicsContext currentContext] graphicsPort]);
+    CGContextSetShadow(context, CGSizeZero, 0);
+}
+

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list