Changeset 65782 in webkit


Ignore:
Timestamp:
Aug 22, 2010 12:30:48 AM (14 years ago)
Author:
ariya@webkit.org
Message:

[Qt] Layer approach to support generic shadow handling
https://bugs.webkit.org/show_bug.cgi?id=44380

Patch by Ariya Hidayat <ariya@sencha.com> on 2010-08-22
Reviewed by Dirk Schulze.

The pair beginShadowLayer and endShadowLayer creates a temporary image
where the caller can draw onto, using the returned QPainter. When
endShadowLayer is called, the temporary image will be filtered, using
the specified shadow color and blur radius, and drawn to the graphics
context.

  • platform/graphics/GraphicsContext.h:
  • platform/graphics/qt/ContextShadow.cpp:

(WebCore::ContextShadow::beginShadowLayer):
(WebCore::ContextShadow::endShadowLayer):

  • platform/graphics/qt/ContextShadow.h:
  • platform/graphics/qt/GraphicsContextQt.cpp:

(WebCore::GraphicsContext::fillRect):
(WebCore::GraphicsContext::contextShadow):

Location:
trunk/WebCore
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/WebCore/ChangeLog

    r65779 r65782  
     12010-08-22  Ariya Hidayat  <ariya@sencha.com>
     2
     3        Reviewed by Dirk Schulze.
     4
     5        [Qt] Layer approach to support generic shadow handling
     6        https://bugs.webkit.org/show_bug.cgi?id=44380
     7
     8        The pair beginShadowLayer and endShadowLayer creates a temporary image
     9        where the caller can draw onto, using the returned QPainter. When
     10        endShadowLayer is called, the temporary image will be filtered, using
     11        the specified shadow color and blur radius, and drawn to the graphics
     12        context.
     13
     14        * platform/graphics/GraphicsContext.h:
     15        * platform/graphics/qt/ContextShadow.cpp:
     16        (WebCore::ContextShadow::beginShadowLayer):
     17        (WebCore::ContextShadow::endShadowLayer):
     18        * platform/graphics/qt/ContextShadow.h:
     19        * platform/graphics/qt/GraphicsContextQt.cpp:
     20        (WebCore::GraphicsContext::fillRect):
     21        (WebCore::GraphicsContext::contextShadow):
     22
    1232010-08-21  Eric Carlson  <eric.carlson@apple.com>
    224
  • trunk/WebCore/platform/graphics/GraphicsContext.h

    r65661 r65782  
    4949#elif PLATFORM(QT)
    5050#include <QPainter>
     51namespace WebCore {
     52class ContextShadow;
     53}
    5154typedef QPainter PlatformGraphicsContext;
    5255#elif PLATFORM(WX)
     
    397400        QPen pen();
    398401        static QPainter::CompositionMode toQtCompositionMode(CompositeOperator op);
     402        ContextShadow* contextShadow();
    399403#endif
    400404
  • trunk/WebCore/platform/graphics/qt/ContextShadow.cpp

    r65776 r65782  
    268268}
    269269
    270 void ContextShadow::drawShadowRect(QPainter* p, const QRectF& rect)
    271 {
    272     if (type == NoShadow)
    273         return;
    274 
    275     if (type == BlurShadow) {
    276         QRectF shadowRect = rect.translated(offset);
    277 
    278         // We expand the area by the blur radius * 2 to give extra space
    279         // for the blur transition.
    280         int extra = blurRadius * 2;
    281         QRectF bufferRect = shadowRect.adjusted(-extra, -extra, extra, extra);
    282         QRect alignedBufferRect = bufferRect.toAlignedRect();
    283 
    284         QRect clipRect;
    285         if (p->hasClipping())
     270QPainter* ContextShadow::beginShadowLayer(QPainter* p, const QRectF &rect)
     271{
     272    // We expand the area by the blur radius * 2 to give extra space
     273    // for the blur transition.
     274    int extra = (type == BlurShadow) ? blurRadius * 2 : 0;
     275
     276    QRectF shadowRect = rect.translated(offset);
     277    QRectF bufferRect = shadowRect.adjusted(-extra, -extra, extra, extra);
     278    m_layerRect = bufferRect.toAlignedRect();
     279
     280    QRect clipRect;
     281    if (p->hasClipping())
    286282#if QT_VERSION >= QT_VERSION_CHECK(4, 8, 0)
    287             clipRect = p->clipBoundingRect();
     283        clipRect = p->clipBoundingRect();
    288284#else
    289             clipRect = p->clipRegion().boundingRect();
     285        clipRect = p->clipRegion().boundingRect();
    290286#endif
    291         else
    292             clipRect = p->transform().inverted().mapRect(p->window());
    293 
    294         if (!clipRect.contains(alignedBufferRect)) {
    295 
    296             // No need to have the buffer larger that the clip.
    297             alignedBufferRect = alignedBufferRect.intersected(clipRect);
    298             if (alignedBufferRect.isEmpty())
    299                 return;
    300 
    301             // We adjust again because the pixels at the borders are still
    302             // potentially affected by the pixels outside the buffer.
    303             alignedBufferRect.adjust(-extra, -extra, extra, extra);
    304         }
    305 
    306         ShadowBuffer* shadowBuffer = scratchShadowBuffer();
    307         QImage* shadowImage = shadowBuffer->scratchImage(alignedBufferRect.size());
    308         QPainter shadowPainter(shadowImage);
    309 
    310         shadowPainter.fillRect(shadowRect.translated(-alignedBufferRect.topLeft()), color);
    311         shadowPainter.end();
    312 
    313         shadowBlur(*shadowImage, blurRadius, color);
    314 
    315         p->drawImage(alignedBufferRect.topLeft(), *shadowImage);
    316 
    317         shadowBuffer->schedulePurge();
    318 
    319         return;
     287    else
     288        clipRect = p->transform().inverted().mapRect(p->window());
     289
     290    if (!clipRect.contains(m_layerRect)) {
     291
     292        // No need to have the buffer larger than the clip.
     293        m_layerRect = m_layerRect.intersected(clipRect);
     294        if (m_layerRect.isEmpty())
     295            return 0;
     296
     297        // We adjust again because the pixels at the borders are still
     298        // potentially affected by the pixels outside the buffer.
     299        if (type == BlurShadow)
     300            m_layerRect.adjust(-extra, -extra, extra, extra);
    320301    }
    321302
    322     p->fillRect(rect.translated(offset), color);
    323 }
    324 
    325 
    326 }
     303    ShadowBuffer* shadowBuffer = scratchShadowBuffer();
     304    QImage* shadowImage = shadowBuffer->scratchImage(m_layerRect.size());
     305    m_layerImage = QImage(*shadowImage);
     306
     307    m_layerPainter = new QPainter;
     308    m_layerPainter->begin(&m_layerImage);
     309    m_layerPainter->translate(offset);
     310
     311    // The origin is now the top left corner of the scratch image.
     312    m_layerPainter->translate(-m_layerRect.topLeft());
     313
     314    return m_layerPainter;
     315}
     316
     317void ContextShadow::endShadowLayer(QPainter* p)
     318{
     319    m_layerPainter->end();
     320    delete m_layerPainter;
     321    m_layerPainter = 0;
     322
     323    if (type == BlurShadow)
     324        shadowBlur(m_layerImage, blurRadius, color);
     325
     326    p->drawImage(m_layerRect.topLeft(), m_layerImage);
     327
     328    scratchShadowBuffer()->schedulePurge();
     329}
     330
     331}
  • trunk/WebCore/platform/graphics/qt/ContextShadow.h

    r65425 r65782  
    5959    void clear();
    6060
    61     // Draws the shadow for colored rectangle (can't be filled with pattern
    62     // or gradient) according to the shadow parameters.
    63     // Note: 'rect' specifies the rectangle which casts the shadow,
    64     // NOT the bounding box of the shadow.
    65     void drawShadowRect(QPainter* p, const QRectF& rect);
     61    // The pair beginShadowLayer and endShadowLayer creates a temporary image
     62    // where the caller can draw onto, using the returned QPainter. This
     63    // QPainter instance must be used only to draw between the call to
     64    // beginShadowLayer and endShadowLayer.
     65    //
     66    // Note: multiple/nested shadow layer is NOT allowed.
     67    //
     68    // The current clip region will be used to optimize the size of the
     69    // temporary image. Thus, the original painter should not change any
     70    // clipping until endShadowLayer.
     71    // If the shadow will be completely outside the clipping region,
     72    // beginShadowLayer will return 0.
     73    //
     74    // The returned QPainter will have the transformation matrix and clipping
     75    // properly initialized to start doing the painting (no need to account
     76    // for the shadow offset), however it will not have the same render hints,
     77    // pen, brush, etc as the passed QPainter. This is intentional, usually
     78    // shadow has different properties than the shape which casts the shadow.
     79    //
     80    // Once endShadowLayer is called, the temporary image will be drawn
     81    // with the original painter. If blur radius is specified, the shadow
     82    // will be filtered first.
     83    QPainter* beginShadowLayer(QPainter* p, const QRectF& rect);
     84    void endShadowLayer(QPainter* p);
    6685
     86private:
     87    QRect m_layerRect;
     88    QImage m_layerImage;
     89    QPainter* m_layerPainter;
    6790};
    6891
  • trunk/WebCore/platform/graphics/qt/GraphicsContextQt.cpp

    r65655 r65782  
    696696    m_data->solidColor.setColor(color);
    697697    QPainter* p = m_data->p();
    698 
    699     if (m_data->hasShadow())
    700         m_data->shadow.drawShadowRect(p, rect);
    701 
    702     p->fillRect(rect, m_data->solidColor);
     698    QRectF normalizedRect = rect.normalized();
     699
     700    if (m_data->hasShadow()) {
     701        ContextShadow* shadow = contextShadow();
     702
     703        if (shadow->type != ContextShadow::BlurShadow) {
     704            // We do not need any layer for simple shadow.
     705            p->fillRect(normalizedRect.translated(shadow->offset), shadow->color);
     706        } else {
     707            QPainter* shadowPainter = shadow->beginShadowLayer(p, normalizedRect);
     708            if (shadowPainter) {
     709                shadowPainter->setCompositionMode(QPainter::CompositionMode_Source);
     710                shadowPainter->fillRect(normalizedRect, shadow->color);
     711                shadow->endShadowLayer(p);
     712            }
     713        }
     714    }
     715
     716    p->fillRect(normalizedRect, m_data->solidColor);
    703717}
    704718
     
    740754{
    741755    return &m_data->currentPath;
     756}
     757
     758ContextShadow* GraphicsContext::contextShadow()
     759{
     760    return &m_data->shadow;
    742761}
    743762
Note: See TracChangeset for help on using the changeset viewer.