Changeset 21601 in webkit


Ignore:
Timestamp:
May 19, 2007 3:54:26 PM (17 years ago)
Author:
bdash
Message:

2007-05-19 Mitz Pettel <mitz@webkit.org>

Reviewed by Darin.

Test for a rendering bug fixed by this patch:

fast/box-shadow/border-radius-big.html

No test for the performance ingredient.

  • platform/graphics/GraphicsContext.cpp: (WebCore::GraphicsContext::addRoundedRectClip): Made cross-platform. Changed to use a single clipping path. If all the radii cannot be accommodated, clips to a rect. (WebCore::GraphicsContext::clipOutRoundedRect): Changed to use a single clipping path. If all the radii cannot be accommodated, clips out a rect.
  • platform/graphics/GraphicsContext.h: Added clipOut(const Path&).
  • platform/graphics/Path.cpp: (WebCore::Path::createRoundedRectangle): Added. Returns a rounded rectangle with the specified radii. If all the radii cannot be accommodated, returns a rectangular path.
  • platform/graphics/Path.h:
  • platform/graphics/cairo/GraphicsContextCairo.cpp: (WebCore::GraphicsContext::clipOut): Added.
  • platform/graphics/cg/GraphicsContextCG.cpp: (WebCore::GraphicsContext::fillRoundedRect): Changed to use a single path. (WebCore::GraphicsContext::clipOut): Added.
  • platform/graphics/qt/GraphicsContextQt.cpp: (WebCore::GraphicsContext::clipOut): Added.

2007-05-19 Mitz Pettel <mitz@webkit.org>

Reviewed by Darin.

  • fast/box-shadow/border-radius-big-expected.checksum: Added.
  • fast/box-shadow/border-radius-big-expected.png: Added.
  • fast/box-shadow/border-radius-big-expected.txt: Added.
  • fast/box-shadow/border-radius-big.html: Added.
Location:
trunk
Files:
4 added
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r21600 r21601  
     12007-05-19  Mitz Pettel  <mitz@webkit.org>
     2
     3        Reviewed by Darin.
     4
     5        - http://bugs.webkit.org/show_bug.cgi?id=13320
     6          rounded corners with drop shadows are really slow
     7
     8        * fast/box-shadow/border-radius-big-expected.checksum: Added.
     9        * fast/box-shadow/border-radius-big-expected.png: Added.
     10        * fast/box-shadow/border-radius-big-expected.txt: Added.
     11        * fast/box-shadow/border-radius-big.html: Added.
     12
    1132007-05-19  Anders Carlsson  <andersca@apple.com>
    214
  • trunk/WebCore/ChangeLog

    r21600 r21601  
     12007-05-19  Mitz Pettel  <mitz@webkit.org>
     2
     3        Reviewed by Darin.
     4
     5        - http://bugs.webkit.org/show_bug.cgi?id=13320
     6          rounded corners with drop shadows are really slow
     7
     8        Test for a rendering bug fixed by this patch:
     9            fast/box-shadow/border-radius-big.html
     10
     11        No test for the performance ingredient.
     12
     13        * platform/graphics/GraphicsContext.cpp:
     14        (WebCore::GraphicsContext::addRoundedRectClip): Made cross-platform.
     15        Changed to use a single clipping path. If all the radii cannot be
     16        accommodated, clips to a rect.
     17        (WebCore::GraphicsContext::clipOutRoundedRect): Changed to use a single
     18        clipping path. If all the radii cannot be accommodated, clips out a rect.
     19        * platform/graphics/GraphicsContext.h: Added clipOut(const Path&).
     20        * platform/graphics/Path.cpp:
     21        (WebCore::Path::createRoundedRectangle): Added. Returns a rounded rectangle
     22        with the specified radii. If all the radii cannot be accommodated, returns
     23        a rectangular path.
     24        * platform/graphics/Path.h:
     25        * platform/graphics/cairo/GraphicsContextCairo.cpp:
     26        (WebCore::GraphicsContext::clipOut): Added.
     27        * platform/graphics/cg/GraphicsContextCG.cpp:
     28        (WebCore::GraphicsContext::fillRoundedRect): Changed to use a single path.
     29        (WebCore::GraphicsContext::clipOut): Added.
     30        * platform/graphics/qt/GraphicsContextQt.cpp:
     31        (WebCore::GraphicsContext::clipOut): Added.
     32
    1332007-05-19  Anders Carlsson  <andersca@apple.com>
    234
  • trunk/WebCore/platform/graphics/GraphicsContext.cpp

    r20646 r21601  
    316316}
    317317
     318void GraphicsContext::addRoundedRectClip(const IntRect& rect, const IntSize& topLeft, const IntSize& topRight,
     319    const IntSize& bottomLeft, const IntSize& bottomRight)
     320{
     321    if (paintingDisabled())
     322        return;
     323
     324    clip(Path::createRoundedRectangle(rect, topLeft, topRight, bottomLeft, bottomRight));
     325}
     326
    318327void GraphicsContext::clipOutRoundedRect(const IntRect& rect, const IntSize& topLeft, const IntSize& topRight,
    319328                                         const IntSize& bottomLeft, const IntSize& bottomRight)
     
    321330    if (paintingDisabled())
    322331        return;
    323        
    324     // Need sufficient width and height to contain these curves.  Sanity check our
    325     // corner radii and our width/height values to make sure the curves can all fit.
    326     if (static_cast<unsigned>(rect.width()) < static_cast<unsigned>(topLeft.width()) + static_cast<unsigned>(topRight.width()) ||
    327         static_cast<unsigned>(rect.width()) < static_cast<unsigned>(bottomLeft.width()) + static_cast<unsigned>(bottomRight.width()) ||
    328         static_cast<unsigned>(rect.height()) < static_cast<unsigned>(topLeft.height()) + static_cast<unsigned>(bottomLeft.height()) ||
    329         static_cast<unsigned>(rect.height()) < static_cast<unsigned>(topRight.height()) + static_cast<unsigned>(bottomRight.height()))
    330         return;
    331    
    332     // Clip out each shape one by one.
    333     clipOutEllipseInRect(IntRect(rect.x(), rect.y(), topLeft.width() * 2, topLeft.height() * 2));
    334     clipOutEllipseInRect(IntRect(rect.right() - topRight.width() * 2, rect.y(), topRight.width() * 2, topRight.height() * 2));
    335     clipOutEllipseInRect(IntRect(rect.x(), rect.bottom() - bottomLeft.height() * 2, bottomLeft.width() * 2, bottomLeft.height() * 2));
    336     clipOutEllipseInRect(IntRect(rect.right() - bottomRight.width() * 2, rect.bottom() - bottomRight.height() * 2, bottomRight.width() * 2, bottomRight.height() * 2));
    337     clipOut(IntRect(rect.x() + topLeft.width(), rect.y(),
    338                     rect.width() - topLeft.width() - topRight.width(),
    339                     max(topLeft.height(), topRight.height())));
    340     clipOut(IntRect(rect.x() + bottomLeft.width(),
    341                     rect.bottom() - max(bottomLeft.height(), bottomRight.height()),
    342                     rect.width() - bottomLeft.width() - bottomRight.width(),
    343                     max(bottomLeft.height(), bottomRight.height())));
    344     clipOut(IntRect(rect.x(), rect.y() + topLeft.height(),
    345                     max(topLeft.width(), bottomLeft.width()), rect.height() - topLeft.height() - bottomLeft.height()));
    346     clipOut(IntRect(rect.right() - max(topRight.width(), bottomRight.width()),
    347                     rect.y() + topRight.height(),
    348                     max(topRight.width(), bottomRight.width()), rect.height() - topRight.height() - bottomRight.height()));
    349     clipOut(IntRect(rect.x() + max(topLeft.width(), bottomLeft.width()),
    350                     rect.y() + max(topLeft.height(), topRight.height()),
    351                     rect.width() - max(topLeft.width(), bottomLeft.width()) - max(topRight.width(), bottomRight.width()),
    352                     rect.height() - max(topLeft.height(), topRight.height()) - max(bottomLeft.height(), bottomRight.height())));
     332
     333    clipOut(Path::createRoundedRectangle(rect, topLeft, topRight, bottomLeft, bottomRight));
    353334}
    354335
  • trunk/WebCore/platform/graphics/GraphicsContext.h

    r20646 r21601  
    178178
    179179        void beginPath();
    180         void addPath(const Path& path);
     180        void addPath(const Path&);
    181181
    182182        void clip(const Path&);
     183        void clipOut(const Path&);
    183184
    184185        void scale(const FloatSize&);
  • trunk/WebCore/platform/graphics/Path.cpp

    r19970 r21601  
    159159}
    160160
     161Path Path::createRoundedRectangle(const FloatRect& rectangle, const FloatSize& topLeftRadius, const FloatSize& topRightRadius, const FloatSize& bottomLeftRadius, const FloatSize& bottomRightRadius)
     162{
     163    Path path;
     164
     165    float width = rectangle.width();
     166    float height = rectangle.height();
     167    if (width <= 0.0 || height <= 0.0)
     168        return path;
     169
     170    if (width < topLeftRadius.width() + topRightRadius.width()
     171            || width < bottomLeftRadius.width() + bottomRightRadius.width()
     172            || height < topLeftRadius.height() + bottomLeftRadius.height()
     173            || height < topRightRadius.height() + bottomRightRadius.height())
     174        // If all the radii cannot be accommodated, return a rect.
     175        return createRectangle(rectangle);
     176
     177    float x = rectangle.x();
     178    float y = rectangle.y();
     179
     180    path.moveTo(FloatPoint(x + topLeftRadius.width(), y));
     181
     182    path.addLineTo(FloatPoint(x + width - topRightRadius.width(), y));
     183
     184    path.addBezierCurveTo(FloatPoint(x + width - topRightRadius.width() * (1 - QUARTER), y), FloatPoint(x + width, y + topRightRadius.height() * (1 - QUARTER)), FloatPoint(x + width, y + topRightRadius.height()));
     185
     186    path.addLineTo(FloatPoint(x + width, y + height - bottomRightRadius.height()));
     187
     188    path.addBezierCurveTo(FloatPoint(x + width, y + height - bottomRightRadius.height() * (1 - QUARTER)), FloatPoint(x + width - bottomRightRadius.width() * (1 - QUARTER), y + height), FloatPoint(x + width - bottomRightRadius.width(), y + height));
     189
     190    path.addLineTo(FloatPoint(x + bottomLeftRadius.width(), y + height));
     191
     192    path.addBezierCurveTo(FloatPoint(x + bottomLeftRadius.width() * (1 - QUARTER), y + height), FloatPoint(x, y + height - bottomLeftRadius.height() * (1 - QUARTER)), FloatPoint(x, y + height - bottomLeftRadius.height()));
     193
     194    path.addLineTo(FloatPoint(x, y + topLeftRadius.height()));
     195
     196    path.addBezierCurveTo(FloatPoint(x, y + topLeftRadius.height() * (1 - QUARTER)), FloatPoint(x + topLeftRadius.width() * (1 - QUARTER), y), FloatPoint(x + topLeftRadius.width(), y));
     197
     198    path.closeSubpath();
     199
     200    return path;
     201}
     202
    161203Path Path::createRectangle(const FloatRect& rectangle)
    162204{
  • trunk/WebCore/platform/graphics/Path.h

    r18518 r21601  
    104104
    105105        static Path createRoundedRectangle(const FloatRect&, const FloatSize& roundingRadii);
     106        static Path createRoundedRectangle(const FloatRect&, const FloatSize& topLeftRadius, const FloatSize& topRightRadius, const FloatSize& bottomLeftRadius, const FloatSize& bottomRightRadius);
    106107        static Path createRectangle(const FloatRect&);
    107108        static Path createEllipse(const FloatPoint& center, float rx, float ry);
  • trunk/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp

    r21134 r21601  
    547547{
    548548    notImplemented();
    549 }
    550 
    551 void GraphicsContext::addRoundedRectClip(const IntRect& rect, const IntSize& topLeft, const IntSize& topRight,
    552         const IntSize& bottomLeft, const IntSize& bottomRight)
    553 {
    554     notImplemented();
    555549}
    556550
     
    704698}
    705699
     700void GraphicsContext::clipOut(const Path&)
     701{
     702    notImplemented();
     703}
     704
    706705void GraphicsContext::rotate(float angle)
    707706{
  • trunk/WebCore/platform/graphics/cg/GraphicsContextCG.cpp

    r21074 r21601  
    437437        setCGFillColor(context, color);
    438438
    439     // Add the four ellipses to the path.  Technically this really isn't good enough, since we could end up
    440     // not clipping the other 3/4 of the ellipse we don't care about.  We're relying on the fact that for
    441     // normal use cases these ellipses won't overlap one another (or when they do the curvature of one will
    442     // be subsumed by the other).
    443     CGContextAddEllipseInRect(context, CGRectMake(rect.x(), rect.y(), topLeft.width() * 2, topLeft.height() * 2));
    444     CGContextAddEllipseInRect(context, CGRectMake(rect.right() - topRight.width() * 2, rect.y(),
    445                                                   topRight.width() * 2, topRight.height() * 2));
    446     CGContextAddEllipseInRect(context, CGRectMake(rect.x(), rect.bottom() - bottomLeft.height() * 2,
    447                                                   bottomLeft.width() * 2, bottomLeft.height() * 2));
    448     CGContextAddEllipseInRect(context, CGRectMake(rect.right() - bottomRight.width() * 2,
    449                                                   rect.bottom() - bottomRight.height() * 2,
    450                                                   bottomRight.width() * 2, bottomRight.height() * 2));
    451    
    452     // Now add five rects (one for each edge rect in between the rounded corners and one for the interior).
    453     CGContextAddRect(context, CGRectMake(rect.x() + topLeft.width(), rect.y(),
    454                                          rect.width() - topLeft.width() - topRight.width(),
    455                                          max(topLeft.height(), topRight.height())));
    456     CGContextAddRect(context, CGRectMake(rect.x() + bottomLeft.width(),
    457                                          rect.bottom() - max(bottomLeft.height(), bottomRight.height()),
    458                                          rect.width() - bottomLeft.width() - bottomRight.width(),
    459                                          max(bottomLeft.height(), bottomRight.height())));
    460     CGContextAddRect(context, CGRectMake(rect.x(), rect.y() + topLeft.height(),
    461                                          max(topLeft.width(), bottomLeft.width()), rect.height() - topLeft.height() - bottomLeft.height()));
    462     CGContextAddRect(context, CGRectMake(rect.right() - max(topRight.width(), bottomRight.width()),
    463                                          rect.y() + topRight.height(),
    464                                          max(topRight.width(), bottomRight.width()), rect.height() - topRight.height() - bottomRight.height()));
    465     CGContextAddRect(context, CGRectMake(rect.x() + max(topLeft.width(), bottomLeft.width()),
    466                                          rect.y() + max(topLeft.height(), topRight.height()),
    467                                          rect.width() - max(topLeft.width(), bottomLeft.width()) - max(topRight.width(), bottomRight.width()),
    468                                          rect.height() - max(topLeft.height(), topRight.height()) - max(bottomLeft.height(), bottomRight.height())));
     439    addPath(Path::createRoundedRectangle(rect, topLeft, topRight, bottomLeft, bottomRight));
    469440    CGContextFillPath(context);
     441
    470442    if (oldFillColor != color)
    471443        setCGFillColor(context, oldFillColor);
     
    501473    CGContextAddEllipseInRect(platformContext(), rect);
    502474    CGContextEOClip(platformContext());
    503 }
    504 
    505 void GraphicsContext::addRoundedRectClip(const IntRect& rect, const IntSize& topLeft, const IntSize& topRight,
    506     const IntSize& bottomLeft, const IntSize& bottomRight)
    507 {
    508     if (paintingDisabled())
    509         return;
    510 
    511     // Need sufficient width and height to contain these curves.  Sanity check our
    512     // corner radii and our width/height values to make sure the curves can all fit.
    513     if (static_cast<unsigned>(rect.width()) < static_cast<unsigned>(topLeft.width()) + static_cast<unsigned>(topRight.width()) ||
    514         static_cast<unsigned>(rect.width()) < static_cast<unsigned>(bottomLeft.width()) + static_cast<unsigned>(bottomRight.width()) ||
    515         static_cast<unsigned>(rect.height()) < static_cast<unsigned>(topLeft.height()) + static_cast<unsigned>(bottomLeft.height()) ||
    516         static_cast<unsigned>(rect.height()) < static_cast<unsigned>(topRight.height()) + static_cast<unsigned>(bottomRight.height()))
    517         return;
    518  
    519     // Clip to our rect.
    520     clip(rect);
    521 
    522     // OK, the curves can fit.
    523     CGContextRef context = platformContext();
    524    
    525     // Add the four ellipses to the path.  Technically this really isn't good enough, since we could end up
    526     // not clipping the other 3/4 of the ellipse we don't care about.  We're relying on the fact that for
    527     // normal use cases these ellipses won't overlap one another (or when they do the curvature of one will
    528     // be subsumed by the other).
    529     CGContextAddEllipseInRect(context, CGRectMake(rect.x(), rect.y(), topLeft.width() * 2, topLeft.height() * 2));
    530     CGContextAddEllipseInRect(context, CGRectMake(rect.right() - topRight.width() * 2, rect.y(),
    531                                                   topRight.width() * 2, topRight.height() * 2));
    532     CGContextAddEllipseInRect(context, CGRectMake(rect.x(), rect.bottom() - bottomLeft.height() * 2,
    533                                                   bottomLeft.width() * 2, bottomLeft.height() * 2));
    534     CGContextAddEllipseInRect(context, CGRectMake(rect.right() - bottomRight.width() * 2,
    535                                                   rect.bottom() - bottomRight.height() * 2,
    536                                                   bottomRight.width() * 2, bottomRight.height() * 2));
    537    
    538     // Now add five rects (one for each edge rect in between the rounded corners and one for the interior).
    539     CGContextAddRect(context, CGRectMake(rect.x() + topLeft.width(), rect.y(),
    540                                          rect.width() - topLeft.width() - topRight.width(),
    541                                          max(topLeft.height(), topRight.height())));
    542     CGContextAddRect(context, CGRectMake(rect.x() + bottomLeft.width(),
    543                                          rect.bottom() - max(bottomLeft.height(), bottomRight.height()),
    544                                          rect.width() - bottomLeft.width() - bottomRight.width(),
    545                                          max(bottomLeft.height(), bottomRight.height())));
    546     CGContextAddRect(context, CGRectMake(rect.x(), rect.y() + topLeft.height(),
    547                                          max(topLeft.width(), bottomLeft.width()), rect.height() - topLeft.height() - bottomLeft.height()));
    548     CGContextAddRect(context, CGRectMake(rect.right() - max(topRight.width(), bottomRight.width()),
    549                                          rect.y() + topRight.height(),
    550                                          max(topRight.width(), bottomRight.width()), rect.height() - topRight.height() - bottomRight.height()));
    551     CGContextAddRect(context, CGRectMake(rect.x() + max(topLeft.width(), bottomLeft.width()),
    552                                          rect.y() + max(topLeft.height(), topRight.height()),
    553                                          rect.width() - max(topLeft.width(), bottomLeft.width()) - max(topRight.width(), bottomRight.width()),
    554                                          rect.height() - max(topLeft.height(), topRight.height()) - max(bottomLeft.height(), bottomRight.height())));
    555     CGContextClip(context);
    556475}
    557476
     
    704623    CGContextClip(context);
    705624    m_data->clip(path);
     625}
     626
     627void GraphicsContext::clipOut(const Path& path)
     628{
     629    if (paintingDisabled())
     630        return;
     631       
     632    CGContextBeginPath(platformContext());
     633    CGContextAddRect(platformContext(), CGContextGetClipBoundingBox(platformContext()));
     634    CGContextAddPath(platformContext(), path.platformPath());
     635    CGContextEOClip(platformContext());
    706636}
    707637
  • trunk/WebCore/platform/graphics/qt/GraphicsContextQt.cpp

    r21554 r21601  
    724724}
    725725
     726void GraphicsContext::clipOut(const Path& path)
     727{
     728    if (paintingDisabled())
     729        return;
     730       
     731    // FIXME: Implement
     732    notImplemented();
     733}
     734
    726735void GraphicsContext::translate(float x, float y)
    727736{
     
    794803}
    795804
    796 void GraphicsContext::addRoundedRectClip(const IntRect& rect, const IntSize& topLeft,
    797                                          const IntSize& topRight, const IntSize& bottomLeft,
    798                                          const IntSize& bottomRight)
    799 {
    800     if (paintingDisabled())
    801         return;
    802 
    803     // Need sufficient width and height to contain these curves.  Sanity check our top/bottom
    804     // values and our width/height values to make sure the curves can all fit.
    805     int requiredWidth = qMax(topLeft.width() + topRight.width(), bottomLeft.width() + bottomRight.width());
    806     if (requiredWidth > rect.width())
    807         return;
    808 
    809     int requiredHeight = qMax(topLeft.height() + bottomLeft.height(), topRight.height() + bottomRight.height());
    810     if (requiredHeight > rect.height())
    811         return;
    812 
    813     // Clip to our rect.
    814     clip(rect);
    815 
    816     // OK, the curves can fit.
    817     QPainterPath path;
    818 
    819     // Add the four ellipses to the path.  Technically this really isn't good enough, since we could end up
    820     // not clipping the other 3/4 of the ellipse we don't care about.  We're relying on the fact that for
    821     // normal use cases these ellipses won't overlap one another (or when they do the curvature of one will
    822     // be subsumed by the other).
    823     path.addEllipse(QRectF(rect.x(), rect.y(), topLeft.width() * 2, topLeft.height() * 2));
    824     path.addEllipse(QRectF(rect.right() - topRight.width() * 2, rect.y(),
    825                            topRight.width() * 2, topRight.height() * 2));
    826     path.addEllipse(QRectF(rect.x(), rect.bottom() - bottomLeft.height() * 2,
    827                            bottomLeft.width() * 2, bottomLeft.height() * 2));
    828     path.addEllipse(QRectF(rect.right() - bottomRight.width() * 2,
    829                            rect.bottom() - bottomRight.height() * 2,
    830                            bottomRight.width() * 2, bottomRight.height() * 2));
    831 
    832     int topLeftRightHeightMax = qMax(topLeft.height(), topRight.height());
    833     int bottomLeftRightHeightMax = qMax(bottomLeft.height(), bottomRight.height());
    834 
    835     int topBottomLeftWidthMax = qMax(topLeft.width(), bottomLeft.width());
    836     int topBottomRightWidthMax = qMax(topRight.width(), bottomRight.width());
    837 
    838     // Now add five rects (one for each edge rect in between the rounded corners and one for the interior).
    839     path.addRect(QRectF(rect.x() + topLeft.width(),
    840                         rect.y(),
    841                         rect.width() - topLeft.width() - topRight.width(),
    842                         topLeftRightHeightMax));
    843 
    844     path.addRect(QRectF(rect.x() + bottomLeft.width(), rect.bottom() - bottomLeftRightHeightMax,
    845                         rect.width() - bottomLeft.width() - bottomRight.width(), bottomLeftRightHeightMax));
    846 
    847     path.addRect(QRectF(rect.x(),
    848                         rect.y() + topLeft.height(),
    849                         topBottomLeftWidthMax,
    850                         rect.height() - topLeft.height() - bottomLeft.height()));
    851 
    852     path.addRect(QRectF(rect.right() - topBottomRightWidthMax,
    853                         rect.y() + topRight.height(),
    854                         topBottomRightWidthMax,
    855                         rect.height() - topRight.height() - bottomRight.height()));
    856 
    857     path.addRect(QRectF(rect.x() + topBottomLeftWidthMax,
    858                         rect.y() + topLeftRightHeightMax,
    859                         rect.width() - topBottomLeftWidthMax - topBottomRightWidthMax,
    860                         rect.height() - topLeftRightHeightMax - bottomLeftRightHeightMax));
    861 
    862     path.setFillRule(Qt::WindingFill);
    863     m_data->p().setClipPath(path, Qt::IntersectClip);
    864 }
    865 
    866805void GraphicsContext::concatCTM(const AffineTransform& transform)
    867806{
Note: See TracChangeset for help on using the changeset viewer.