Changeset 26894 in webkit


Ignore:
Timestamp:
Oct 22, 2007 2:29:37 PM (16 years ago)
Author:
hyatt
Message:

Fix for bug 15624, make transforms work properly with opacity.

Make sure a unitless 0 is allowed as an angle argument to rotation/skew.

Reviewed by Mitz Pettel

fast/transforms/transforms-with-opacity.html
fast/transforms/skew-with-unitless-zero.html

  • css/CSSParser.cpp: (WebCore::CSSParser::validUnit):
  • rendering/RenderLayer.cpp: (WebCore::transparencyClipBox): (WebCore::RenderLayer::beginTransparencyLayers): (WebCore::RenderLayer::paintLayer): (WebCore::RenderLayer::calculateClipRects):
  • rendering/RenderLayer.h: (WebCore::RenderLayer::transform):
Location:
trunk/WebCore
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/WebCore/ChangeLog

    r26889 r26894  
     12007-10-22  David Hyatt  <hyatt@apple.com>
     2
     3        Fix for bug 15624, make transforms work properly with opacity.
     4
     5        Make sure a unitless 0 is allowed as an angle argument to rotation/skew.
     6
     7        Reviewed by Mitz Pettel
     8
     9        fast/transforms/transforms-with-opacity.html
     10        fast/transforms/skew-with-unitless-zero.html
     11
     12        * css/CSSParser.cpp:
     13        (WebCore::CSSParser::validUnit):
     14        * rendering/RenderLayer.cpp:
     15        (WebCore::transparencyClipBox):
     16        (WebCore::RenderLayer::beginTransparencyLayers):
     17        (WebCore::RenderLayer::paintLayer):
     18        (WebCore::RenderLayer::calculateClipRects):
     19        * rendering/RenderLayer.h:
     20        (WebCore::RenderLayer::transform):
     21
    1222007-10-22  Adam Roben  <aroben@apple.com>
    223
  • trunk/WebCore/css/CSSParser.cpp

    r26843 r26894  
    388388    case CSSPrimitiveValue::CSS_NUMBER:
    389389        b = (unitflags & FNumber);
    390         if (!b && ((unitflags & FLength) && (value->fValue == 0 || !strict))) {
    391             value->unit = CSSPrimitiveValue::CSS_PX;
     390        if (!b && ((unitflags & (FLength | FAngle)) && (value->fValue == 0 || !strict))) {
     391            value->unit = (unitflags & FLength) ? CSSPrimitiveValue::CSS_PX : CSSPrimitiveValue::CSS_DEG;
    392392            b = true;
    393393        }
  • trunk/WebCore/rendering/RenderLayer.cpp

    r26865 r26894  
    437437}
    438438
    439 static IntRect transparencyClipBox(const RenderLayer* l, const RenderLayer* rootLayer)
    440 {
    441     // FIXME: This function does not work properly with transforms.
    442 
    443     // FIXME: Although this completely ignores clipping, we ultimately intersect with the
     439static IntRect transparencyClipBox(const AffineTransform& enclosingTransform, const RenderLayer* l, const RenderLayer* rootLayer)
     440{
     441    // FIXME: Although this function completely ignores CSS-imposed clipping, we did already intersect with the
    444442    // paintDirtyRect, and that should cut down on the amount we have to paint.  Still it
    445443    // would be better to respect clips.
     444   
     445    AffineTransform* t = l->transform();
     446    if (t) {
     447        // The best we can do here is to use enclosed bounding boxes to establish a "fuzzy" enough clip to encompass
     448        // the transformed layer and all of its children.
     449        int x = 0;
     450        int y = 0;
     451        l->convertToLayerCoords(rootLayer, x, y);
     452        AffineTransform transform;
     453        transform.translate(x, y);
     454        transform = *t * transform;
     455        transform = transform * enclosingTransform;
     456       
     457        // We now have a transform that will produce a rectangle in our view's space.
     458        IntRect clipRect = transform.mapRect(l->boundingBox(l));
     459       
     460        // Now shift the root layer to be us and pass down the new enclosing transform.
     461        for (RenderLayer* curr = l->firstChild(); curr; curr = curr->nextSibling())
     462            clipRect.unite(transparencyClipBox(transform, curr, l));
     463           
     464        return clipRect;
     465    }
     466   
     467    // Note: we don't have to walk z-order lists since transparent elements always establish
     468    // a stacking context.  This means we can just walk the layer tree directly.
    446469    IntRect clipRect = l->boundingBox(rootLayer);
    447    
    448     // Note: we don't have to walk z-order lists since transparent elements always establish
    449     // a stacking context.  This means we can just walk the layer tree directly.
    450470    for (RenderLayer* curr = l->firstChild(); curr; curr = curr->nextSibling())
    451         clipRect.unite(transparencyClipBox(curr, rootLayer));
     471        clipRect.unite(transparencyClipBox(enclosingTransform, curr, rootLayer));
    452472   
    453473    return clipRect;
    454474}
    455475
    456 void RenderLayer::beginTransparencyLayers(GraphicsContext* p, const IntRect& paintDirtyRect, const RenderLayer* rootLayer)
     476void RenderLayer::beginTransparencyLayers(GraphicsContext* p, const RenderLayer* rootLayer)
    457477{
    458478    if (p->paintingDisabled() || (isTransparent() && m_usedTransparency))
     
    461481    RenderLayer* ancestor = transparentAncestor();
    462482    if (ancestor)
    463         ancestor->beginTransparencyLayers(p, paintDirtyRect, rootLayer);
     483        ancestor->beginTransparencyLayers(p, rootLayer);
    464484   
    465485    if (isTransparent()) {
    466486        m_usedTransparency = true;
    467         IntRect clipRect = transparencyClipBox(this, rootLayer);
    468         clipRect.intersect(paintDirtyRect);
    469487        p->save();
    470         p->clip(clipRect);
     488        p->clip(transparencyClipBox(AffineTransform(), this, rootLayer));
    471489        p->beginTransparencyLayer(renderer()->opacity());
    472490    }
     
    14451463        return;
    14461464   
     1465    // If this layer is totally invisible then there is nothing to paint.
     1466    if (!m_object->opacity())
     1467        return;
     1468
     1469    if (isTransparent())
     1470        haveTransparency = true;
     1471
    14471472    // Apply a transform if we have one.
    14481473    if (m_transform && rootLayer != this) {
     
    14511476            return;
    14521477
     1478        // If we have a transparency layer enclosing us and we are the root of a transform, then we need to establish the transparency
     1479        // layer from the parent now.
     1480        if (haveTransparency)
     1481            parent()->beginTransparencyLayers(p, rootLayer);
     1482 
    14531483        // Make sure the parent's clip rects have been calculated.
    14541484        parent()->calculateClipRects(rootLayer);
     
    14711501        p->save();
    14721502        p->concatCTM(transform);
    1473        
     1503
    14741504        // Now do a paint with the root layer shifted to be us.
    1475         // FIXME: We aren't handling transparency correctly yet.  We need to aggressively begin the transparency layer
    1476         // now so that the clip box will be computed properly.
    14771505        rootLayer = this;
    14781506        paintLayer(this, p, transform.inverse().mapRect(paintDirtyRect), haveTransparency, paintRestriction, paintingRoot);
     
    14981526    updateOverflowList();
    14991527
    1500     // If this layer is totally invisible then there is nothing to paint.
    1501     if (!m_object->opacity())
    1502         return;
    1503        
    15041528    bool selectionOnly = paintRestriction == PaintRestrictionSelectionOnly || paintRestriction == PaintRestrictionSelectionOnlyBlackText;
    15051529    bool forceBlackText = paintRestriction == PaintRestrictionSelectionOnlyBlackText;
    1506 
    1507     if (isTransparent())
    1508         haveTransparency = true;
    15091530   
    15101531    // If this layer's renderer is a child of the paintingRoot, we render unconditionally, which
     
    15151536    if (paintingRoot && !m_object->isDescendantOf(paintingRoot))
    15161537        paintingRootForRenderer = paintingRoot;
    1517    
     1538
    15181539    // We want to paint our layer, but only if we intersect the damage rect.
    15191540    bool shouldPaint = intersectsDamageRect(layerBounds, damageRect, rootLayer) && m_hasVisibleContent;
     
    15211542        // Begin transparency layers lazily now that we know we have to paint something.
    15221543        if (haveTransparency)
    1523             beginTransparencyLayers(p, paintDirtyRect, rootLayer);
     1544            beginTransparencyLayers(p, rootLayer);
    15241545       
    15251546        // Paint our background first, before painting any child layers.
     
    15491570        // Begin transparency layers lazily now that we know we have to paint something.
    15501571        if (haveTransparency)
    1551             beginTransparencyLayers(p, paintDirtyRect, rootLayer);
     1572            beginTransparencyLayers(p, rootLayer);
    15521573
    15531574        // Set up the clip used when painting our children.
     
    17431764
    17441765    if (rootLayer == this || !parent()) {
    1745         // The root layer's clip rect is always just its dimensions.
    1746         m_clipRects = new (m_object->renderArena()) ClipRects(IntRect(0,0,width(),height()));
     1766        // The root layer's clip rect is always infinite.
     1767        m_clipRects = new (m_object->renderArena()) ClipRects(IntRect(INT_MIN/2, INT_MIN/2, INT_MAX, INT_MAX));
    17471768        m_clipRects->ref();
    17481769        return;
  • trunk/WebCore/rendering/RenderLayer.h

    r26843 r26894  
    212212    bool isTransparent() const;
    213213    RenderLayer* transparentAncestor();
    214     void beginTransparencyLayers(GraphicsContext*, const IntRect&, const RenderLayer* rootLayer);
     214    void beginTransparencyLayers(GraphicsContext*, const RenderLayer* rootLayer);
    215215
    216216    const RenderLayer* root() const
     
    350350    void setStaticY(int staticY) { m_staticY = staticY; }
    351351
     352    AffineTransform* transform() const { return m_transform.get(); }
     353
    352354    void destroy(RenderArena*);
    353355
Note: See TracChangeset for help on using the changeset viewer.